From patchwork Wed Sep 18 01:26:29 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163640 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="dMELXAWf"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2M92Jwjz9s4Y for ; Wed, 18 Sep 2019 11:24:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id DB466C21EA8; Wed, 18 Sep 2019 01:24:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id BEAC8C21EA8; Wed, 18 Sep 2019 01:23:49 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D120EC21E9F; Wed, 18 Sep 2019 01:23:39 +0000 (UTC) Received: from mail-pf1-f176.google.com (mail-pf1-f176.google.com [209.85.210.176]) by lists.denx.de (Postfix) with ESMTPS id BA59EC21ED6 for ; Wed, 18 Sep 2019 01:23:33 +0000 (UTC) Received: by mail-pf1-f176.google.com with SMTP id y22so3263514pfr.3 for ; Tue, 17 Sep 2019 18:23:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=M+k80Uksgg/MXq73rs8flaP7BNyHrhrvhGOUrBVIfVE=; b=dMELXAWfvWLiclEBamU36gJ/TcEmt4UBAM2XOCSM8iQYGW3l1nLLTKG4qfT3q2cUZR eFeGaNTCK2g71iO6rdbTUYVlMwEZTy09Zu46S9C6f+M9x5Db5npY6JxOYiZLP9MfQtPI 0w7+5nisIeAvgvDMARnF3/E4UuJvoH/2s9vTjnG8OsVfCEWHQNpkLvLpExgDL7tZmp5m mJj3o9FEhV6aMKjNhYMZARkGjaYJUwhX3QLFKCBnxnSq2q+Xsnil5m0fj/lojHdQ5QwC dNDwWSQBPok+Y91ZXzRHWddNqwpUU4XFNXXzgLdklh6ACaBxpSqdHkya9Tfs4m88UtpZ fxIQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=M+k80Uksgg/MXq73rs8flaP7BNyHrhrvhGOUrBVIfVE=; b=IPZMFrOAnvvK+ovvfPLxas1L1PNIqaFoUNicBltrcciySAxmQXK7BEbMN2a4XMbxFM j0FF3DpgTHAR2Eu2nkJobiG6tToUthlJcitWbijSUfpGKMIwfsN3SMWULGjiYe2BH6uK wemCRT4VRi4sEXwtNPy9GNXojtIolumi0dZ2qtdbT/y/5KOynyJyDW7S+ktiaqmU1qDc tCOBJ5BaYWMsLuP/MjIpwriFA5j0kyURUkwW5PY+DKqPQx5PLeztMBwXYNxAwhyxITWn QtI0AvEcfpgXuomUoWNqEdMii/4+RTcN3J6Il0w+ZSXS2qFFZiCoyzvQXoijCUabdqfK 9GnQ== X-Gm-Message-State: APjAAAXEzRW/Kzln70Qr89F5Dew/t3eHZ2Of98e9IgCKfnn4hq9VTVoH e4lWoLau0b2QsbVoGH4U0duh5Q== X-Google-Smtp-Source: APXvYqzYjWq1319dlGOaF0a0DnOKr9Cb9ldba4OyDs1pxMTPW4fyFa7sqOViJomxmsog1W59+v/yVw== X-Received: by 2002:aa7:9307:: with SMTP id 7mr1411238pfj.224.1568769812357; Tue, 17 Sep 2019 18:23:32 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id o42sm426086pjo.32.2019.09.17.18.23.31 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:31 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:29 +0900 Message-Id: <20190918012643.25192-2-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 01/15] lib: charset: add u16_strcmp() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" u16 version of strcmp(): u16_strncmp() works like u16_strcmp() but only at most n characters (in u16) are compared. This function will be used in my UEFI secure boot patch. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- include/charset.h | 15 +++++++++++++++ lib/charset.c | 25 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/include/charset.h b/include/charset.h index 020f8a90df07..fde6bddbc2fb 100644 --- a/include/charset.h +++ b/include/charset.h @@ -168,6 +168,21 @@ s32 utf_to_lower(const s32 code); */ s32 utf_to_upper(const s32 code); +/* + * u16_strncmp() - compare two u16 string + * + * @s1: first string to compare + * @s2: second string to compare + * @n: maximum number of u16 to compare + * Return: 0 if the first n u16 are the same in s1 and s2 + * < 0 if the first different u16 in s1 is less than the + * corresponding u16 in s2 + * > 0 if the first different u16 in s1 is greater than the + * corresponding u16 in s2 + */ +int u16_strncmp(const u16 *s1, const u16 *s2, size_t n); +#define u16_strcmp(s1, s2) u16_strncmp((s1), (s2), SIZE_MAX) + /** * u16_strlen - count non-zero words * diff --git a/lib/charset.c b/lib/charset.c index 72d745da4f4e..1c6a7f693de4 100644 --- a/lib/charset.c +++ b/lib/charset.c @@ -335,6 +335,31 @@ s32 utf_to_upper(const s32 code) return ret; } +/* + * u16_strncmp() - compare two u16 string + * + * @s1: first string to compare + * @s2: second string to compare + * @n: maximum number of u16 to compare + * Return: 0 if the first n u16 are the same in s1 and s2 + * < 0 if the first different u16 in s1 is less than the + * corresponding u16 in s2 + * > 0 if the first different u16 in s1 is greater than the + * corresponding u16 in s2 + */ +int u16_strncmp(const u16 *s1, const u16 *s2, size_t n) +{ + int ret = 0; + + for (; n; --n, ++s1, ++s2) { + ret = *s1 - *s2; + if (ret || !*s1) + break; + } + + return ret; +} + size_t u16_strlen(const void *in) { const char *pos = in; From patchwork Wed Sep 18 01:26:30 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163639 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ygFDslzR"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2M039T2z9sNF for ; Wed, 18 Sep 2019 11:24:12 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id BD3C4C21E89; Wed, 18 Sep 2019 01:23:49 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E2D6FC21E76; Wed, 18 Sep 2019 01:23:47 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 600DEC21E56; Wed, 18 Sep 2019 01:23:41 +0000 (UTC) Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by lists.denx.de (Postfix) with ESMTPS id 99AA8C21DFB for ; Wed, 18 Sep 2019 01:23:36 +0000 (UTC) Received: by mail-pf1-f173.google.com with SMTP id q10so3272568pfl.0 for ; Tue, 17 Sep 2019 18:23:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JswXq8DQKSopmta/bIQVN4a+zloodOOxIEm29A9FVJ8=; b=ygFDslzRL7f1g68LM/61q0FX9ftemVbIh0zce1QQgUMzt/CZu8iV/ETDIqCuhegjrp wS+m/wvsHp7vEuouCgo5c+9CFVoCsZ3zaCKnAZuIDRBBFHcgpE06y8B1Of9xjuzdZMad oQZnGLCZj4bkzjHU3xr09MPhE8I66unx8e8Ot/03tBaaU8tzL/F+c4LKpLbsXhqRaT8r 8pg+qbhUyNEE1jE8wZJatxTKQiNkbleyFlBG3NBPkKpTtmOfCT6mP8OOBjmi7PmwzlI1 /wXqlCWCjxuYw4x24bzz2N4LtSeiz8lyD10Re3Q+YUAOIibxwNVbGQcR3GZkAjCOnhvU +c3w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JswXq8DQKSopmta/bIQVN4a+zloodOOxIEm29A9FVJ8=; b=A8VUI8iZ1syIWoflZQgyyFIyKULDOov1MADCLZMhrEGC90RnJlDZulMCYgkCN4fwUv Lnad79S5NDL+DE+TFm/EcnASTJLlY/hlMGKULiSjZ3Cp+b8Y3LdhUXLwjcNwqH0svkoj u/2mCUDRPjiyiYCSKlAlR+3fynH2IK4akDF/Gbu5FkCEkAvDavc9LUaWkxHHvtvEbsBk QiTBnS95GKBr4e0f5CwsdfMdLD5RbLMbIQInmXVPxtGtZyDUAfT9Ql1XpfAzOB66Jxr3 32o6J5CJQhToDFijNUbzIYN5GPivlqArNJoiMTA8XsN96CAFPE55XYYsnI7JxB/q2avg i2Lg== X-Gm-Message-State: APjAAAUXyz+ohNVQFsLelfnxpFKqQ/apv4tOpbdz9E5DxcMJ6aVQs/sN sZ1EoSioR3kb1xOwjxS6Hgwwh66ztN4= X-Google-Smtp-Source: APXvYqzwN29WBraGCLLYeJI4nwWiAkNYVOQF06BUsDMhH3Ak010HnTshT0oJTjvv6Be+haXoa0bRGA== X-Received: by 2002:a62:1b85:: with SMTP id b127mr1376458pfb.56.1568769815308; Tue, 17 Sep 2019 18:23:35 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id u7sm3313380pgr.94.2019.09.17.18.23.34 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:34 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:30 +0900 Message-Id: <20190918012643.25192-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 02/15] test: add tests for u16_strcmp() X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" New seven test cases for u16_strcmp() are added under Unicode unit test, which should be executed by "ut unicode" command. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- test/unicode_ut.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/unicode_ut.c b/test/unicode_ut.c index 1ccd36e7c9e8..8875cdc6b2f5 100644 --- a/test/unicode_ut.c +++ b/test/unicode_ut.c @@ -567,6 +567,19 @@ static int unicode_test_utf_to_upper(struct unit_test_state *uts) } UNICODE_TEST(unicode_test_utf_to_upper); +static int unicode_test_u16_strncmp(struct unit_test_state *uts) +{ + ut_assert(u16_strncmp(L"abc", L"abc", 3) == 0); + ut_assert(u16_strncmp(L"abcdef", L"abcghi", 3) == 0); + ut_assert(u16_strncmp(L"abcdef", L"abcghi", 6) < 0); + ut_assert(u16_strncmp(L"abcghi", L"abcdef", 6) > 0); + ut_assert(u16_strcmp(L"abc", L"abc") == 0); + ut_assert(u16_strcmp(L"abcdef", L"deghi") < 0); + ut_assert(u16_strcmp(L"deghi", L"abcdef") > 0); + return 0; +} +UNICODE_TEST(unicode_test_u16_strncmp); + int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test); From patchwork Wed Sep 18 01:26:31 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163643 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="FR8CDKSv"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2PT3l03z9s4Y for ; Wed, 18 Sep 2019 11:26:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 23E63C21E7E; Wed, 18 Sep 2019 01:24:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id DEC81C21E76; Wed, 18 Sep 2019 01:24:03 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 796A9C21EC3; Wed, 18 Sep 2019 01:23:44 +0000 (UTC) Received: from mail-pg1-f196.google.com (mail-pg1-f196.google.com [209.85.215.196]) by lists.denx.de (Postfix) with ESMTPS id 7118BC21EC2 for ; Wed, 18 Sep 2019 01:23:39 +0000 (UTC) Received: by mail-pg1-f196.google.com with SMTP id m29so3000022pgc.3 for ; Tue, 17 Sep 2019 18:23:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=nGQq0KcIOwqd2uGX3jZqZ7hg04vXNtmfymcA5EcjKrw=; b=FR8CDKSvik3CoPSxIA03dDZAeV8en6WLZp/enoRleaZLsn1e7S+pwpFtJo4uBtElMk QFtAHNME+My5zQ7yCJBiFZ3E5Nsw1Jbp9CnsupUX1UnlzhW+SJLLxxpVomff6tTRr45m O+rKLr3+aN9K93WtPiqEypzaX7vCYwwxSpnfpiIBxobLHJ2T5C3E03hs7rC+nwTYE/F7 swUbc1Gc/UlrlsZFCjYZXoIxAP/oxk9FU8T6rxlkDnnY5/BA9H6EC5s1qVHfN93CC6zA I4m/4kdsaJD//NRuaY08coeiYhcXtHYyO202zcjpepsuRqOcKt+hKJHZ2M78hgTVHW7w cY/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=nGQq0KcIOwqd2uGX3jZqZ7hg04vXNtmfymcA5EcjKrw=; b=B2/Iaemo1TlpXi+Kt6SKAHXeCtgX1GZQjrAYcGOAHZfaS94YY49sRC6+taKcGQNzy6 uL7ui3MjHX/LmJW2p8l/ecv+227ZyFBeBvE+uxiPpYJAD51y0usHgkmeLM9Ma9FETNds 24dWYEqAyXtUHPRzqm8S0rMGmMbWaudWoJHwVl6lBM+IhYJioPJj2rWpr1yUmNg4mW+M Crn76bsLh/5B5wcl+ZbDSp3QsXIP9Z6bp870To2xrhR77kxSLN9cf1f+z+cZdhCz03WX +zKqe74ZC2chgNajhyUfwWl6uc5bEo0cqjbS+56vI/wSZpoxI3+MDIzgDiqJdB30UBiu uqQQ== X-Gm-Message-State: APjAAAXFbFBx6/lhkjoSOI8ig7hbvEtryqhZtK4U24mkmnGRDQjy2C5h ZoVqaT1i4IxRSqJU8Du/USPfhw== X-Google-Smtp-Source: APXvYqw6fZ6btiSqWWpmu+PDGNOlPmQT2L9o/o8SZlcFV8JHS6502FrPO9Xp99DN0gki0XWSaht6eQ== X-Received: by 2002:a65:5c02:: with SMTP id u2mr1582235pgr.367.1568769818061; Tue, 17 Sep 2019 18:23:38 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id ck13sm372174pjb.29.2019.09.17.18.23.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:37 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:31 +0900 Message-Id: <20190918012643.25192-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 03/15] include: pe.h: add image-signing-related definitions X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The index (IMAGE_DIRECTORY_ENTRY_CERTTABLE) in a table points to a region containing authentication information (image's signature) in PE format. WIN_CERTIFICATE structure defines an embedded signature format. Those definitions will be used in my UEFI secure boot patch. Signed-off-by: AKASHI Takahiro --- include/pe.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/include/pe.h b/include/pe.h index bff3b0aa7a6c..650478ca78af 100644 --- a/include/pe.h +++ b/include/pe.h @@ -155,6 +155,7 @@ typedef struct _IMAGE_SECTION_HEADER { uint32_t Characteristics; } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; +#define IMAGE_DIRECTORY_ENTRY_CERTTABLE 4 #define IMAGE_DIRECTORY_ENTRY_BASERELOC 5 typedef struct _IMAGE_BASE_RELOCATION @@ -252,4 +253,19 @@ typedef struct _IMAGE_RELOCATION #define IMAGE_REL_AMD64_PAIR 0x000F #define IMAGE_REL_AMD64_SSPAN32 0x0010 +/* certificate appended to PE image */ +typedef struct _WIN_CERTIFICATE { + uint32_t dwLength; + uint16_t wRevision; + uint16_t wCertificateType; + uint8_t bCertificate[]; +} WIN_CERTIFICATE, *LPWIN_CERTIFICATE; + +#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002 +#define WIN_CERT_TYPE_EFI_OKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +#define WIN_CERT_REVISION_1_0 0x0100 +#define WIN_CERT_REVISION_2_0 0x0200 + #endif /* _PE_H */ From patchwork Wed Sep 18 01:26:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163642 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="F03x6f3j"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2PN5FCcz9s4Y for ; Wed, 18 Sep 2019 11:26:16 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 443A7C21E9F; Wed, 18 Sep 2019 01:24:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 75F4AC21E50; Wed, 18 Sep 2019 01:24:06 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id CCA32C21E5B; Wed, 18 Sep 2019 01:23:46 +0000 (UTC) Received: from mail-pg1-f170.google.com (mail-pg1-f170.google.com [209.85.215.170]) by lists.denx.de (Postfix) with ESMTPS id 5F2FFC21DFB for ; Wed, 18 Sep 2019 01:23:42 +0000 (UTC) Received: by mail-pg1-f170.google.com with SMTP id n9so3011036pgc.1 for ; Tue, 17 Sep 2019 18:23:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ZaJHSAn1YsfUj2jTL2rmxcmOd/yNAZycnFEGXJJsriI=; b=F03x6f3jvvKB95mNyKe1bxV3pzEF5lIZ3YUKWSucVrG/xn/66O2lwzaeM4p++xMMvK m2ylV44rPSQVXua/9/qEuEWIfwba6q6FYfKTxCXqFzf3o6pTEO3gDKm3d54VwoBiAx2G NPzYGKK++mb4E2BWdEZAhVmFNqXGwnpuAYcxQzHfkjSaPXs8xbFJdZArGM3LT3A2fG0S KlKArMjdSu7eD48WWzjEwuXkjyY/lQsXycc2tAJzlDqF7HEIkh6kVHsCCMe/gDaaKWZe h/yn4s16vm5T56fqAvVknF3FVwrx4UXrpxa7+99vIgFvdnuKAVMv4Mc8SxWfy40SQPtD HB2w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ZaJHSAn1YsfUj2jTL2rmxcmOd/yNAZycnFEGXJJsriI=; b=h40FmgtASCh/EycA2hYoc8bivWhT5Zg5HmZFBl70WgrYhl4ygkigpQb0zhPxFJ0iia dkRGJqtuFvVM/idSGLjWLjzrCWlubNZBm1EjHBdwFVYhzTSLZ/c4EPhdwisUDbuPhl+p MpBMNhiZmMR/fmNRaeeI09lOFm+w234IEdOF75DvgX+urFN55+O5s5MQq3wj3/u9ijVm 3Gvk3wt6mlmMCEj1FbJkl9+oG4tZewbiQLGtexOvEBe6twKKUHFe+mpDiYaZOlz2jhPq qnDcpjmUPJqjsNXifRV7Fr0L7TFy07OaGRU7YkHDnKw1xtCbNSQjfd8IlNzCBk6aZJ8Y cimg== X-Gm-Message-State: APjAAAXwQnbQMRZ0wcyw57rFXcA5DTvsNs8mR0XYO8AnsNTrZxMS00t0 pmQUK+rjbkNtCFaa9uZ3yLz1Qw== X-Google-Smtp-Source: APXvYqw6b9BLLvAmYyz/EfPMDd0jDDp1V+5IBo9aM0alae0It0bDOZU+pLqyf1DsAjJioLnojk3M/g== X-Received: by 2002:a63:db49:: with SMTP id x9mr1632975pgi.44.1568769820927; Tue, 17 Sep 2019 18:23:40 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id n66sm6579075pfn.90.2019.09.17.18.23.40 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:40 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:32 +0900 Message-Id: <20190918012643.25192-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 04/15] include: image.h: add key info to image_sign_info X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" For FIT verification, all the properties of a public key come from "control fdt" pointed to by fdt_blob. In UEFI secure boot, on the other hand, a public key is located and retrieved from dedicated signature database stored as UEFI variables. Added two fields may hold values of a public key if fdt_blob is NULL, and will be used in rsa_verify_with_pkey() to verify a signature in UEFI sub-system. Signed-off-by: AKASHI Takahiro --- include/image.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/image.h b/include/image.h index 97b6a82d9754..685f5181c829 100644 --- a/include/image.h +++ b/include/image.h @@ -1136,6 +1136,8 @@ struct image_sign_info { struct checksum_algo *checksum; /* Checksum algorithm information */ struct padding_algo *padding; /* Padding algorithm information */ struct crypto_algo *crypto; /* Crypto algorithm information */ + const void *key; + int keylen; const void *fdt_blob; /* FDT containing public keys */ int required_keynode; /* Node offset of key to use: -1=any */ const char *require_keys; /* Value for 'required' property */ From patchwork Wed Sep 18 01:26:33 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163645 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="s+l94L+J"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2RL3d47z9s4Y for ; Wed, 18 Sep 2019 11:27:58 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 250CDC21EE4; Wed, 18 Sep 2019 01:24:11 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 51312C21E8A; Wed, 18 Sep 2019 01:24:01 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D1CC2C21E76; Wed, 18 Sep 2019 01:23:46 +0000 (UTC) Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by lists.denx.de (Postfix) with ESMTPS id 3B9AAC21E35 for ; Wed, 18 Sep 2019 01:23:45 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id u72so2977849pgb.10 for ; Tue, 17 Sep 2019 18:23:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=AJLRjIYANGSmDo/T5VxQbVaojrTzYkPWK12kGNG0Ugg=; b=s+l94L+JkYlPmlUqvpad1yvFMtoIu4OPaqryhRQoQ0JTnTRPgsT1A9K7qXqMqny56/ XVF07No+iB/8I5cKCLAv5/CT+J+buyUMdinMdEX3PPFfzBkkSydSGxkFLGn3IZmH6D2x 9trDPQWmwfaSX0uLxJb3icnEdJJIxDfXnS1xSUQq0XUoW0dBilt6N8BucRwvNIRXQ0re h6pKsI+3m/I5lPXdWx2HfOqIVArTUDoJH/6lM3ayc7/cWk1p3wF96tI1AXfnXa+IKIsZ PugsLslVrLpzzVUozlZet5TLsOwgEr/u1YuRYX265ko56c5kP+uzZIBaptWqyfpotNAI IXCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=AJLRjIYANGSmDo/T5VxQbVaojrTzYkPWK12kGNG0Ugg=; b=Kc7C/IArYqEkAHPBRgvoyy+9KbDoQDZMIWMiVGziug/KOMAsfjkInI7dKJ2eYazZF8 mtzIqChVOtpyUaLe9YxeOr38BmbBdPyJExO+qFZPgzbXjioH0QP32OPRINjctOpc4H8n OeIWEgglENtMfWe72vy+6Ceqj2d6yYvZ3z/DItQlyQbmh6hLFB+c0S75JhuYeiocqNGC yWZcRIvs7eDi/3eHrOFIICvaI0p+Kqu7wEsDUQHy6w64h/jec22c3vmBtTUHKO7dFHAM wlxBOMAFL6Q3UuKAm8fVyhKO80HvEXaEDulU0+kTuPXrnJL9aDu+ra8xWjI1hUFQnqvF KsyQ== X-Gm-Message-State: APjAAAXkflOkEFCACUBh0N/nQpw7QWR0SpH8H7/e4nIfmzUicPXTNOw0 UIcln63P/o7Fa/0AkX4j8Vg1EA== X-Google-Smtp-Source: APXvYqwV5blRtik4VjvU5CmCiHMjIGml53HaH32lvAL1wVYefBzUPaZ8CoM4MKxWI0OVygGvKNSv0w== X-Received: by 2002:a63:5807:: with SMTP id m7mr1578046pgb.371.1568769823803; Tue, 17 Sep 2019 18:23:43 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id k3sm3320646pgl.9.2019.09.17.18.23.43 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:43 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:33 +0900 Message-Id: <20190918012643.25192-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 05/15] include: image.h: export hash algorithm helper functions X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" This commit allows us to use common/image-sig.c even if CONFIG_FIT is disabled but CONFIG_EFI_LOADER is enabled. Signed-off-by: AKASHI Takahiro Reviewed-by: Simon Glass --- include/image.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/include/image.h b/include/image.h index 685f5181c829..c9fe1d8eaed8 100644 --- a/include/image.h +++ b/include/image.h @@ -53,7 +53,7 @@ struct fdt_region; #endif /* USE_HOSTCC */ -#if IMAGE_ENABLE_FIT +#if IMAGE_ENABLE_FIT || defined(CONFIG_EFI_SECURE_BOOT) #include #include #include @@ -86,13 +86,14 @@ struct fdt_region; #endif #if defined(CONFIG_FIT_ENABLE_SHA256_SUPPORT) || \ - defined(CONFIG_SPL_SHA256_SUPPORT) + defined(CONFIG_SPL_SHA256_SUPPORT) || \ + defined(CONFIG_EFI_SECURE_BOOT) #define IMAGE_ENABLE_SHA256 1 #else #define IMAGE_ENABLE_SHA256 0 #endif -#endif /* IMAGE_ENABLE_FIT */ +#endif /* IMAGE_ENABLE_FIT || defined(CONFIG_EFI_SECURE_BOOT) */ #ifdef CONFIG_SYS_BOOT_GET_CMDLINE # define IMAGE_BOOT_GET_CMDLINE 1 @@ -1085,6 +1086,7 @@ int fit_conf_get_prop_node(const void *fit, int noffset, int fit_check_ramdisk(const void *fit, int os_noffset, uint8_t arch, int verify); +#endif /* IMAGE_ENABLE_FIT */ int calculate_hash(const void *data, int data_len, const char *algo, uint8_t *value, int *value_len); @@ -1143,7 +1145,6 @@ struct image_sign_info { const char *require_keys; /* Value for 'required' property */ const char *engine_id; /* Engine to use for signing */ }; -#endif /* Allow struct image_region to always be defined for rsa.h */ /* A part of an image, used for hashing */ struct image_region { @@ -1151,7 +1152,7 @@ struct image_region { int size; }; -#if IMAGE_ENABLE_FIT +#if IMAGE_ENABLE_FIT || defined(CONFIG_EFI_SECURE_BOOT) #if IMAGE_ENABLE_VERIFY # include @@ -1252,7 +1253,9 @@ struct crypto_algo *image_get_crypto_algo(const char *full_name); * @return pointer to algorithm information, or NULL if not found */ struct padding_algo *image_get_padding_algo(const char *name); +#endif /* IMAGE_ENABLE_FIT || defined(CONFIG_EFI_SECURE_BOOT) */ +#if IMAGE_ENABLE_FIT /** * fit_image_verify_required_sigs() - Verify signatures marked as 'required' * @@ -1328,7 +1331,7 @@ static inline int fit_image_check_target_arch(const void *fdt, int node) #define fit_unsupported(msg) #define fit_unsupported_reset(msg) #endif /* CONFIG_FIT_VERBOSE */ -#endif /* CONFIG_FIT */ +#endif /* IMAGE_ENABLE_FIT */ #if defined(CONFIG_ANDROID_BOOT_IMAGE) struct andr_img_hdr; From patchwork Wed Sep 18 01:26:34 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163652 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="HU1bkF4e"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Ws6xy9z9s4Y for ; Wed, 18 Sep 2019 11:31:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 9C73CC21EF2; Wed, 18 Sep 2019 01:26:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 45B26C21F00; Wed, 18 Sep 2019 01:25:13 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 4E689C21E7D; Wed, 18 Sep 2019 01:23:51 +0000 (UTC) Received: from mail-pg1-f195.google.com (mail-pg1-f195.google.com [209.85.215.195]) by lists.denx.de (Postfix) with ESMTPS id 47DB6C21DB5 for ; Wed, 18 Sep 2019 01:23:48 +0000 (UTC) Received: by mail-pg1-f195.google.com with SMTP id u17so2990552pgi.6 for ; Tue, 17 Sep 2019 18:23:48 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/WUJ5Lpc9tWEsTQYEUVBWcMfBbKcpdSH1ruiElEaCQ0=; b=HU1bkF4evC7xFNyiYrONAixsVY3uQ5rjccVMyOTLz50QiOEL1XNZH3SITDCPDvedya gHgy0dDlvO0CZtUIHDdRmGoQKd2IJ2l1eUkvAnvSJmFNUgO3DB1xcHrOegf0id43UWWQ lSJ27Bcn4KmZW6ra8LGudF6F4CqSBSaJxr07Vuhcnbro4nxOxh4F92GlrltesW7aXkQf HH+A2WdvIdUlHMjOkWTYir6q3+yCLFZKqJTuwfDnYLvCI9L3RGxo1nhFT9ArVd2m4iJ+ 892A0bH9P5L+zB17gA7U0MiQy9hB1RPfa+k5XMh+iNvA2CR6H9CC2HiKEG30QhBD+4ZV WLJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/WUJ5Lpc9tWEsTQYEUVBWcMfBbKcpdSH1ruiElEaCQ0=; b=GaRG1bNIN2hsomWQL8zVOwElE65vr+jwJeUcDWbZNoMm2t9DU+K8Z3hDWJ0jp9izYD pp9UuGu7wxXgOszB8dt/dP5Xz6x0Qhut8m5W6TqlaOhF2CjfykyFyekmrmeUC2j0Hho9 dvjc6Gk0ORRwLW0ZXo3/wPDEqP9i5RYEkyZQzRLcG17V0P/qAAUnBGy1Fl9b5YqZvLxj nZVPhZptWAgVzIF27kBXK+qxUl3aaPnlTqH2/RbyDCzEpfjdXj4i9UfiShVwrnIHJ4wm KoQ3PH6GnvaqDoWs3t1J1Ggp6RL+O80FgcIkC97TXN4KrgadgsrU/9usszQVv7RvvlEg UybQ== X-Gm-Message-State: APjAAAXJ3lXWn0+6TFMK4hfEChUw2TV4xJg728oyWu2gh2/ESeXgFcL+ lAbKZpvO48sJINTJueHUC2bLjg== X-Google-Smtp-Source: APXvYqwGUpteiMBbJroh6e3iMOB61KaTfiz35EPYbeKnXKPQ3s5ZZDMqGyTbydMWyczXdzea6BfQsQ== X-Received: by 2002:a63:3196:: with SMTP id x144mr1625533pgx.284.1568769826815; Tue, 17 Sep 2019 18:23:46 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id w6sm9074032pfw.84.2019.09.17.18.23.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:46 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:34 +0900 Message-Id: <20190918012643.25192-7-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 06/15] secure boot: rename CONFIG_SECURE_BOOT X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The configuration, CONFIG_SECURE_BOOT, was scattered among different architecture directories for different implementation. This will prevent UEFI secure boot from being added later. So let's rename them, giving each implementation to different configuration option. CONFIG_SECURE_BOOT still remains not to break existing implicit dependency. Signed-off-by: AKASHI Takahiro --- Kconfig | 7 +++++++ arch/arm/cpu/armv7/ls102xa/Kconfig | 3 ++- arch/arm/cpu/armv8/fsl-layerscape/Kconfig | 3 ++- arch/arm/mach-imx/Kconfig | 3 ++- arch/powerpc/cpu/mpc85xx/Kconfig | 3 ++- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Kconfig b/Kconfig index 1f0904f7045e..c11fc102a7d4 100644 --- a/Kconfig +++ b/Kconfig @@ -282,6 +282,13 @@ config SYS_LDSCRIPT endmenu # General setup +config SECURE_BOOT + bool "Secure Boot" + imply SHA256 + help + Enable Secure Boot feature. The actual behavior may vary + from architecture to architecture. + menu "Boot images" config ANDROID_BOOT_IMAGE diff --git a/arch/arm/cpu/armv7/ls102xa/Kconfig b/arch/arm/cpu/armv7/ls102xa/Kconfig index 94fa68250ddf..ce1bc580d23d 100644 --- a/arch/arm/cpu/armv7/ls102xa/Kconfig +++ b/arch/arm/cpu/armv7/ls102xa/Kconfig @@ -50,8 +50,9 @@ config MAX_CPUS cores, count the reserved ports. This will allocate enough memory in spin table to properly handle all cores. -config SECURE_BOOT +config FSL_ARMV7_ENABLE_SECURE_BOOT bool "Secure Boot" + depends on SECURE_BOOT help Enable Freescale Secure Boot feature. Normally selected by defconfig. If unsure, do not change. diff --git a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig index 42d31fdab0a0..d4cfe31f8ebf 100644 --- a/arch/arm/cpu/armv8/fsl-layerscape/Kconfig +++ b/arch/arm/cpu/armv8/fsl-layerscape/Kconfig @@ -383,8 +383,9 @@ config EMC2305 Enable the EMC2305 fan controller for configuration of fan speed. -config SECURE_BOOT +config FSI_ARMV8_ENABLE_SECURE_BOOT bool "Secure Boot" + depends on SECURE_BOOT help Enable Freescale Secure Boot feature diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index aeb54934888d..e1602fd5f0e8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -34,8 +34,9 @@ config USE_IMXIMG_PLUGIN i.MX6/7 supports DCD and Plugin. Enable this configuration to use Plugin, otherwise DCD will be used. -config SECURE_BOOT +config FSL_IMX_ENABLE_SECURE_BOOT bool "Support i.MX HAB features" + depends on SECURE_BOOT depends on ARCH_MX7 || ARCH_MX6 || ARCH_MX5 select FSL_CAAM if HAS_CAAM imply CMD_DEKBLOB diff --git a/arch/powerpc/cpu/mpc85xx/Kconfig b/arch/powerpc/cpu/mpc85xx/Kconfig index c038a6ddb0f4..9cf6ebbfe3ce 100644 --- a/arch/powerpc/cpu/mpc85xx/Kconfig +++ b/arch/powerpc/cpu/mpc85xx/Kconfig @@ -1208,8 +1208,9 @@ config FSL_LAW help Use Freescale common code for Local Access Window -config SECURE_BOOT +config FSL_MPC_ENABLE_SECURE_BOOT bool "Secure Boot" + depends on SECURE_BOOT help Enable Freescale Secure Boot feature. Normally selected by defconfig. If unsure, do not change. From patchwork Wed Sep 18 01:26:35 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163646 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="KkmkPgPt"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2S201YKz9s4Y for ; Wed, 18 Sep 2019 11:28:33 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 86234C21EE0; Wed, 18 Sep 2019 01:26:19 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 9DEEFC21EC8; Wed, 18 Sep 2019 01:25:07 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A8C4EC21EBA; Wed, 18 Sep 2019 01:23:54 +0000 (UTC) Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by lists.denx.de (Postfix) with ESMTPS id 6C606C21D8A for ; Wed, 18 Sep 2019 01:23:51 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id i18so2978011pgl.11 for ; Tue, 17 Sep 2019 18:23:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=HTy41RUYySitNTo5PLsqDN8VpPrrTWt2aEkt7ULmc+s=; b=KkmkPgPtEbnQwWTR5NgRkPpoZNq983YHdyzWolWOqDmI88rUxlGfInfK1OS+CgT3Jj FctZYRl+6qUUVVpOBCiwT6Uo6hgTZ3fi9U7WvdgkYMaMGEfRGA26NV0c++gSGYhRkvOJ uSQODRrQBaKwkZ0qLvygirfTlwfRrhDb7nCP3iHFLHYKHKnOIzoY9gvMxvW2qszu/eQZ oPQuUscrXM5OVsQgAJTT8YFxHnCt4Aswg7Ye4aGhVfvDzD5ag+Y85gdEf3q5baNSVB9i KlvRYaqazyD+ac4k2+wQzmNUWGDS/aXEuxNsXILNvxmZyUual+1lMwiplDB3oCM1WAm4 XE7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=HTy41RUYySitNTo5PLsqDN8VpPrrTWt2aEkt7ULmc+s=; b=mo1MWnvnQ4eU9g55PJasT7JL7sAjZpYo/A5eUU/OakL3faeUIXLz9FNREe8WsTOA+j J0bdwaEqhlW/9u7dvbh+Gvtayq2wGQby0Z6EVve0Up68bN43324QfWb9W+q5vwSOSiLH HaxR+Hr/dEwvJdwVwnC+gS1uY8BwoIyi9V2EfRMPn+qJ3DSLtgmfinZle1Jpd92FqgGA D+c9+D54UhBCDo37uzaAmuoiYMqVE/BaHRKBvPP6J7vi86p18fg3xXyjlcVE2XXydk1O 8rm8EqGma1bxjHwnZlAsQSDX7JggAV8J0lkU5qYGdmJCIv4hAraODOASbDTWlb9CikJn k43A== X-Gm-Message-State: APjAAAWYQlwBsw39YftJjY8VzqKC/o7NFpi37MmnQolT95b/uQ4871LR yHiVF56TaNmnu++adIVsRlZfP5yLNRA= X-Google-Smtp-Source: APXvYqyLS8rfJxtakJWETp+lo7aGZD6KSYHFwQWieikTaok3eHcVsTcQIQ/7wGl5NJ966tnImSY0/A== X-Received: by 2002:aa7:9a92:: with SMTP id w18mr1453181pfi.244.1568769829772; Tue, 17 Sep 2019 18:23:49 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 196sm5080351pfz.99.2019.09.17.18.23.48 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:49 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:35 +0900 Message-Id: <20190918012643.25192-8-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 07/15] efi_loader: add signature verification functions X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" In this commit, implemented are efi_signature_verify_with_db(), efi_signature_parse_sigdb() and a couple of helper functions which will be used for variable authentication as well as image authentication in UEFI secure boot. efi_signature_verify_with_db() - authenticate an image with its hash value for unsigned image, and with its embedded pkcs7 signature with a given signature store if signed. This function will also be used to validate authentication data in authenticated variables. efi_signature_parse_sigdb() - parse signature database variable and retrieve signature lists, which may consist of x509 certificates or message digests (SHA256 only for now). Signed-off-by: AKASHI Takahiro --- include/efi_api.h | 47 +++ include/efi_loader.h | 47 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_signature.c | 602 +++++++++++++++++++++++++++++++++ 4 files changed, 697 insertions(+) create mode 100644 lib/efi_loader/efi_signature.c diff --git a/include/efi_api.h b/include/efi_api.h index 9f49a4575e07..72999f762515 100644 --- a/include/efi_api.h +++ b/include/efi_api.h @@ -18,6 +18,7 @@ #include #include +#include #ifdef CONFIG_EFI_LOADER #include @@ -307,6 +308,10 @@ struct efi_runtime_services { EFI_GUID(0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, \ 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c) +#define EFI_IMAGE_SECURITY_DATABASE_GUID \ + EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, \ + 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) + #define EFI_FDT_GUID \ EFI_GUID(0xb1b621d5, 0xf19c, 0x41a5, \ 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0) @@ -1597,4 +1602,46 @@ struct efi_unicode_collation_protocol { #define LOAD_OPTION_CATEGORY_BOOT 0x00000000 #define LOAD_OPTION_CATEGORY_APP 0x00000100 +/* Secure boot */ +#define EFI_CERT_SHA256_GUID \ + EFI_GUID(0xc1c41626, 0x504c, 0x4092, 0xac, 0xa9, \ + 0x41, 0xf9, 0x36, 0x93, 0x43, 0x28) +#define EFI_CERT_RSA2048_GUID \ + EFI_GUID(0x3c5766e8, 0x269c, 0x4e34, 0xaa, 0x14, \ + 0xed, 0x77, 0x6e, 0x85, 0xb3, 0xb6) +#define EFI_CERT_X509_GUID \ + EFI_GUID(0xa5c059a1, 0x94e4, 0x4aa7, 0x87, 0xb5, \ + 0xab, 0x15, 0x5c, 0x2b, 0xf0, 0x72) +#define EFI_CERT_X509_SHA256_GUID \ + EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, \ + 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed) +#define EFI_CERT_TYPE_PKCS7_GUID \ + EFI_GUID(0x4aafd29d, 0x68df, 0x49ee, 0x8a, 0xa9, \ + 0x34, 0x7d, 0x37, 0x56, 0x65, 0xa7) + +struct win_certificate_uefi_guid { + WIN_CERTIFICATE hdr; + efi_guid_t cert_type; + u8 cert_data[]; +} __attribute__((__packed__)); + +struct efi_variable_authentication_2 { + struct efi_time time_stamp; + struct win_certificate_uefi_guid auth_info; +} __attribute__((__packed__)); + +struct efi_signature_data { + efi_guid_t signature_owner; + u8 signature_data[]; +} __attribute__((__packed__)); + +struct efi_signature_list { + efi_guid_t signature_type; + u32 signature_list_size; + u32 signature_header_size; + u32 signature_size; +/* u8 signature_header[signature_header_size]; */ +/* struct efi_signature_data signatures[...][signature_size]; */ +} __attribute__((__packed__)); + #endif diff --git a/include/efi_loader.h b/include/efi_loader.h index 5298ea7997f7..c75ee5fcb6ba 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -16,6 +16,7 @@ #if CONFIG_IS_ENABLED(EFI_LOADER) #include +#include /* Maximum number of configuration tables */ #define EFI_MAX_CONFIGURATION_TABLES 16 @@ -156,6 +157,11 @@ extern const efi_guid_t efi_guid_hii_config_routing_protocol; extern const efi_guid_t efi_guid_hii_config_access_protocol; extern const efi_guid_t efi_guid_hii_database_protocol; extern const efi_guid_t efi_guid_hii_string_protocol; +/* GUID for authentication */ +extern const efi_guid_t efi_guid_image_security_database; +extern const efi_guid_t efi_guid_sha256; +extern const efi_guid_t efi_guid_cert_x509; +extern const efi_guid_t efi_guid_cert_x509_sha256; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; @@ -654,6 +660,47 @@ void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data); unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data); efi_status_t efi_bootmgr_load(efi_handle_t *handle); +#ifdef CONFIG_EFI_SECURE_BOOT +#include + +#define EFI_REGS_MAX 16 /* currently good enough */ + +typedef struct { + int num; + struct image_region reg[EFI_REGS_MAX]; +} efi_image_regions; + +struct efi_sig_data { + struct efi_sig_data *next; + efi_guid_t owner; + void *data; + size_t size; +}; + +typedef struct efi_signature_store { + struct efi_signature_store *next; + efi_guid_t sig_type; + struct efi_sig_data *sig_data_list; +} efi_signature_store; + +struct pkcs7_message; + +bool efi_signature_verify_with_db(efi_image_regions *regs, + struct pkcs7_message *msg, + efi_signature_store *trusted); +bool efi_signature_revoke(efi_image_regions *regs, + struct pkcs7_message *msg, + efi_signature_store *untrusted, + efi_signature_store *tsa); + +efi_status_t efi_image_region_add(efi_image_regions *ctx, + const void *start, const void *end, + int nocheck); + +void efi_sigstore_free(efi_signature_store *ctx); +efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); +#endif /* CONFIG_EFI_SECURE_BOOT */ + #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */ diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 01769ea58ba6..49c996c89052 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -39,3 +39,4 @@ obj-$(CONFIG_PARTITIONS) += efi_disk.o obj-$(CONFIG_NET) += efi_net.o obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o +obj-y += efi_signature.o diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c new file mode 100644 index 000000000000..55a335cc44ae --- /dev/null +++ b/lib/efi_loader/efi_signature.c @@ -0,0 +1,602 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2018 Patrick Wildt + * Copyright (c) 2019 Linaro Limited, Author: AKASHI Takahiro + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* + * avoid duplicated inclusion: + * #include "../lib/crypto/x509_parser.h" + */ +#include "../lib/crypto/pkcs7_parser.h" + +const efi_guid_t efi_guid_image_security_database = + EFI_IMAGE_SECURITY_DATABASE_GUID; +const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID; +const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID; +const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID; +const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID; + +#ifdef CONFIG_EFI_SECURE_BOOT +/* TODO: generalized for other hash algos */ +static const unsigned char WinIndirectSha256[] = { + 0x30, 0x33, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, + 0x01, 0x0f, 0x30, 0x25, 0x03, 0x01, 0x00, 0xa0, 0x20, 0xa2, 0x1e, 0x80, + 0x1c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x4f, 0x00, 0x62, 0x00, + 0x73, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, + 0x3e, 0x00, 0x3e, 0x00, 0x3e, 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +}; + +static bool efi_hash_regions(efi_image_regions *regs, void **hash, size_t *size) +{ + *size = 0; + *hash = calloc(1, SHA256_SUM_LEN); + if (!*hash) { + debug("Out of memory\n"); + return false; + } + *size = SHA256_SUM_LEN; + + hash_calculate("sha256", regs->reg, regs->num, *hash); +#ifdef DEBUG + debug("hash calculated:\n"); + print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, + *hash, SHA256_SUM_LEN, false); +#endif + + return true; +} + +static bool efi_hash_regions_in_der(efi_image_regions *regs, void **hash, + size_t *size) +{ + void *msg; + size_t msg_size; + struct image_region regtmp[2]; + + if (!efi_hash_regions(regs, &msg, &msg_size)) { + debug("Hash calculation failed\n"); + return false; + ; + } + + *size = 0; + *hash = calloc(1, SHA256_SUM_LEN); + if (!*hash) { + debug("Out of memory\n"); + free(msg); + return false; + } + *size = SHA256_SUM_LEN; + + /* File image hash is digested with some DER wrapper. */ + regtmp[0].data = WinIndirectSha256; + regtmp[0].size = sizeof(WinIndirectSha256); + regtmp[1].data = msg; + regtmp[1].size = msg_size; + + hash_calculate("sha256", regtmp, 2, *hash); +#ifdef DEBUG + debug("hash calculated in der:\n"); + print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, + *hash, SHA256_SUM_LEN, false); +#endif + + free(msg); + + return true; +} + +static bool efi_signature_verify(efi_image_regions *regs, + struct pkcs7_signed_info *ps_info, + struct x509_certificate *cert) +{ + struct image_sign_info info; + struct image_region regtmp[2]; + void *hash; + size_t size; + char c; + bool verified; + + debug("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__, + regs, ps_info, cert, cert->issuer, cert->subject); + + verified = false; + + memset(&info, '\0', sizeof(info)); + info.padding = image_get_padding_algo("pkcs-1.5"); + /* + * Note: image_get_[checksum|crypto]_algo takes an string + * argument like "," + */ + if (!strcmp(ps_info->sig->hash_algo, "sha1")) { + info.checksum = image_get_checksum_algo("sha1,rsa2048"); + info.name = "sha1,rsa2048"; + } else if (!strcmp(ps_info->sig->hash_algo, "sha256")) { + info.checksum = image_get_checksum_algo("sha256,rsa2048"); + info.name = "sha256,rsa2048"; + } else { + debug("unknown msg digest algo: %s\n", ps_info->sig->hash_algo); + goto out; + } + info.crypto = image_get_crypto_algo(info.name); + + info.key = cert->pub->key; + info.keylen = cert->pub->keylen; + + /* verify signature */ + debug("%s: crypto: %s, signature len:%x\n", __func__, + info.name, ps_info->sig->s_size); + if (ps_info->authattrs_len) { + debug("%s: RSA verify authentication attribute\n", __func__); + /* + * NOTE: This path will be executed only for + * PE image authentication + */ + + /* check if hash matches digest first */ + debug("checking msg digest first, len:0x%x\n", + ps_info->msgdigest_len); + + if (efi_hash_regions_in_der(regs, &hash, &size)) { + if (ps_info->msgdigest_len != size || + memcmp(hash, ps_info->msgdigest, size)) { + debug("Digest doesn't match\n"); + free(hash); + goto out; + } + + free(hash); + } else { + debug("Digesting image failed\n"); + goto out; + } + + /* against digest */ + c = 0x31; + regtmp[0].data = &c; + regtmp[0].size = 1; + regtmp[1].data = ps_info->authattrs; + regtmp[1].size = ps_info->authattrs_len; + + if (!rsa_verify(&info, regtmp, 2, + ps_info->sig->s, ps_info->sig->s_size)) + verified = true; + } else { + debug("%s: RSA verify content data\n", __func__); + /* against all data */ + if (!rsa_verify(&info, regs->reg, regs->num, + ps_info->sig->s, ps_info->sig->s_size)) + verified = true; + } + +out: + debug("%s: Exit, verified: %d\n", __func__, verified); + return verified; +} + +static +bool efi_signature_verify_with_list(efi_image_regions *regs, + struct pkcs7_signed_info *signed_info, + efi_signature_store *siglist) +{ + struct x509_certificate *cert; + struct efi_sig_data *sig_data; + bool verified = false; + + debug("%s: Enter, %p, %p, %p\n", __func__, regs, signed_info, siglist); + + if (!signed_info) { + void *hash; + size_t size; + + debug("%s: unsigned image\n", __func__); + /* verify based on calculated hash value */ + if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) { + debug("Digest algorithm is not supported: %pUl\n", + &siglist->sig_type); + goto out; + } + + /* TODO: other than CERT_SHA256 */ + if (!efi_hash_regions(regs, &hash, &size)) { + debug("Digesting unsigned image failed\n"); + goto out; + } + + /* go through the list */ + for (sig_data = siglist->sig_data_list; sig_data; + sig_data = sig_data->next) { +#ifdef DEBUG + debug("Msg digest in database:\n"); + print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1, + sig_data->data, sig_data->size, false); +#endif + if ((sig_data->size == size) && + !memcmp(sig_data->data, hash, size)) { + verified = true; + free(hash); + goto out; + } + } + free(hash); + goto out; + } + + debug("%s: signed image\n", __func__); + if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509)) { + debug("Signature type is not supported: %pUl\n", + &siglist->sig_type); + goto out; + } + + /* go through the list */ + for (sig_data = siglist->sig_data_list; sig_data; + sig_data = sig_data->next) { + /* TODO: owner check by policy? */ + + cert = x509_cert_parse(sig_data->data, sig_data->size); + if (IS_ERR(cert)) { + debug("Parsing x509 certificate failed\n"); + goto out; + } + + verified = efi_signature_verify(regs, signed_info, cert); + x509_free_certificate(cert); + + if (verified) + break; + } + +out: + debug("%s: Exit, verified: %d\n", __func__, verified); + return verified; +} + +bool efi_signature_verify_with_db(efi_image_regions *regs, + struct pkcs7_message *msg, + efi_signature_store *trusted) +{ + struct pkcs7_signed_info *info; + efi_signature_store *siglist; + bool verified = false; + + if (!trusted) + goto out; + + if (!trusted->sig_data_list) + goto out; + + /* for unsigned image */ + if (!msg) { + for (siglist = trusted; siglist; siglist = siglist->next) + if (efi_signature_verify_with_list(regs, NULL, + siglist)) { + verified = true; + goto out; + } + + goto out; + } + + /* signed image or variable */ + for (info = msg->signed_infos; info; info = info->next) { + debug("Signed Info: digest algo: %s, pkey algo: %s\n", + info->sig->hash_algo, info->sig->pkey_algo); + + for (siglist = trusted; siglist; siglist = siglist->next) { + if (efi_signature_verify_with_list(regs, info, + siglist)) { + verified = true; + goto out; + } + } + } + +out: + return verified; +} + +/* TODO: TSA support */ +bool efi_signature_revoke(efi_image_regions *regs, + struct pkcs7_message *msg, + efi_signature_store *untrusted, + efi_signature_store *tsa) +{ + struct pkcs7_signed_info *info; + efi_signature_store *siglist; + bool rejected = false; + + if (!untrusted) + goto out; + + if (!untrusted->sig_data_list) + goto out; + + for (info = msg->signed_infos; info; info = info->next) { + debug("Signed Info: digest algo: %s, pkey algo: %s\n", + info->sig->hash_algo, info->sig->pkey_algo); + + for (siglist = untrusted; siglist; siglist = siglist->next) { + if (efi_signature_verify_with_list(regs, info, + siglist)) { + rejected = true; + goto out; + } + } + } + +out: + return rejected; +} + +/* + * Image region helper. With this it's easier to record what parts + * of an image should be checksummed and then do the checksumming + * later depending on the hash. + */ +efi_status_t efi_image_region_add(efi_image_regions *ctx, + const void *start, const void *end, + int nocheck) +{ + struct image_region *reg; + int i, j; + + if (ctx->num >= EFI_REGS_MAX) { + debug("%s: no more room for regions\n", __func__); + return EFI_OUT_OF_RESOURCES; + } + + if (end < start) + return EFI_INVALID_PARAMETER; + + for (i = 0; i < ctx->num; i++) { + reg = &ctx->reg[i]; + if (nocheck) + continue; + + if (start > reg->data + reg->size) + continue; + + if ((start >= reg->data && start < reg->data + reg->size) || + (end > reg->data && end < reg->data + reg->size)) { + debug("%s: new region already part of another\n", + __func__); + return EFI_INVALID_PARAMETER; + } + + if (start < reg->data && end < reg->data + reg->size) { + for (j = ctx->num - 1; j >= i; j--) + memcpy(&ctx->reg[j], &ctx->reg[j + 1], + sizeof(*reg)); + break; + } + } + + reg = &ctx->reg[i]; + reg->data = start; + reg->size = end - start; + ctx->num++; + + return EFI_SUCCESS; +} + +void efi_sigstore_free(efi_signature_store *sigstore) +{ + efi_signature_store *sigstore_next; + struct efi_sig_data *sig_data, *sig_data_next; + + while (sigstore) { + sigstore_next = sigstore->next; + + /* TODO: more structured data? */ + sig_data = sigstore->sig_data_list; + while (sig_data) { + if (sig_data) + sig_data_next = sig_data->next; + free(sig_data->data); + free(sig_data); + sig_data = sig_data_next; + } + + free(sigstore); + sigstore = sigstore_next; + } +} + +static +efi_signature_store *efi_sigstore_parse_siglist(struct efi_signature_list *esl) +{ + efi_signature_store *sigstore = NULL; + struct efi_sig_data *sig_data, *sig_data_next; + struct efi_signature_data *esd; + size_t left; + + /* + * UEFI specification defines certificate types: + * for non-signed images, + * EFI_CERT_SHA256_GUID + * EFI_CERT_RSA2048_GUID + * EFI_CERT_RSA2048_SHA256_GUID + * EFI_CERT_SHA1_GUID + * EFI_CERT_RSA2048_SHA_GUID + * EFI_CERT_SHA224_GUID + * EFI_CERT_SHA384_GUID + * EFI_CERT_SHA512_GUID + * + * for signed images, + * EFI_CERT_X509_GUID + * NOTE: Each certificate will normally be in a separate + * EFI_SIGNATURE_LIST as the size may vary depending on + * its algo's. + * + * for timestamp revocation of certificate, + * EFI_CERT_X509_SHA512_GUID + * EFI_CERT_X509_SHA256_GUID + * EFI_CERT_X509_SHA384_GUID + */ + + if (esl->signature_list_size + <= (sizeof(*esl) + esl->signature_header_size)) { + debug("Siglist in wrong format\n"); + return NULL; + } + + /* Create a head */ + sigstore = calloc(sizeof(*sigstore), 1); + if (!sigstore) { + debug("Out of memory\n"); + goto err; + } + memcpy(&sigstore->sig_type, &esl->signature_type, sizeof(efi_guid_t)); + + /* Go through the list */ + sig_data_next = NULL; + left = esl->signature_list_size + - (sizeof(*esl) + esl->signature_header_size); + esd = (struct efi_signature_data *) + ((u8 *)esl + sizeof(*esl) + esl->signature_header_size); + + while ((left > 0) && left >= esl->signature_size) { + /* Signature must exist if there is remaining data. */ + if (left < esl->signature_size) { + debug("Certificate is too small\n"); + goto err; + } + + sig_data = calloc(esl->signature_size + - sizeof(esd->signature_owner), 1); + if (!sig_data) { + debug("Out of memory\n"); + goto err; + } + + /* Append signature data */ + memcpy(&sig_data->owner, &esd->signature_owner, + sizeof(efi_guid_t)); + sig_data->size = esl->signature_size + - sizeof(esd->signature_owner); + sig_data->data = malloc(sig_data->size); + if (!sig_data->data) { + debug("Out of memory\n"); + goto err; + } + memcpy(sig_data->data, esd->signature_data, sig_data->size); + + sig_data->next = sig_data_next; + sig_data_next = sig_data; + + /* Next */ + esd = (struct efi_signature_data *) + ((u8 *)esd + esl->signature_size); + left -= esl->signature_size; + } + sigstore->sig_data_list = sig_data_next; + + return sigstore; + +err: + efi_sigstore_free(sigstore); + + return NULL; +} + +efi_signature_store *efi_sigstore_parse_sigdb(u16 *name) +{ + efi_signature_store *sigstore = NULL, *sigstore_list; + struct efi_signature_list *esl; + const efi_guid_t *vendor; + void *db; + efi_uintn_t db_size; + efi_status_t ret; + + if (!u16_strcmp(name, L"PK") || !u16_strcmp(name, L"KEK")) { + vendor = &efi_global_variable_guid; + } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) { + vendor = &efi_guid_image_security_database; + } else { + debug("unknown signature database, %ls\n", name); + return NULL; + } + + /* retrieve variable data */ + db_size = 0; + ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL)); + if (ret == EFI_NOT_FOUND) { + debug("variable, %ls, not found\n", name); + /* + * TODO: + * how should this condition be notified of to caller? + * Returning empty sigstore won't harm anything. + */ + sigstore = calloc(sizeof(*sigstore), 1); + + return sigstore; + } else if (ret != EFI_BUFFER_TOO_SMALL) { + debug("Getting variable, %ls, failed\n", name); + return NULL; + } + + db = malloc(db_size); + if (!db) { + debug("Out of memory\n"); + return NULL; + } + + ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db)); + if (ret != EFI_SUCCESS) { + debug("Getting variable, %ls, failed\n", name); + goto err; + } + + /* Parse siglist list */ + esl = db; + while (db_size > 0) { + /* List must exist if there is remaining data. */ + if (db_size < sizeof(*esl)) { + debug("variable, %ls, in wrong format\n", name); + goto err; + } + + if (db_size < esl->signature_list_size) { + debug("variable, %ls, in wrong format\n", name); + goto err; + } + + /* Parse a single siglist. */ + sigstore_list = efi_sigstore_parse_siglist(esl); + if (!sigstore_list) { + debug("Parsing signature list of %ls failed\n", name); + goto err; + } + + /* Append siglist */ + sigstore_list->next = sigstore; + sigstore = sigstore_list; + + /* Next */ + db_size -= esl->signature_list_size; + esl = (void *)esl + esl->signature_list_size; + } + free(db); + + return sigstore; + +err: + efi_sigstore_free(sigstore); + free(db); + + return NULL; +} +#endif /* CONFIG_EFI_SECURE_BOOT */ From patchwork Wed Sep 18 01:26:36 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163641 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="scnS4uka"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Ny083yz9s4Y for ; Wed, 18 Sep 2019 11:25:53 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id A35A4C21E2C; Wed, 18 Sep 2019 01:24:48 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=RCVD_IN_MSPIKE_H2, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 64512C21EB9; Wed, 18 Sep 2019 01:24:13 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id D430FC21E5B; Wed, 18 Sep 2019 01:23:58 +0000 (UTC) Received: from mail-pf1-f171.google.com (mail-pf1-f171.google.com [209.85.210.171]) by lists.denx.de (Postfix) with ESMTPS id B0A0CC21E90 for ; Wed, 18 Sep 2019 01:23:54 +0000 (UTC) Received: by mail-pf1-f171.google.com with SMTP id q7so3249020pfh.8 for ; Tue, 17 Sep 2019 18:23:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=OPbKMfwiLIr3aHT1/acExztizG+GkkFFsSjpBfX5Bro=; b=scnS4ukaWHwOGHxVF25iiKjZ/shSXEhRkmuvLvDstTdlbaNpfpHaenRrFsRl2Npqdc DGlvFyVv3tc1HwSKuheLS82mn+u7Zndyhls5+6jN3FG1lx3OPNTSsz3NXUmr3z96e7ND 9uzmYREA125KdRu/S84GdY8DyMGK8uN/nuvz9KZZOD58nWWYO9Ks10lnfQpkqRWOfQ8w ovuagCT3ZPDzw5vRDOWI3PjGkZ7OFTW0VNDkF/BxlBtLFoFSurnVOq5sR0sL6A1JroDg v4gezU2OhQzK1XHObDMu83/N5Rgxg/lYpzUlDIgwowJDrXoj0+duuWMrJ2IO8mtKfwoi cJmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OPbKMfwiLIr3aHT1/acExztizG+GkkFFsSjpBfX5Bro=; b=QjUGa794qT+sxfOeFBEkL7+XPVxfGctExv5mKV8DCq+so/tXKs/iRiDNHQj9pI4WdH kmlGUdEBRCfr9SQIHB1I9FcffeQ/GcJZUd95owpAbRhju4mgcl64Fe3oA6KsTJhdQl0V QEDez18+Cwec2SbHAiShTxEU4foi+lIM//zqMfrgzT5gdsTvQMa6Mdp5+v5+3+PCzH6N PgTV2H52ydUJjhTw83Fmwaor8NBRkQSVlLJfJR+Wg6oaJiu31ySNkwXh6QG9L42DD/jj QeJs2DgolG4eFPSYGU5l6q3MAX9/n3itPis2m6oVeyOMdPm+VfgdXF0mvV1wV27wtubk JXQw== X-Gm-Message-State: APjAAAW1N2+XsYk+oKUacVXlzcxWtjxh3hbRFLiBlXrNtaCjxH7wKR8v 2KlYG+3no11f1B/hexyBAK3n/AY1sr0= X-Google-Smtp-Source: APXvYqybEagDxRhxqVbg27AlBG2QHJO73jAj+T6Kd2Wdazj7HEPZKXwNrdLl+dsxVToEZojEGRH0jw== X-Received: by 2002:a63:6195:: with SMTP id v143mr1566949pgb.73.1568769832754; Tue, 17 Sep 2019 18:23:52 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id a11sm4158784pfg.94.2019.09.17.18.23.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:52 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:36 +0900 Message-Id: <20190918012643.25192-9-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 08/15] efi_loader: variable: support variable authentication X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" With this commit, EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS is supported for authenticated variables and the system secure state will transfer between setup mode and user mode as UEFI specification section 32.3 describes. Internally, authentication data is stored as part of authenticated variable's value. It is nothing but a pkcs7 message (but we need some wrapper, see efi_variable_parse_signature()) and will be validated by efi_variable_authenticate(), hence efi_signature_verify_with_db(). Associated time value will be encoded in "{...,time=...}" along with other UEFI variable's attributes. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 4 + lib/efi_loader/efi_variable.c | 855 ++++++++++++++++++++++++++++++---- 2 files changed, 757 insertions(+), 102 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index c75ee5fcb6ba..caac8efba89a 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -162,6 +162,7 @@ extern const efi_guid_t efi_guid_image_security_database; extern const efi_guid_t efi_guid_sha256; extern const efi_guid_t efi_guid_cert_x509; extern const efi_guid_t efi_guid_cert_x509_sha256; +extern const efi_guid_t efi_guid_cert_type_pkcs7; extern unsigned int __efi_runtime_start, __efi_runtime_stop; extern unsigned int __efi_runtime_rel_start, __efi_runtime_rel_stop; @@ -699,6 +700,9 @@ efi_status_t efi_image_region_add(efi_image_regions *ctx, void efi_sigstore_free(efi_signature_store *ctx); efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); + +bool efi_secure_boot_enabled(void); +efi_status_t efi_init_secure_boot(void); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 5d1ee50a606e..fa706f1ad6b8 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -11,8 +11,25 @@ #include #include #include +#include #include #include +#include +/* + * avoid duplicated inclusion: + * #include "../lib/crypto/x509_parser.h" + */ +#include "../lib/crypto/pkcs7_parser.h" + +enum efi_secure_mode { + EFI_MODE_SETUP, + EFI_MODE_USER, + EFI_MODE_AUDIT, + EFI_MODE_DEPLOYED, +}; + +const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; +static bool efi_secure_boot; #define READ_ONLY BIT(31) @@ -109,7 +126,7 @@ static const char *prefix(const char *str, const char *prefix) * @attrp: pointer to UEFI attributes * Return: pointer to remainder of U-Boot variable value */ -static const char *parse_attr(const char *str, u32 *attrp) +static const char *parse_attr(const char *str, u32 *attrp, u64 *timep) { u32 attr = 0; char sep = '{'; @@ -132,6 +149,12 @@ static const char *parse_attr(const char *str, u32 *attrp) attr |= EFI_VARIABLE_BOOTSERVICE_ACCESS; } else if ((s = prefix(str, "run"))) { attr |= EFI_VARIABLE_RUNTIME_ACCESS; + } else if ((s = prefix(str, "time="))) { + attr |= EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + hex2bin((u8 *)timep, s, sizeof(*timep)); + s += sizeof(*timep) * 2; + } else if (*str == '}') { + break; } else { printf("invalid attribute: %s\n", str); break; @@ -148,49 +171,454 @@ static const char *parse_attr(const char *str, u32 *attrp) return str; } -/** - * efi_get_variable() - retrieve value of a UEFI variable - * - * This function implements the GetVariable runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @variable_name: name of the variable - * @vendor: vendor GUID - * @attributes: attributes of the variable - * @data_size: size of the buffer to which the variable value is copied - * @data: buffer to which the variable value is copied - * Return: status code +static efi_status_t efi_set_variable_internal(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check); + +static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode) +{ + u32 attributes; + u8 val; + efi_status_t ret; + + debug("Secure state from %d to %d\n", efi_secure_mode, mode); + + attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS; + if (mode == EFI_MODE_DEPLOYED) { + val = 1; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_AUDIT) { + ret = efi_set_variable_internal(L"PK", + &efi_global_variable_guid, + attributes, + 0, NULL, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_USER) { + val = 1; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + + efi_secure_boot = true; + } else if (mode == EFI_MODE_SETUP) { + val = 0; + ret = efi_set_variable_internal(L"SecureBoot", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 1; + ret = efi_set_variable_internal(L"SetupMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"AuditMode", + &efi_global_variable_guid, + attributes, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + val = 0; + ret = efi_set_variable_internal(L"DeployedMode", + &efi_global_variable_guid, + attributes | READ_ONLY, + sizeof(val), &val, + false); + if (ret != EFI_SUCCESS) + goto err; + } else { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; + +err: + /* TODO: failsafe */ + printf("ERROR: Secure state transition failed\n"); + return ret; +} + +efi_status_t efi_init_secure_boot(void) +{ + efi_uintn_t size = 0; + efi_status_t ret; + + ret = EFI_CALL(efi_get_variable(L"PK", &efi_global_variable_guid, + NULL, &size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL && IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) + ret = efi_transfer_secure_state(EFI_MODE_USER); + else + ret = efi_transfer_secure_state(EFI_MODE_SETUP); + + return ret; +} + +/* check if secure boot is enabled by trying to read PK */ +bool efi_secure_boot_enabled(void) +{ + return efi_secure_boot; +} + +#ifdef CONFIG_EFI_SECURE_BOOT +static u8 pkcs7_hdr[] = { + /* SEQUENCE */ + 0x30, 0x82, 0x05, 0xc7, + /* OID: pkcs7-signedData */ + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02, + /* Context Structured? */ + 0xa0, 0x82, 0x05, 0xb8, +}; + +/* + * This function is a wrapper for pkcs7_parse_message() now. + * TODO: Any better way? */ -efi_status_t EFIAPI efi_get_variable(u16 *variable_name, - const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data) +static struct pkcs7_message *efi_variable_parse_signature(const void *buf, + size_t buflen) +{ + u8 *ebuf; + size_t ebuflen, len; + struct pkcs7_message *msg; + + /* + * This is the best assumption to check if the binary is + * already in a form of pkcs7's signedData. + */ + if (buflen > sizeof(pkcs7_hdr) && + !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) { + msg = pkcs7_parse_message(buf, buflen); + goto out; + } + + /* + * Otherwise, we should add a dummy prefix sequence for pkcs7 + * message parser to be able to process. + * NOTE: EDK2 also uses similar hack in WrapPkcs7Data() + * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c + */ + debug("Fake prefix added to authentication data\n"); + ebuflen = sizeof(pkcs7_hdr) + buflen; + if (ebuflen <= 0x7f) { + debug("Data is too short\n"); + return NULL; + } + + ebuf = malloc(ebuflen); + if (!ebuf) { + debug("Out of memory\n"); + return NULL; + } + + memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr)); + memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen); + len = ebuflen - 4; + ebuf[2] = (len >> 8) & 0xff; + ebuf[3] = len & 0xff; + len = ebuflen - 0x13; + ebuf[0x11] = (len >> 8) & 0xff; + ebuf[0x12] = len & 0xff; + + msg = pkcs7_parse_message(ebuf, ebuflen); + + free(ebuf); + +out: + if (IS_ERR(msg)) + return NULL; + + return msg; +} + +/* + * Called by efi_set_variable() to verify that the input is correct. + * Will replace the given data pointer with another that points to + * the actual data to store in the internal memory. + */ +static efi_status_t efi_variable_authenticate(u16 *variable, + const efi_guid_t *vendor, + efi_uintn_t *data_size, + const void **data, u32 given_attr, + u32 *env_attr, u64 *time) +{ + const struct efi_variable_authentication_2 *auth; + efi_signature_store *truststore, *truststore2; + struct pkcs7_message *var_sig; + efi_image_regions *regs; + const struct efi_time *timestamp; + struct rtc_time tm; + efi_status_t ret; + + var_sig = NULL; + truststore = NULL; + truststore2 = NULL; + regs = NULL; + ret = EFI_SECURITY_VIOLATION; + + if (*data_size < sizeof(struct efi_variable_authentication_2)) + goto err; + + /* authentication data */ + auth = *data; + if (*data_size < (sizeof(auth->time_stamp) + + auth->auth_info.hdr.dwLength)) + goto err; + + if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7)) + goto err; + + *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength; + *data_size -= (sizeof(auth->time_stamp) + + auth->auth_info.hdr.dwLength); + + /* FIXME: What to do when one attr has time but other one does not? */ + timestamp = &auth->time_stamp; + memset(&tm, 0, sizeof(tm)); + tm.tm_year = timestamp->year; + tm.tm_mon = timestamp->month; + tm.tm_mday = timestamp->day; + tm.tm_hour = timestamp->hour; + tm.tm_min = timestamp->minute; + tm.tm_sec = timestamp->second; + + if (!efi_secure_boot_enabled()) { + /* finished checking */ + *time = rtc_mktime(&tm); + return EFI_SUCCESS; + } + + if (rtc_mktime(&tm) <= *time) + goto err; + + /* data to be digested */ + regs = calloc(1, sizeof(*regs)); + if (!regs) + goto err; + efi_image_region_add(regs, (uint8_t *)variable, + (uint8_t *)variable + + u16_strlen(variable) * sizeof(u16), 1); + efi_image_region_add(regs, (uint8_t *)vendor, + (uint8_t *)vendor + sizeof(*vendor), 1); + efi_image_region_add(regs, (uint8_t *)&given_attr, + (uint8_t *)&given_attr + sizeof(given_attr), 1); + efi_image_region_add(regs, (uint8_t *)timestamp, + (uint8_t *)timestamp + sizeof(*timestamp), 1); + efi_image_region_add(regs, (uint8_t *)*data, + (uint8_t *)*data + *data_size, 1); + + /* variable's signature list */ + if (auth->auth_info.hdr.dwLength < sizeof(auth->auth_info)) + goto err; + var_sig = efi_variable_parse_signature(auth->auth_info.cert_data, + auth->auth_info.hdr.dwLength + - sizeof(auth->auth_info)); + if (IS_ERR(var_sig)) { + debug("Parsing variable's signature failed\n"); + var_sig = NULL; + goto err; + } + + /* signature database used for authentication */ + if (u16_strcmp(variable, L"PK") == 0 || + u16_strcmp(variable, L"KEK") == 0) { + /* with PK */ + truststore = efi_sigstore_parse_sigdb(L"PK"); + if (!truststore) + goto err; + } else if (u16_strcmp(variable, L"db") == 0 || + u16_strcmp(variable, L"dbx") == 0) { + /* with PK and KEK */ + truststore = efi_sigstore_parse_sigdb(L"KEK"); + truststore2 = efi_sigstore_parse_sigdb(L"PK"); + + if (!truststore) { + if (!truststore2) + goto err; + + truststore = truststore2; + truststore2 = NULL; + } + } else { + /* TODO: what UEFI spec says for other variables? */ + goto err; + } + + /* verify signature */ + if (efi_signature_verify_with_db(regs, var_sig, truststore)) { + debug("Verified\n"); + } else { + if (truststore2) { + if (efi_signature_verify_with_db(regs, var_sig, + truststore2)) { + debug("Verified\n"); + } else { + debug("Verifying variable's signature failed\n"); + goto err; + } + } else { + debug("Verifying variable's signature failed\n"); + goto err; + } + } + + /* finished checking */ + *time = rtc_mktime(&tm); + ret = EFI_SUCCESS; + +err: + efi_sigstore_free(truststore); + efi_sigstore_free(truststore2); + pkcs7_free_message(var_sig); + free(regs); + + return ret; +} +#else +static efi_status_t efi_variable_authenticate(u16 *variable, + const efi_guid_t *vendor, + efi_uintn_t *data_size, + const void **data, u32 given_attr, + u32 *env_attr, u64 *time) +{ + return EFI_SUCCESS; +} +#endif /* CONFIG_EFI_SECURE_BOOT */ + +static +efi_status_t EFIAPI efi_get_variable_common(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, void *data, + bool is_non_volatile) { char *native_name; efi_status_t ret; unsigned long in_size; - const char *val, *s; + const char *val = NULL, *s; + u64 time = 0; u32 attr; - EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes, - data_size, data); - if (!variable_name || !vendor || !data_size) return EFI_EXIT(EFI_INVALID_PARAMETER); ret = efi_to_native(&native_name, variable_name, vendor); if (ret) - return EFI_EXIT(ret); + return ret; EFI_PRINT("get '%s'\n", native_name); val = env_get(native_name); free(native_name); if (!val) - return EFI_EXIT(EFI_NOT_FOUND); + return EFI_NOT_FOUND; - val = parse_attr(val, &attr); + val = parse_attr(val, &attr, &time); in_size = *data_size; @@ -199,7 +627,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, /* number of hexadecimal digits must be even */ if (len & 1) - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_DEVICE_ERROR; /* two characters per byte: */ len /= 2; @@ -210,11 +638,13 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, goto out; } - if (!data) - return EFI_EXIT(EFI_INVALID_PARAMETER); + if (!data) { + debug("Variable with no data shouldn't exist.\n"); + return EFI_INVALID_PARAMETER; + } if (hex2bin(data, s, len)) - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_DEVICE_ERROR; EFI_PRINT("got value: \"%s\"\n", s); } else if ((s = prefix(val, "(utf8)"))) { @@ -227,8 +657,10 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, goto out; } - if (!data) - return EFI_EXIT(EFI_INVALID_PARAMETER); + if (!data) { + debug("Variable with no data shouldn't exist.\n"); + return EFI_INVALID_PARAMETER; + } memcpy(data, s, len); ((char *)data)[len] = '\0'; @@ -236,13 +668,67 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, EFI_PRINT("got value: \"%s\"\n", (char *)data); } else { EFI_PRINT("invalid value: '%s'\n", val); - return EFI_EXIT(EFI_DEVICE_ERROR); + return EFI_DEVICE_ERROR; } out: if (attributes) *attributes = attr & EFI_VARIABLE_MASK; + return ret; +} + +static +efi_status_t EFIAPI efi_get_volatile_variable(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, + void *data) +{ + return efi_get_variable_common(variable_name, vendor, attributes, + data_size, data, false); +} + +efi_status_t EFIAPI efi_get_nonvolatile_variable(u16 *variable_name, + const efi_guid_t *vendor, + u32 *attributes, + efi_uintn_t *data_size, + void *data) +{ + return efi_get_variable_common(variable_name, vendor, attributes, + data_size, data, true); +} + +/** + * efi_efi_get_variable() - retrieve value of a UEFI variable + * + * This function implements the GetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @variable_name: name of the variable + * @vendor: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer to which the variable value is copied + * @data: buffer to which the variable value is copied + * Return: status code + */ +efi_status_t EFIAPI efi_get_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 *attributes, + efi_uintn_t *data_size, void *data) +{ + efi_status_t ret; + + EFI_ENTRY("\"%ls\" %pUl %p %p %p", variable_name, vendor, attributes, + data_size, data); + + ret = efi_get_volatile_variable(variable_name, vendor, attributes, + data_size, data); + if (ret == EFI_NOT_FOUND) + ret = efi_get_nonvolatile_variable(variable_name, vendor, + attributes, data_size, data); + return EFI_EXIT(ret); } @@ -275,6 +761,7 @@ static efi_status_t parse_uboot_variable(char *variable, { char *guid, *name, *end, c; unsigned long name_len; + u64 time; u16 *p; guid = strchr(variable, '_'); @@ -309,7 +796,7 @@ static efi_status_t parse_uboot_variable(char *variable, *(name - 1) = c; /* attributes */ - parse_attr(end, attributes); + parse_attr(end, attributes, &time); return EFI_SUCCESS; } @@ -391,7 +878,7 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, list_len = hexport_r(&env_htab, '\n', H_MATCH_REGEX | H_MATCH_KEY, &efi_variables_list, 0, 1, regexlist); - /* 1 indicates that no match was found */ + if (list_len <= 1) return EFI_EXIT(EFI_NOT_FOUND); @@ -404,132 +891,296 @@ efi_status_t EFIAPI efi_get_next_variable_name(efi_uintn_t *variable_name_size, return EFI_EXIT(ret); } -/** - * efi_set_variable() - set value of a UEFI variable - * - * This function implements the SetVariable runtime service. - * - * See the Unified Extensible Firmware Interface (UEFI) specification for - * details. - * - * @variable_name: name of the variable - * @vendor: vendor GUID - * @attributes: attributes of the variable - * @data_size: size of the buffer with the variable value - * @data: buffer with the variable value - * Return: status code - */ -efi_status_t EFIAPI efi_set_variable(u16 *variable_name, - const efi_guid_t *vendor, u32 attributes, - efi_uintn_t data_size, const void *data) +static +efi_status_t EFIAPI efi_set_variable_common(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check, + bool is_non_volatile) { - char *native_name = NULL, *oval, *val = NULL, *s; - size_t oval_size; - efi_status_t ret = EFI_SUCCESS; + char *native_name = NULL, *odata = NULL, *val = NULL, *s; + efi_uintn_t odata_size; + bool append, delete; + u64 time = 0; u32 attr; + efi_status_t ret = EFI_SUCCESS; - EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes, - data_size, data); + debug("%s: set '%s'\n", __func__, native_name); if (!variable_name || !*variable_name || !vendor || ((attributes & EFI_VARIABLE_RUNTIME_ACCESS) && !(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) { ret = EFI_INVALID_PARAMETER; - goto out; + goto err; } ret = efi_to_native(&native_name, variable_name, vendor); if (ret) - goto out; - -#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS) - - if ((data_size == 0) || !(attributes & ACCESS_ATTR)) { - /* delete the variable: */ - env_set(native_name, NULL); - ret = EFI_SUCCESS; - goto out; + goto err; + + /* check if a variable exists */ + odata_size = 0; + attr = 0; + ret = EFI_CALL(efi_get_variable(variable_name, vendor, &attr, + &odata_size, NULL)); + if (ret == EFI_BUFFER_TOO_SMALL) { + if ((is_non_volatile && !(attr & EFI_VARIABLE_NON_VOLATILE)) || + (!is_non_volatile && (attr & EFI_VARIABLE_NON_VOLATILE))) { + ret = EFI_INVALID_PARAMETER; + goto err; + } } - oval = env_get(native_name); - if (oval) { - oval = parse_attr(oval, &attr); + append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); + attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE; + delete = (!data_size || !(attributes & + (EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS))); - if (attr & READ_ONLY) { + /* check attributes */ + if (odata_size) { + if (ro_check && (attr & READ_ONLY)) { ret = EFI_WRITE_PROTECTED; - goto out; + goto err; } /* attributes won't be changed */ - if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) { + if (!delete && + ((ro_check && attr != attributes) || + (!ro_check && ((attr & ~(u32)READ_ONLY) + != (attributes & ~(u32)READ_ONLY))))) { ret = EFI_INVALID_PARAMETER; + goto err; + } + } else { + if (delete || append) { + ret = EFI_NOT_FOUND; + goto err; + } + } + + if (((!u16_strcmp(variable_name, L"PK") || + !u16_strcmp(variable_name, L"KEK")) && + !guidcmp(vendor, &efi_global_variable_guid)) || + ((!u16_strcmp(variable_name, L"db") || + !u16_strcmp(variable_name, L"dbx")) && + !guidcmp(vendor, &efi_guid_image_security_database))) { + /* authentication is mandatory */ + if (!(attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) { + debug("%ls: AUTHENTICATED_WRITE_ACCESS required\n", + variable_name); + ret = EFI_INVALID_PARAMETER; + goto err; + } + } + + /* authenticate a variable */ + if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) { + if (attributes & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) { + ret = EFI_INVALID_PARAMETER; + goto err; + } + if (attributes & + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) { + ret = efi_variable_authenticate(variable_name, vendor, + &data_size, &data, + attributes, &attr, + &time); + if (ret != EFI_SUCCESS) + goto err; + + /* last chance to check for delete */ + if (!data_size) + delete = true; + } + } else { + if (attributes & + (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) { + debug("Secure boot is not configured\n"); + ret = EFI_INVALID_PARAMETER; + goto err; + } + } + + /* delete a variable */ + if (delete) { + ret = EFI_SUCCESS; + if (odata_size) { + val = NULL; goto out; } + ret = EFI_SUCCESS; + goto err; /* not error, but nothing to do */ + } - if (attributes & EFI_VARIABLE_APPEND_WRITE) { - if (!prefix(oval, "(blob)")) { - /* TODO: should support utf8? */ - return EFI_DEVICE_ERROR; - goto out; - } - oval_size = strlen(oval); - } else { - oval_size = 0; + if (append) { + odata = malloc(odata_size); + if (!odata) { + return EFI_OUT_OF_RESOURCES; + goto err; } + ret = EFI_CALL(efi_get_variable(variable_name, vendor, + &attr, &odata_size, odata)); + if (ret != EFI_SUCCESS) + goto err; } else { - oval_size = 0; + odata_size = 0; } - val = malloc(oval_size + 2 * data_size - + strlen("{ro,run,boot,nv}(blob)") + 1); + val = malloc(2 * odata_size + 2 * data_size + + strlen("{ro,run,boot,nv,time=0123456701234567}(blob)") + + 1); if (!val) { ret = EFI_OUT_OF_RESOURCES; - goto out; + goto err; } s = val; - /* store attributes */ - attributes &= (EFI_VARIABLE_NON_VOLATILE | + /* + * store attributes + */ + attributes &= (READ_ONLY | + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | - EFI_VARIABLE_RUNTIME_ACCESS); + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS); s += sprintf(s, "{"); while (attributes) { - u32 attr = 1 << (ffs(attributes) - 1); + attr = 1 << (ffs(attributes) - 1); - if (attr == EFI_VARIABLE_NON_VOLATILE) + if (attr == READ_ONLY) { + s += sprintf(s, "ro"); + } else if (attr == EFI_VARIABLE_NON_VOLATILE) { s += sprintf(s, "nv"); - else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) + } else if (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS) { s += sprintf(s, "boot"); - else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) + } else if (attr == EFI_VARIABLE_RUNTIME_ACCESS) { s += sprintf(s, "run"); + } else if (attr == + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) { + s += sprintf(s, "time="); + s = bin2hex(s, (u8 *)&time, sizeof(time)); + } attributes &= ~attr; if (attributes) s += sprintf(s, ","); } s += sprintf(s, "}"); - - if (oval_size) - /* APPEND_WRITE */ - s += sprintf(s, oval); - else - s += sprintf(s, "(blob)"); + s += sprintf(s, "(blob)"); /* store payload: */ + if (append) + s = bin2hex(s, odata, odata_size); s = bin2hex(s, data, data_size); *s = '\0'; EFI_PRINT("setting: %s=%s\n", native_name, val); - if (env_set(native_name, val)) +out: + if (env_set(native_name, val)) { ret = EFI_DEVICE_ERROR; + } else { + if ((u16_strcmp(variable_name, L"PK") == 0 && + guidcmp(vendor, &efi_global_variable_guid) == 0)) { + ret = efi_transfer_secure_state( + (delete ? EFI_MODE_SETUP : + EFI_MODE_USER)); + if (ret != EFI_SUCCESS) + goto err; + } + ret = EFI_SUCCESS; + } -out: +err: free(native_name); + free(odata); free(val); - return EFI_EXIT(ret); + return ret; +} + +static +efi_status_t EFIAPI efi_set_volatile_variable(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check) +{ + return efi_set_variable_common(variable_name, vendor, attributes, + data_size, data, ro_check, false); +} + +efi_status_t EFIAPI efi_set_nonvolatile_variable(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check) +{ + efi_status_t ret; + + ret = efi_set_variable_common(variable_name, vendor, attributes, + data_size, data, ro_check, true); + + return ret; +} + +static efi_status_t efi_set_variable_internal(u16 *variable_name, + const efi_guid_t *vendor, + u32 attributes, + efi_uintn_t data_size, + const void *data, + bool ro_check) +{ + efi_status_t ret; + + if (attributes & EFI_VARIABLE_NON_VOLATILE) + ret = efi_set_nonvolatile_variable(variable_name, vendor, + attributes, + data_size, data, ro_check); + else + ret = efi_set_volatile_variable(variable_name, vendor, + attributes, data_size, data, + ro_check); + + return ret; +} + +/** + * efi_set_variable() - set value of a UEFI variable + * + * This function implements the SetVariable runtime service. + * + * See the Unified Extensible Firmware Interface (UEFI) specification for + * details. + * + * @variable_name: name of the variable + * @vendor: vendor GUID + * @attributes: attributes of the variable + * @data_size: size of the buffer with the variable value + * @data: buffer with the variable value + * Return: status code + */ +efi_status_t EFIAPI efi_set_variable(u16 *variable_name, + const efi_guid_t *vendor, u32 attributes, + efi_uintn_t data_size, const void *data) +{ + EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes, + data_size, data); + + /* READ_ONLY bit is not part of API */ + attributes &= ~(u32)READ_ONLY; + + return EFI_EXIT(efi_set_variable_internal(variable_name, vendor, + attributes, data_size, data, + true)); } /** From patchwork Wed Sep 18 01:26:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163647 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="zs+Yz5Iw"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Sq22Z3z9s4Y for ; Wed, 18 Sep 2019 11:29:15 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id E5B26C21E44; Wed, 18 Sep 2019 01:26:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id BD320C21E7E; Wed, 18 Sep 2019 01:24:47 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 972ABC21DF3; Wed, 18 Sep 2019 01:24:00 +0000 (UTC) Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.169]) by lists.denx.de (Postfix) with ESMTPS id 3D339C21E68 for ; Wed, 18 Sep 2019 01:23:57 +0000 (UTC) Received: by mail-pf1-f169.google.com with SMTP id q7so3249102pfh.8 for ; Tue, 17 Sep 2019 18:23:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=swpST8Nn3GE5LrbzS4TXgMLJTECIT2jEw26P8rZbo+s=; b=zs+Yz5IwdbGJgSxYJFg/xJuREamK9p/s7KdyQxzJklkRDxQjmFvIwv5uzyKNGxMUdS rNtTUAH0tviNQqL1besZWU9qUMj/j7FmwWm4xin5abE7G8M1zGZ7LDocC6PA8thqc7ZW qvrg2uXxxzZkFocsWSpbIzYJRX4JU5GVvFweeos6OLuH7I3ubcj4VDgvPY/EJzOzvRHV gVlV3cAaoIoWs4PZY+sRUW9nHF2ixQTe8k0R73V3LX/jICVh/YbhEZLsg6CMf8XPM/Ul OhjY6u0uVglBfqCnMQk3JIKYl23pm78kw82ARbKYmSrkojYn/4vM6Zt4yX7DTcw+mpyC rlsw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=swpST8Nn3GE5LrbzS4TXgMLJTECIT2jEw26P8rZbo+s=; b=S1kHLPlGKnfdIAC6fUL1mTdS2gNQwvD4iTcLCTNqlT+r2EKaLF0ukDY9dvF6GS9wA6 V5hieER5Xe19xB8SqbHkGuFaJZ0GdgVtwHG6OrXh6E5bx7svDzcYPu6TbFSghuRCCQ/D RbqXOKg33ap007RJUZ76RFOHSil6YNW1BFvh5qaOfKJs+Kue2ZA8t2utdmO96swtv3Ir mzSoLArn4akgiIopWRox/YW2QJRnWU1+8GlrI1vQGp88EFdsyDev8+NILEqfjHbwcFuw 8AeSbJKUuwCQjktl3BnZnTP+3mUsnsS+c3H28SISLfLe8ew4ae88+ssKb8b7Aym3MxUF PRAQ== X-Gm-Message-State: APjAAAVXx7SG9Kow/ChnIFrqZTEgN9yPDwnxK65qdESSJNUHuBpEivyS i7pCbJzvfjnop3in4DHunBFFOg== X-Google-Smtp-Source: APXvYqzlYgrmQwyL7wvUyH0K1iYAksduz+UdwPLO20EJHIUZ5F/Ffrx3pfndaXxuvdkv1OmpC5R09w== X-Received: by 2002:a17:90a:a116:: with SMTP id s22mr1103130pjp.34.1568769835659; Tue, 17 Sep 2019 18:23:55 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id p68sm9198070pfp.9.2019.09.17.18.23.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:55 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:37 +0900 Message-Id: <20190918012643.25192-10-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 09/15] efi_loader: variable: add VendorKeys and SignatureSupport variables X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Those two variables are well defined UEFI variables: SignatureSupport: array of GUIDs representing the type of signatures supported by the platform firmware VendorKeys: whether the system is configured to use only vendor-provided keys or not Signed-off-by: AKASHI Takahiro --- lib/efi_loader/efi_variable.c | 85 ++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 6 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index fa706f1ad6b8..9b7654bde017 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -28,8 +28,14 @@ enum efi_secure_mode { EFI_MODE_DEPLOYED, }; +static const efi_guid_t signature_types[] = { + /* EFI_CERT_SHA256_GUID, */ + EFI_CERT_X509_GUID, +}; const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID; static bool efi_secure_boot; +static int efi_secure_mode; +static u8 efi_vendor_keys; #define READ_ONLY BIT(31) @@ -337,6 +343,8 @@ static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode) return EFI_INVALID_PARAMETER; } + efi_secure_mode = mode; + return EFI_SUCCESS; err: @@ -347,16 +355,57 @@ err: efi_status_t efi_init_secure_boot(void) { - efi_uintn_t size = 0; + enum efi_secure_mode mode; + efi_uintn_t size; efi_status_t ret; + ret = efi_set_variable_internal(L"SignatureSupport", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS + | READ_ONLY, + sizeof(signature_types), + &signature_types, + false); + if (ret != EFI_SUCCESS) + goto err; + + /* + * TODO: + * Since there is currently no "platform-specific" installation + * method of Platform Key, we can't say if VendorKeys is 0 or 1 + * precisely. + */ + + size = 0; ret = EFI_CALL(efi_get_variable(L"PK", &efi_global_variable_guid, NULL, &size, NULL)); - if (ret == EFI_BUFFER_TOO_SMALL && IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) - ret = efi_transfer_secure_state(EFI_MODE_USER); - else - ret = efi_transfer_secure_state(EFI_MODE_SETUP); + if (ret == EFI_BUFFER_TOO_SMALL) { + if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) + mode = EFI_MODE_USER; + else + mode = EFI_MODE_SETUP; + + efi_vendor_keys = 0; + } else if (ret == EFI_NOT_FOUND) { + mode = EFI_MODE_SETUP; + efi_vendor_keys = 1; + } else { + goto err; + } + ret = efi_transfer_secure_state(mode); + if (ret == EFI_SUCCESS) + ret = efi_set_variable_internal(L"VendorKeys", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS + | READ_ONLY, + sizeof(efi_vendor_keys), + &efi_vendor_keys, + false); + +err: return ret; } @@ -1086,6 +1135,8 @@ out: if (env_set(native_name, val)) { ret = EFI_DEVICE_ERROR; } else { + bool vendor_keys_modified = false; + if ((u16_strcmp(variable_name, L"PK") == 0 && guidcmp(vendor, &efi_global_variable_guid) == 0)) { ret = efi_transfer_secure_state( @@ -1093,8 +1144,30 @@ out: EFI_MODE_USER)); if (ret != EFI_SUCCESS) goto err; + + if (efi_secure_mode != EFI_MODE_SETUP) + vendor_keys_modified = true; + } else if ((u16_strcmp(variable_name, L"KEK") == 0 && + guidcmp(vendor, &efi_global_variable_guid) == 0)) { + if (efi_secure_mode != EFI_MODE_SETUP) + vendor_keys_modified = true; + } + + /* update VendorKeys */ + if (vendor_keys_modified & efi_vendor_keys) { + efi_vendor_keys = 0; + ret = efi_set_variable_internal( + L"VendorKeys", + &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS + | READ_ONLY, + sizeof(efi_vendor_keys), + &efi_vendor_keys, + false); + } else { + ret = EFI_SUCCESS; } - ret = EFI_SUCCESS; } err: From patchwork Wed Sep 18 01:26:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163644 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ehvL+kt/"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Qn5K5fz9s4Y for ; Wed, 18 Sep 2019 11:27:29 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 66EBFC21E7E; Wed, 18 Sep 2019 01:25:36 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E200FC21E8A; Wed, 18 Sep 2019 01:24:30 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 4E06FC21DF3; Wed, 18 Sep 2019 01:24:03 +0000 (UTC) Received: from mail-pl1-f195.google.com (mail-pl1-f195.google.com [209.85.214.195]) by lists.denx.de (Postfix) with ESMTPS id 49DC9C21E5B for ; Wed, 18 Sep 2019 01:24:00 +0000 (UTC) Received: by mail-pl1-f195.google.com with SMTP id t10so2315515plr.8 for ; Tue, 17 Sep 2019 18:24:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=rGsJ0/W0dyNni4CKX0cJphu9PLPe47e2L0nAN3xf9OY=; b=ehvL+kt/lhTucz26B5uaPs3EE2nghlEXbIDIx61n8x1SsRTok529PBpNJVJeT6e5cN LGyg6tpyO/WA34DxQ00YIalf4j4Tqou3ryHP4nkwGCTJCpF5BTxDDDRs1zYy4xUTQbpt KAVtdT18u7qNkMFSBRxmyIq1/FLHrQQrB1jb4JrJQ39o7e3gwxrAr35ufGe75RvsVOSY MCmw5ja+JavLH/LD3AZ0AiI5zLyqDMrKgjQ6g+YuqcSHKFYsQjBaqKGio/iE0aKoUZ8o e0FmsHuMRdhlHtlsRpXewXSvLeAejVoBJoMxVLbxoEv+ZeGZxuCewIWAtsDBAdckkTEj NnQA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rGsJ0/W0dyNni4CKX0cJphu9PLPe47e2L0nAN3xf9OY=; b=AMfPRL29wJcPzmWOgoXc3XLE4LDhIhroy/dP7LtKhnWHGGLprDfm3tOz0f6jw5J6mo NI/zuumpgSE0AiDd4u333kxm5H3mOJLx92tAOFfu8n8MGru619QvE+B5KQWZQxaXcMIr z2Ga4NCRAJNiyNgtj/NQrlwA7Byd/w4tk1SXc1Q3Z2HzcJrbC167ddO5U5O2iy+tPsW5 wa44POAQMphvkeKQq9YCPPaa340jidbfVChi0R+Q8uV68dnXflVVHygY9MjamYZsr7s9 /ISf39sYn/wUk08c7mfEgFqPwW2BeUIRTEW0Pg3r7FmrlILBd/tVNusYNbwyBOTIS9k5 GW+w== X-Gm-Message-State: APjAAAV5L3TgYA0+GqT4RotfCvfRLwKhQDGeVBTm0uKd2KdqzQ1JHEZK 7elGdmBjcvcUPyvIr0ql80nEBQ== X-Google-Smtp-Source: APXvYqxAHDb7bisX47ZSlpkoJkq8jsRKzLW8T+/CCbgxwb1vEeYYjhoU/lTNtSKsv3pF5SDTUyaotQ== X-Received: by 2002:a17:902:fe81:: with SMTP id x1mr1640929plm.66.1568769838514; Tue, 17 Sep 2019 18:23:58 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id f12sm3663079pgo.85.2019.09.17.18.23.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:23:58 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:38 +0900 Message-Id: <20190918012643.25192-11-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 10/15] efi_loader: image_loader: support image authentication X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" With this commit, image validation can be enforced, as UEFI specification section 32.5 describes, if CONFIG_EFI_SECURE_BOOT is enabled. Currently we support * authentication based on db and dbx, so dbx-validated image will always be rejected. * following signature types: EFI_CERT_SHA256_GUID (SHA256 digest for unsigned images) EFI_CERT_X509_GUID (x509 certificate for signed images) Timestamp-based certifcate revocation is not supported here. Internally, authentication data is stored in one of certificates tables of PE image (See efi_image_parse()) and will be verified by efi_image_authenticate(), hence efi_signature_verify_with_db(), before loading a given image. Signed-off-by: AKASHI Takahiro --- include/efi_loader.h | 7 +- lib/efi_loader/efi_boottime.c | 2 +- lib/efi_loader/efi_image_loader.c | 364 +++++++++++++++++++++++++++++- 3 files changed, 366 insertions(+), 7 deletions(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index caac8efba89a..b0e1a3b7902d 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -11,6 +11,7 @@ #include #include #include +#include /* No need for efi loader support in SPL */ #if CONFIG_IS_ENABLED(EFI_LOADER) @@ -385,7 +386,8 @@ efi_status_t efi_set_watchdog(unsigned long timeout); /* Called from places to check whether a timer expired */ void efi_timer_check(void); /* PE loader implementation */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, + void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info); /* Called once to store the pristine gd pointer */ void efi_save_gd(void); @@ -703,6 +705,9 @@ efi_signature_store *efi_sigstore_parse_sigdb(u16 *name); bool efi_secure_boot_enabled(void); efi_status_t efi_init_secure_boot(void); + +bool efi_image_parse(void *efi, size_t len, efi_image_regions **regp, + WIN_CERTIFICATE **auth, size_t *auth_len); #endif /* CONFIG_EFI_SECURE_BOOT */ #else /* CONFIG_IS_ENABLED(EFI_LOADER) */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b9bff894cbba..e27a52493291 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -1879,7 +1879,7 @@ efi_status_t EFIAPI efi_load_image(bool boot_policy, efi_dp_split_file_path(file_path, &dp, &fp); ret = efi_setup_loaded_image(dp, fp, image_obj, &info); if (ret == EFI_SUCCESS) - ret = efi_load_pe(*image_obj, dest_buffer, info); + ret = efi_load_pe(*image_obj, dest_buffer, source_size, info); if (!source_buffer) /* Release buffer to which file was loaded */ efi_free_pages((uintptr_t)dest_buffer, diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index 13541cfa7a28..3004cb34a3cd 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -9,7 +9,13 @@ #include #include +#include #include +/* + * avoid duplicated inclusion: + * #include "../lib/crypto/x509_parser.h" + */ +#include "../lib/crypto/pkcs7_parser.h" const efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; const efi_guid_t efi_guid_device_path = EFI_DEVICE_PATH_PROTOCOL_GUID; @@ -205,6 +211,288 @@ static void efi_set_code_and_data_type( } } +#ifdef CONFIG_EFI_SECURE_BOOT +/* + * Parse image binary in PE32(+) format + * Assuming that sanity of PE image has been checked by a caller. + * + * Return: true on success, false on failure + */ +bool efi_image_parse(void *efi, size_t len, efi_image_regions **regp, + WIN_CERTIFICATE **auth, size_t *auth_len) +{ + efi_image_regions *regs; + IMAGE_DOS_HEADER *dos; + IMAGE_NT_HEADERS32 *nt; + IMAGE_SECTION_HEADER *sections; + int num_sections, i; + int ctidx = IMAGE_DIRECTORY_ENTRY_CERTTABLE; + u32 align, size, authsz, authoff; + size_t bytes_hashed; + + regs = calloc(1, sizeof(*regs)); + if (!regs) + goto err; + + dos = (void *)efi; + nt = (void *)(efi + dos->e_lfanew); + + /* + * Collect data regions for hash calculation + * 1. File headers + */ + if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + IMAGE_NT_HEADERS64 *nt64 = (void *)nt; + IMAGE_OPTIONAL_HEADER64 *opt = &nt64->OptionalHeader; + + /* Skip CheckSum */ + efi_image_region_add(regs, efi, &opt->CheckSum, 0); + if (nt64->OptionalHeader.NumberOfRvaAndSizes <= ctidx) { + efi_image_region_add(regs, + &opt->CheckSum + 1, + efi + opt->SizeOfHeaders, 0); + } else { + /* Skip Certificates Table */ + efi_image_region_add(regs, + &opt->CheckSum + 1, + &opt->DataDirectory[ctidx], 0); + efi_image_region_add(regs, + &opt->DataDirectory[ctidx] + 1, + efi + opt->SizeOfHeaders, 0); + } + + bytes_hashed = opt->SizeOfHeaders; + align = opt->FileAlignment; + authoff = opt->DataDirectory[ctidx].VirtualAddress; + authsz = opt->DataDirectory[ctidx].Size; + } else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + IMAGE_OPTIONAL_HEADER32 *opt = &nt->OptionalHeader; + + efi_image_region_add(regs, efi, &opt->CheckSum, 0); + efi_image_region_add(regs, &opt->CheckSum + 1, + &opt->DataDirectory[ctidx], 0); + efi_image_region_add(regs, &opt->DataDirectory[ctidx] + 1, + efi + opt->SizeOfHeaders, 0); + + bytes_hashed = opt->SizeOfHeaders; + align = opt->FileAlignment; + authoff = opt->DataDirectory[ctidx].VirtualAddress; + authsz = opt->DataDirectory[ctidx].Size; + } else { + debug("%s: Invalid optional header magic %x\n", __func__, + nt->OptionalHeader.Magic); + goto err; + } + + /* 2. Sections */ + num_sections = nt->FileHeader.NumberOfSections; + sections = (void *)((uint8_t *)&nt->OptionalHeader + + nt->FileHeader.SizeOfOptionalHeader); + for (i = 0; i < num_sections; i++) { + if (!sections[i].SizeOfRawData) + continue; + + /* TODO: ensure ascending order */ + size = (sections[i].SizeOfRawData + align - 1) & ~(align - 1); + efi_image_region_add(regs, efi + sections[i].PointerToRawData, + efi + sections[i].PointerToRawData + size, + 0); + debug("section[%d](%s): raw: 0x%x-0x%x, virt: %x-%x\n", + i, sections[i].Name, + sections[i].PointerToRawData, + sections[i].PointerToRawData + size, + sections[i].VirtualAddress, + sections[i].VirtualAddress + + sections[i].Misc.VirtualSize); + + bytes_hashed += size; + } + + /* 3. Extra data excluding Certificates Table */ + if (bytes_hashed + authsz < len) { + debug("extra data for hash: %lu\n", + len - (bytes_hashed + authsz)); + efi_image_region_add(regs, efi + bytes_hashed, + efi + len - authsz, 0); + } + + /* Return Certificates Table */ + if (authsz) { + if (len < authoff + authsz) { + debug("%s: Size for auth too large: %u >= %zu\n", + __func__, authsz, len - authoff); + goto err; + } + if (authsz < sizeof(*auth)) { + debug("%s: Size for auth too small: %u < %zu\n", + __func__, authsz, sizeof(*auth)); + goto err; + } + *auth = efi + authoff; + *auth_len = authsz; + debug("WIN_CERTIFICATE: 0x%x, size: 0x%x\n", authoff, authsz); + } else { + *auth = NULL; + *auth_len = 0; + } + + *regp = regs; + + return true; + +err: + free(regs); + + return false; +} + +/* + * Authenticate unsigned image with SHA256 hash + * + * Return: true on success, false on failure + */ +static bool efi_image_unsigned_authenticate(efi_image_regions *regs) +{ + efi_signature_store *db; + bool ret; + + /* try black-list */ + ret = true; + db = efi_sigstore_parse_sigdb(L"dbx"); + if (db) { + if (efi_signature_verify_with_db(regs, NULL, db)) { + debug("Image is not signed and rejected by \"dbx\"\n"); + ret = false; + } + + efi_sigstore_free(db); + } else { + debug("Getting signature database(dbx) failed\n"); + } + + if (!ret) + goto out; + + /* try white-list */ + ret = false; + db = efi_sigstore_parse_sigdb(L"db"); + if (db) { + if (efi_signature_verify_with_db(regs, NULL, db)) + ret = true; + else + debug("Image is not signed and not found in \"db\" or \"dbx\"\n"); + + efi_sigstore_free(db); + } else { + debug("Getting signature database(db) failed\n"); + } + +out: + return ret; +} + +/* + * TODO: + * When AuditMode==0, if the image's signature is not found in + * the authorized database, or is found in the forbidden database, + * the image will not be started and instead, information about it + * will be placed in this table. + * When AuditMode==1, an EFI_IMAGE_EXECUTION_INFO element is created + * in the EFI_IMAGE_EXECUTION_INFO_TABLE for every certificate found + * in the certificate table of every image that is validated. + * + * Return: true on success, false on failure + */ +static bool efi_image_authenticate(void *efi, size_t len) +{ + efi_image_regions *regs = NULL; + WIN_CERTIFICATE *wincerts = NULL, *wincert; + size_t wincerts_len; + struct pkcs7_message *msg = NULL; + efi_signature_store *db = NULL, *dbx = NULL; + bool ret = false; + + if (!efi_secure_boot_enabled()) + return true; + + if (!efi_image_parse(efi, len, ®s, &wincerts, + &wincerts_len)) { + debug("Parsing PE executable image failed\n"); + return false; + } + + if (!wincerts) { + /* The image is not signed */ + ret = efi_image_unsigned_authenticate(regs); + free(regs); + + return ret; + } + + /* + * verify signature using db and dbx + */ + db = efi_sigstore_parse_sigdb(L"db"); + if (!db) { + debug("Getting signature database(db) failed\n"); + goto err; + } + + dbx = efi_sigstore_parse_sigdb(L"dbx"); + if (!dbx) { + /* FIXME: error or not found? */ + debug("Getting signature database(dbx) failed\n"); + goto err; + } + + /* go through WIN_CERTIFICATE list */ + for (wincert = wincerts; + (void *)wincert < (void *)wincerts + wincerts_len; + wincert = (void *)wincert + ALIGN(wincert->dwLength, 8)) { + if (wincert->dwLength < sizeof(*wincert)) { + debug("%s: dwLength too small: %u < %zu\n", + __func__, wincert->dwLength, sizeof(*wincert)); + goto err; + } + msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert), + wincert->dwLength - sizeof(*wincert)); + if (!msg) { + debug("Parsing image's signature failed\n"); + goto err; + } + + /* try black-list first */ + if (dbx) { + if (efi_signature_revoke(regs, msg, dbx, NULL)) { + debug("Signature was revoked by \"dbx\"\n"); + goto err; + } + } + + /* try white-list */ + if (db) { + if (!efi_signature_verify_with_db(regs, msg, db)) + debug("Verifying signature with \"db\" failed\n"); + else + ret = true; + } + } + +err: + efi_sigstore_free(db); + efi_sigstore_free(dbx); + pkcs7_free_message(msg); + free(regs); + + return ret; +} +#else +static bool efi_image_authenticate(void *efi, size_t len) +{ + return true; +} +#endif /* CONFIG_EFI_SECURE_BOOT */ + /** * efi_load_pe() - relocate EFI binary * @@ -216,7 +504,8 @@ static void efi_set_code_and_data_type( * @loaded_image_info: loaded image protocol * Return: status code */ -efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, +efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, + void *efi, size_t efi_size, struct efi_loaded_image *loaded_image_info) { IMAGE_NT_HEADERS32 *nt; @@ -232,15 +521,56 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, unsigned long virt_size = 0; int supported = 0; + /* + * Size must be 8-byte aligned and the trailing bytes must be + * zero'ed. Otherwise hash value may be incorrect. + */ + if (efi_size & 0x7) { + void *new_efi; + size_t new_efi_size; + + new_efi_size = (efi_size + 0x7) & ~0x7ULL; + new_efi = calloc(new_efi_size, 1); + if (!new_efi) + return EFI_OUT_OF_RESOURCES; + memcpy(new_efi, efi, efi_size); + efi = new_efi; + efi_size = new_efi_size; + /* TODO: free */ + } + + /* Sanity check for a file header */ + if (efi_size < sizeof(*dos)) { + printf("%s: Truncated DOS Header\n", __func__); + + return EFI_LOAD_ERROR; + } + dos = efi; if (dos->e_magic != IMAGE_DOS_SIGNATURE) { printf("%s: Invalid DOS Signature\n", __func__); + + return EFI_LOAD_ERROR; + } + + /* assume sizeof(IMAGE_NT_HEADERS32) <= sizeof(IMAGE_NT_HEADERS64) */ + if (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS32)) { + printf("%s: Invalid offset for Extended Header\n", __func__); + return EFI_LOAD_ERROR; } nt = (void *) ((char *)efi + dos->e_lfanew); + if ((nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) && + (efi_size < dos->e_lfanew + sizeof(IMAGE_NT_HEADERS64))) { + printf("%s: Invalid offset for Extended Header\n", __func__); + + return EFI_LOAD_ERROR; + } + if (nt->Signature != IMAGE_NT_SIGNATURE) { printf("%s: Invalid NT Signature\n", __func__); + return EFI_LOAD_ERROR; } @@ -253,14 +583,32 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!supported) { printf("%s: Machine type 0x%04x is not supported\n", __func__, nt->FileHeader.Machine); + return EFI_LOAD_ERROR; } - /* Calculate upper virtual address boundary */ num_sections = nt->FileHeader.NumberOfSections; sections = (void *)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader; + if (efi_size < ((void *)sections + sizeof(sections[0]) * num_sections + - efi)) { + printf("%s: Invalid number of sections: %d\n", + __func__, num_sections); + + return EFI_LOAD_ERROR; + } + + /* + * Authenticate an image + * TODO: + * If authentication fails, relevant information must be + * recorded in executable information table. + */ + if (!efi_image_authenticate(efi, efi_size)) + return EFI_ACCESS_DENIED; + + /* Calculate upper virtual address boundary */ for (i = num_sections - 1; i >= 0; i--) { IMAGE_SECTION_HEADER *sec = §ions[i]; virt_size = max_t(unsigned long, virt_size, @@ -279,6 +627,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); + return EFI_OUT_OF_RESOURCES; } handle->entry = efi_reloc + opt->AddressOfEntryPoint; @@ -295,6 +644,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, if (!efi_reloc) { printf("%s: Could not allocate %lu bytes\n", __func__, virt_size); + return EFI_OUT_OF_RESOURCES; } handle->entry = efi_reloc + opt->AddressOfEntryPoint; @@ -304,13 +654,16 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, } else { printf("%s: Invalid optional header magic %x\n", __func__, nt->OptionalHeader.Magic); + return EFI_LOAD_ERROR; } /* Copy PE headers */ - memcpy(efi_reloc, efi, sizeof(*dos) + sizeof(*nt) - + nt->FileHeader.SizeOfOptionalHeader - + num_sections * sizeof(IMAGE_SECTION_HEADER)); + memcpy(efi_reloc, efi, + sizeof(*dos) + + sizeof(*nt) + + nt->FileHeader.SizeOfOptionalHeader + + num_sections * sizeof(IMAGE_SECTION_HEADER)); /* Load sections into RAM */ for (i = num_sections - 1; i >= 0; i--) { @@ -327,6 +680,7 @@ efi_status_t efi_load_pe(struct efi_loaded_image_obj *handle, void *efi, (unsigned long)image_base) != EFI_SUCCESS) { efi_free_pages((uintptr_t) efi_reloc, (virt_size + EFI_PAGE_MASK) >> EFI_PAGE_SHIFT); + return EFI_LOAD_ERROR; } From patchwork Wed Sep 18 01:26:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163649 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ug5JmfS9"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2V60HyGz9sCJ for ; Wed, 18 Sep 2019 11:30:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 605D8C21EBA; Wed, 18 Sep 2019 01:25:25 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 2B237C21E9F; Wed, 18 Sep 2019 01:24:24 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 3960CC21C29; Wed, 18 Sep 2019 01:24:05 +0000 (UTC) Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by lists.denx.de (Postfix) with ESMTPS id 79642C21EC2 for ; Wed, 18 Sep 2019 01:24:02 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id u17so2990919pgi.6 for ; Tue, 17 Sep 2019 18:24:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=fCfmfPvXvHQ6Y2+STlqkdKqEtGQaUITTmrJrDO65JZY=; b=ug5JmfS9EK136tlBooUNGGMVtlSFPh0ZY7JCJrbBFgIsSNUYIBqI98dbDL9v3NHcpT 2vGZQoh+Rx6tct6QwTxaFHyX/yHCAQ2spS/5azjSw5GLsEIyxO5HqBmQIyduT+wl8DpY NdPcN96Fjm9W3CuAXPV8DpPmJ6mmnKypoUvQCV7fXl4pvuxZGfCEDsxl9HhTVXbzkuz5 CRKgE0u0YUtkeKkoO8bZlFiC3zb77clgvc4e8qzaY067lN5xAhRzlEGz6ZtxA8buPKTB y3R2Xg7YPI0JsCvJzW95qluy0wNIPjwwqrZkq+3ct1KakkWwB3XA8PeUzbCmvLQhfjxu XwXQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fCfmfPvXvHQ6Y2+STlqkdKqEtGQaUITTmrJrDO65JZY=; b=s83NKc6y/mhexb5S85Wa6ZZrHU5OCiVVM463ZLR5uIcWpk3qCGbZ/h16FrQmInshOQ jgYiXLP6aUUqVoxFvYY4uokOFgUdMZY9ZEaXRUlpkwFhkZfh0Ql71hK/BUZF4ORE+Aj1 br/ipzBS+g8FPdft6dTgNSKZO/Vcbv+bMsqv8XNC4li3l1Kk+bmVnVGyQtCLh3iyWafI Kg1I1vfDx5q17b1SY98Yw3l/DXyMJUiRxrbMdnXegFLBITx6oP9SXLZbpmNRc2ZBDyjr Pm4AK1EhsjDwKg/luACsICM5zTKbx+oLfQ3T0Sr2ZCUro4YKOTdTQbz4vh6tZwbJUi0U 4dqA== X-Gm-Message-State: APjAAAXFr8bhhBSUtIfDrJUdrlJfa03RLZLlDx2CI2xLMiWKWrFG1pI8 hq8W2tz2Hwfi1DKBCCSEeKq93Q== X-Google-Smtp-Source: APXvYqwSCH2P2uZOWJ8qghhPmlCA0h7GpbxOpFx7fjYFuxH5RetgjPpuGizIFZ8/YMoRR3lK6ux2BA== X-Received: by 2002:a17:90a:5aa1:: with SMTP id n30mr1046471pji.82.1568769841195; Tue, 17 Sep 2019 18:24:01 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id a11sm4159035pfg.94.2019.09.17.18.24.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:24:00 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:39 +0900 Message-Id: <20190918012643.25192-12-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 11/15] efi_loader: initialize secure boot state X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" We call efi_init_secure_boot() after loading saved UEFI variables so that the initial secure boot status will be initialized. Signed-off-by: AKASHI Takahiro --- lib/efi_loader/efi_setup.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 0d915ba386da..de8f0bd7e68e 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -132,6 +132,11 @@ efi_status_t efi_init_obj_list(void) if (ret != EFI_SUCCESS) goto out; + /* Secure boot */ + ret = efi_init_secure_boot(); + if (ret != EFI_SUCCESS) + goto out; + /* Indicate supported runtime services */ ret = efi_init_runtime_supported(); if (ret != EFI_SUCCESS) From patchwork Wed Sep 18 01:26:40 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163653 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wWdKfx2v"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Wv4KPmz9sCJ for ; Wed, 18 Sep 2019 11:31:55 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 53AA0C2204B; Wed, 18 Sep 2019 01:28:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 00589C21DAF; Wed, 18 Sep 2019 01:28:15 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 16C39C2200D; Wed, 18 Sep 2019 01:24:08 +0000 (UTC) Received: from mail-pl1-f194.google.com (mail-pl1-f194.google.com [209.85.214.194]) by lists.denx.de (Postfix) with ESMTPS id 328F2C21E57 for ; Wed, 18 Sep 2019 01:24:05 +0000 (UTC) Received: by mail-pl1-f194.google.com with SMTP id x6so839576plv.6 for ; Tue, 17 Sep 2019 18:24:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bVQVGDg1oulOFv0ADnZkVHZK+1zNMaDEicjYv6u1RFA=; b=wWdKfx2vf3iMHJPL3uNTrwSZM+fM+CwhyuSaHY8b/BxKWDxpwvZ4P9jZRQ1SZj1BIQ XJHFBO2I9FJwfs3FaPajw5/QyvOUZddN4YjZrqKxj2StXj7TpTJXlbJ5FanNLpFR4b90 AejYDy0BU1dwOIFOTZ39u/oA2l2ZBy7ikUGUGB3KGniSAolsgOUqUazKRumYdHgwcZa0 To0v4FfFt7noSRWzjA9ISU7QiKLcq9a/pMeLm+MG//XZGH12NkGGi21UCe0cv7HKvbwK NVPq9njTYcSYerXAXPT/6Zb354b7TvfzGUxprs1oiwjdq7DeCHFB6OOOvk/43VpyN1dD 8q7A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bVQVGDg1oulOFv0ADnZkVHZK+1zNMaDEicjYv6u1RFA=; b=Nk2iUdrUd+fsbk8vwq/4gDGvbzmbwN4v3XYxkrPEojSMm+GtnJ1gp9EbFp3qCKkJWj FKF2KoNfRos5KvmSvAr7sIJ9nbZ43DPoklt8z+zy+L5SdsQh6hPe5ggundv6yxUXba8a 1OnNs2oEP5Jj1SqN8tnDqtRgrQhWDSKn6IGwuUVqmaXTbHkg77kgVpeYJvWlR/ujE0Mk PEsH3XwMZB6bZC4aHd6gtvE/CYQZYAO29IqnSILYBk8+SxioJqgKS2xQy54KCcmejnpP gl1i2QbX8IT4fhYccE8OuZR0cIwZ3NXEUhkAtvujkHUnkYPUJXY/ui2RW/fOG75eB7FA 13QQ== X-Gm-Message-State: APjAAAUOsGl426UZaeZFnjlHjEgsfPdSkB4JUcsn4ExRFhMTjEGAn21j oTAdDj4qHXqXcYQf7PkOkfgcAwxiWPs= X-Google-Smtp-Source: APXvYqzhgcHBlf2K/dclnmE2J+hWvjPvwc7h5Ns43xRZR8wQhrxIKZQq5PMYulLN9TN9i5viRBwaUw== X-Received: by 2002:a17:902:8d81:: with SMTP id v1mr1615853plo.23.1568769843899; Tue, 17 Sep 2019 18:24:03 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id c62sm6954482pfa.92.2019.09.17.18.24.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:24:03 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:40 +0900 Message-Id: <20190918012643.25192-13-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 12/15] efi_loader: add CONFIG_EFI_SECURE_BOOT X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Now we can enable UEFI secure boot with this option. Signed-off-by: AKASHI Takahiro --- lib/efi_loader/Kconfig | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c7027a967653..fb66766d2b7a 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -115,4 +115,17 @@ config EFI_GRUB_ARM32_WORKAROUND GRUB prior to version 2.04 requires U-Boot to disable caches. This workaround currently is also needed on systems with caches that cannot be managed via CP15. + +config EFI_SECURE_BOOT + bool "Enable EFI secure boot support" + depends on EFI_LOADER + depends on SECURE_BOOT + imply RSA_VERIFY_WITH_PKEY + default n + help + Select this option to enable EFI secure boot support. + Once SecureBoot mode is enforced, any EFI binary can run only if + it is signed with a trusted key. To do that, you need to install, + at least, PK, KEK and db. + endif From patchwork Wed Sep 18 01:26:41 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163648 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="UeW7uGrC"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2TJ6Bkkz9s4Y for ; Wed, 18 Sep 2019 11:29:40 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 9984AC2209D; Wed, 18 Sep 2019 01:28:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 737FEC21E1E; Wed, 18 Sep 2019 01:27:55 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 14476C21DAF; Wed, 18 Sep 2019 01:24:10 +0000 (UTC) Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) by lists.denx.de (Postfix) with ESMTPS id 13472C21D72 for ; Wed, 18 Sep 2019 01:24:08 +0000 (UTC) Received: by mail-pf1-f180.google.com with SMTP id 205so3266030pfw.2 for ; Tue, 17 Sep 2019 18:24:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=lpT0i+omjdd1fCw1v5ryFUmN/toLIUPG52wfp5+OhmM=; b=UeW7uGrCroQINMd6dUMCSf7EAkUs6gMOkvAJ8RXZK+/E/M/rA5L9j54rBzysZ6isi2 tv002kQvf77gsj63NYs+OUIN7KmUkRgh9f/3Wo/HrrnrS7GI3dGmvhFoYVfYB5T4MlQw Am0KTTeryeOJ5mp1cssH5iLhQaB8Osoe8ACViWvfCBdDkWMX8ow61oqgutVB4g2FYimk tjlLr8JPXCXPWYEv5nIt9H46XXCK+PIR+DWBOdqxQceV4/chL4xNauybEcsb3L5uO2n7 QRhkAjjP+TAhfoGAMEUR1Q00qzE4qPTZI40g6Qfgb7Ni+RBrArbZ5vrkP9yz3Uh3aXZb oBYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=lpT0i+omjdd1fCw1v5ryFUmN/toLIUPG52wfp5+OhmM=; b=tTGxxJSEVYdma7qw/K+x/TIDN1nEM9ipfnzJwNL5eYOROXpX1TSg+wCO/ZRBeVgaq7 q3bJes5EC5nfrHS9eCetmwCDxbqQTUFH+3+jfF/NNY0ozeQ5qnuvuIJ8+wSn/nxozgpZ 6VMLoARdJYTdT9EJOPunUcGV3ROMIFksDYGo/BdAQSHxbZie8YnYBipwiqpYHRCeERfU IwBoA9b8J633XdjfGZs9Zm4j2k340Rzls82G0PVEb0MuffU6Ab51t+8X5LXDjceGHDlr 7/ungsVcsxjRK0Vk7XN6wpu7rrr0ar6PJgvsaFJBHJFJiHX6cSkXOfutjQ9BM7HGBxN0 Zb2Q== X-Gm-Message-State: APjAAAWKoDRRQl1NjuJO/j7XJzeAvQC/hw/ajyhgQlWyCmWMDk9QjyRo 6NCssScWKG+gZ1UlLFpuTei4cg== X-Google-Smtp-Source: APXvYqwqhDeCfOSdFVxSdHsAgcXv4aj9wEwYQ02hz/ekAm/DAz8CMTbf2WTwwkJsVrc5/OW1pmORng== X-Received: by 2002:a65:6259:: with SMTP id q25mr1622395pgv.145.1568769846653; Tue, 17 Sep 2019 18:24:06 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id j1sm399894pjs.28.2019.09.17.18.24.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:24:06 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:41 +0900 Message-Id: <20190918012643.25192-14-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 13/15] cmd: env: provide appropriate guid for well-defined variable X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Any signature database variable is associated with a specific guid. For convenience, if user doesn't supply any guid info, "env set|print -e" should complement it. Signed-off-by: AKASHI Takahiro --- cmd/nvedit_efi.c | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/cmd/nvedit_efi.c b/cmd/nvedit_efi.c index 4532124c33d0..a4dbf37f3f2e 100644 --- a/cmd/nvedit_efi.c +++ b/cmd/nvedit_efi.c @@ -41,6 +41,11 @@ static const struct { } efi_guid_text[] = { /* signature database */ {EFI_GLOBAL_VARIABLE_GUID, "EFI_GLOBAL_VARIABLE_GUID"}, + {EFI_IMAGE_SECURITY_DATABASE_GUID, "EFI_IMAGE_SECURITY_DATABASE_GUID"}, + /* certificate type */ + {EFI_CERT_SHA256_GUID, "EFI_CERT_SHA256_GUID"}, + {EFI_CERT_X509_GUID, "EFI_CERT_X509_GUID"}, + {EFI_CERT_TYPE_PKCS7_GUID, "EFI_CERT_TYPE_PKCS7_GUID"}, }; /* "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" */ @@ -135,6 +140,7 @@ static int efi_dump_vars(int argc, char * const argv[], bool verbose) { u16 *var_name16, *p; efi_uintn_t buf_size, size; + efi_guid_t *guid; buf_size = 128; var_name16 = malloc(buf_size); @@ -156,9 +162,13 @@ static int efi_dump_vars(int argc, char * const argv[], bool verbose) p = var_name16; utf8_utf16_strcpy(&p, argv[0]); - efi_dump_single_var(var_name16, - (efi_guid_t *)&efi_global_variable_guid, - verbose); + if (!strcmp(argv[0], "db") || !strcmp(argv[0], "dbx") || + !strcmp(argv[0], "dbt")) + guid = (efi_guid_t *)&efi_guid_image_security_database; + else + guid = (efi_guid_t *)&efi_global_variable_guid; + + efi_dump_single_var(var_name16, guid, verbose); } free(var_name16); @@ -167,7 +177,7 @@ static int efi_dump_vars(int argc, char * const argv[], bool verbose) } /** - * efi_dump_vars() - show information about all the UEFI variables + * efi_dump_var_all() - show information about all the UEFI variables * * @verbose: if true, dump data * Return: CMD_RET_SUCCESS on success, or CMD_RET_RET_FAILURE @@ -463,9 +473,9 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (*ep != ',') return CMD_RET_USAGE; + /* 0 should be allowed for delete */ size = simple_strtoul(++ep, NULL, 16); - if (!size) - return CMD_RET_FAILURE; + value_on_memory = true; } else if (!strcmp(argv[0], "-v")) { verbose = true; @@ -477,8 +487,13 @@ int do_env_set_efi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return CMD_RET_USAGE; var_name = argv[0]; - if (default_guid) - guid = efi_global_variable_guid; + if (default_guid) { + if (!strcmp(var_name, "db") || !strcmp(var_name, "dbx") || + !strcmp(var_name, "dbt")) + guid = efi_guid_image_security_database; + else + guid = efi_global_variable_guid; + } if (verbose) { printf("GUID: %s\n", efi_guid_to_str(&guid)); From patchwork Wed Sep 18 01:26:42 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163651 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="hT8rS/z7"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2WF650Rz9s4Y for ; Wed, 18 Sep 2019 11:31:21 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 79215C22078; Wed, 18 Sep 2019 01:27:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id A8361C21FF6; Wed, 18 Sep 2019 01:27:45 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id A4FB3C21E1E; Wed, 18 Sep 2019 01:24:15 +0000 (UTC) Received: from mail-pl1-f195.google.com (mail-pl1-f195.google.com [209.85.214.195]) by lists.denx.de (Postfix) with ESMTPS id 2B2FEC21E5B for ; Wed, 18 Sep 2019 01:24:11 +0000 (UTC) Received: by mail-pl1-f195.google.com with SMTP id t10so2315743plr.8 for ; Tue, 17 Sep 2019 18:24:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MJVaNwJCGO/pNUvoAUKAhnn7wY5XuRywW1QfG1Gxnfc=; b=hT8rS/z7lnjvbJUBEcbJicZIe0/8Ismbqi2qcYdkParrD7CYq0m+HQpRXVZ982IQQ5 ZBBmrAc4TNvDmIARv3vCpXOppjRPXQ0f7mrPBhzWViP4kNLGawOhjdlgqA7SqopmghEA azkZN2Wbk3op51/Pjr1SOqWjzXVs0TaXYy0HtIT8Q+nzibBwqsMTx17R8WCNuCDKhowY CpaL+mOT4a0zA2Z+nz2Ver2LmIw+ZTL2SUNHnkgJrxnUUUNDkv8+diAsg3Vn74QTsyn6 I8yIB0R97X4K7DUno+AYlYFTtNXys5rVAHqEkycHaq3AXxDDOtkio0D2gdC7uGX3kCHk LGmw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MJVaNwJCGO/pNUvoAUKAhnn7wY5XuRywW1QfG1Gxnfc=; b=kN0JN8TgCumDZhe5i/HgF8gl1nFQ2arPZe0FPTzND7UGrtuLCWKOzQKBh+UT9hlHR1 BoIZqRcSucDasmwKPrO0dysq5r+OVKy0TFXVtaMvM/wxS/xcNM2v1ZCC6CVcE9/qBf/X Sawk+qte5sPYzSUIlnavq30iErzM/OxGG21ZvgGrscbRkJJLDDdAWFYu5ccVQYAybIk2 atS80FSrUPCJlCMaFAqqoV8eK6Sw7nfPE07ljPpJbOK9oxgUTjNeBby3GUdwraAnMEpl LzZHkFj59du2F9HjLEifm9sWtejAHc4ObqdIV8o9TSDJgQDtmeVs4PAU6yrGSTPxgX7s CxpQ== X-Gm-Message-State: APjAAAWGpb3K4vT1nwDHatMtAbBWhdtt0ILofnvN9UDQfSdzN0y1GBBK rJuOn6orlMDLhV0RUm2KruC22g== X-Google-Smtp-Source: APXvYqwl9jO5IJehWHCQlhGzYJ1Ltu/NUcwaT+PeqWy3MMSZ4hKOyVZPQw5ZGugWt7zVs/2oN4N4OQ== X-Received: by 2002:a17:902:8d8d:: with SMTP id v13mr1594604plo.137.1568769849632; Tue, 17 Sep 2019 18:24:09 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id x72sm4201676pfc.89.2019.09.17.18.24.08 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:24:09 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:42 +0900 Message-Id: <20190918012643.25192-15-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 14/15] efi_loader, pytest: add UEFI secure boot tests (image) X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" test_efi_secboot/test_signed.py: provide test cases of image authentication for signed images test_efi_secboot/test_unsigned.py: provide test cases of image authentication for unsigned images This test relies on efitools and user should compile it on his own. (Currently some local change has been applied.) Signed-off-by: AKASHI Takahiro --- test/py/tests/test_efi_secboot/conftest.py | 168 ++++++++++++++++++ test/py/tests/test_efi_secboot/defs.py | 7 + test/py/tests/test_efi_secboot/test_signed.py | 97 ++++++++++ .../tests/test_efi_secboot/test_unsigned.py | 126 +++++++++++++ 4 files changed, 398 insertions(+) create mode 100644 test/py/tests/test_efi_secboot/conftest.py create mode 100644 test/py/tests/test_efi_secboot/defs.py create mode 100644 test/py/tests/test_efi_secboot/test_signed.py create mode 100644 test/py/tests/test_efi_secboot/test_unsigned.py diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py new file mode 100644 index 000000000000..3806f305a138 --- /dev/null +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -0,0 +1,168 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro + +import os +import os.path +import pytest +import re +from subprocess import call, check_call, check_output, CalledProcessError +from defs import * + +# +# Helper functions +# +def mk_fs(config, fs_type, size, id): + """Create a file system volume. + + Args: + fs_type: File system type. + size: Size of file system in MiB. + id: Prefix string of volume's file name. + + Return: + Nothing. + """ + fs_img = '%s.%s.img' % (id, fs_type) + fs_img = config.persistent_data_dir + '/' + fs_img + + if fs_type == 'fat16': + mkfs_opt = '-F 16' + elif fs_type == 'fat32': + mkfs_opt = '-F 32' + elif fs_type == 'ext4': + mkfs_opt = '-O ^metadata_csum' + else: + mkfs_opt = '' + + if re.match('fat', fs_type): + fs_lnxtype = 'vfat' + else: + fs_lnxtype = fs_type + + count = (size + 1048576 - 1) / 1048576 + + try: + check_call('rm -f %s' % fs_img, shell=True) + check_call('dd if=/dev/zero of=%s bs=1M count=%d' + % (fs_img, count), shell=True) + check_call('mkfs.%s %s %s' + % (fs_lnxtype, mkfs_opt, fs_img), shell=True) + return fs_img + except CalledProcessError: + call('rm -f %s' % fs_img, shell=True) + raise + +# from test/py/conftest.py +def tool_is_in_path(tool): + """Check whether a given command is available on host. + + Args: + tool: Command name. + + Return: + True if available, False if not. + """ + for path in os.environ['PATH'].split(os.pathsep): + fn = os.path.join(path, tool) + if os.path.isfile(fn) and os.access(fn, os.X_OK): + return True + return False + +fuse_mounted = False + +def mount_fs(fs_type, device, mount_point): + """Mount a volume. + + Args: + fs_type: File system type. + device: Volume's file name. + mount_point: Mount point. + + Return: + Nothing. + """ + global fuse_mounted + + fuse_mounted = False + try: + if tool_is_in_path('guestmount'): + fuse_mounted = True + check_call('guestmount -a %s -m /dev/sda %s' + % (device, mount_point), shell=True) + else: + mount_opt = 'loop,rw' + if re.match('fat', fs_type): + mount_opt += ',umask=0000' + + check_call('sudo mount -o %s %s %s' + % (mount_opt, device, mount_point), shell=True) + + # may not be effective for some file systems + check_call('sudo chmod a+rw %s' % mount_point, shell=True) + except CalledProcessError: + raise + +def umount_fs(mount_point): + """Unmount a volume. + + Args: + mount_point: Mount point. + + Return: + Nothing. + """ + if fuse_mounted: + call('sync') + call('guestunmount %s' % mount_point, shell=True) + else: + call('sudo umount %s' % mount_point, shell=True) + +# +# Fixture for TestEfiSignedImage test +# +# NOTE: yield_fixture was deprecated since pytest-3.0 +@pytest.yield_fixture() +def efi_boot_env(request, u_boot_config): + """Set up a file system to be used in basic fs test. + + Args: + request: Pytest request object. + u_boot_config: U-boot configuration. + + Return: + A fixture for basic fs test, i.e. a triplet of file system type, + volume file name and a list of MD5 hashes. + """ + fs_type = 'fat32' + fs_img = '' + + mount_dir = u_boot_config.persistent_data_dir + '/mnt' + + try: + + # test volume + fs_img = mk_fs(u_boot_config, 'fat32', TEST_VOL_SIZE, 'test') + + # Mount the image so we can populate it. + check_output('mkdir -p %s' % mount_dir, shell=True) + mount_fs(fs_type, fs_img, mount_dir) + + # Copy files + check_output('cp %s/*.efi %s' % (EFITOOLS_PATH, mount_dir), shell=True) + check_output('cp %s/PK* %s' % (EFITOOLS_PATH, mount_dir), shell=True) + check_output('cp %s/noPK* %s' % (EFITOOLS_PATH, mount_dir), shell=True) + check_output('cp %s/KEK* %s' % (EFITOOLS_PATH, mount_dir), shell=True) + check_output('cp %s/DB* %s' % (EFITOOLS_PATH, mount_dir), shell=True) + + umount_fs(mount_dir) + except CalledProcessError as e: + pytest.skip('Setup failed: %s' % e.cmd) + return + else: + yield fs_img + finally: + umount_fs(mount_dir) + call('rmdir %s' % mount_dir, shell=True) + if fs_img: + call('rm -f %s' % fs_img, shell=True) diff --git a/test/py/tests/test_efi_secboot/defs.py b/test/py/tests/test_efi_secboot/defs.py new file mode 100644 index 000000000000..cbe99ef3a6ba --- /dev/null +++ b/test/py/tests/test_efi_secboot/defs.py @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0+ + +# 64MiB +TEST_VOL_SIZE=0x4000000 + +# efitools build directory +EFITOOLS_PATH='/home/akashi/x86/efitools' diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py new file mode 100644 index 000000000000..05b193a5266b --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_signed.py @@ -0,0 +1,97 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Signed Image Authentication Test + +""" +This test verifies image authentication for signed images. +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.slow +class TestEfiSignedImage(object): + def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - authenticated by DB + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 1a'): + # Test Case 1a, run signed image if no DB/DBX + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 HELLO1 host 0:0 /HelloWorld_simple-signed.efi ""', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('Hello World!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1b'): + # Test Case 1b, run unsigned image if no DB/DBX + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO2 host 0:0 /HelloWorld_simple.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('Hello World!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1c'): + # Test Case 1c, not authenticated by DB + output = u_boot_console.run_command_list([ + 'efidebug boot add 3 UPDV host 0:0 /UpdateVars.efi ""', + 'setenv bootargs "cmd db DB.auth"', + 'efidebug boot next 3', + 'bootefi bootmgr', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 3', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 3', + 'bootefi bootmgr', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(not re.search('Hello World!', ''.join(output))) + + with u_boot_console.log.section('Test Case 1d'): + # Test Case 1d, authenticated by DB + output = u_boot_console.run_command_list([ + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(re.search('Hello World!', ''.join(output))) + + def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env): + """ + Test Case 2 - rejected by DBX + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 2a'): + # Test Case 2a, rejected by DBX + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 UPDV host 0:0 /UpdateVars-signed.efi ""', + 'setenv bootargs "cmd dbx DB.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'efidebug boot add 2 HELLO1 host 0:0 /HelloWorld_simple-signed.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(not re.search('Hello World!', ''.join(output))) + + with u_boot_console.log.section('Test Case 2b'): + # Test Case 2b, rejected by DBX even if DB allows + output = u_boot_console.run_command_list([ + 'setenv bootargs "cmd db DB.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(not re.search('Hello World!', ''.join(output))) diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py new file mode 100644 index 000000000000..232793e431b3 --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_unsigned.py @@ -0,0 +1,126 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Signed Image Authentication Test + +""" +This test verifies image authentication for unsigned images. +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.slow +class TestEfiUnsignedImage(object): + def test_efi_unsigned_image_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - rejected when not hash in DB or DBX + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 1'): + # Test Case 1 + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 UPDV host 0:0 /UpdateVars.efi ""', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(not re.search('\'UPDV\' failed', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO1 host 0:0 /HelloWorld_simple.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('\'HELLO1\' failed', ''.join(output))) + + def test_efi_unsigned_image_auth2(self, u_boot_console, efi_boot_env): + """ + Test Case 2 - authenticated by DB with hash + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 2'): + # Test Case 2 + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 UPDV host 0:0 /UpdateVars.efi ""', + 'setenv bootargs "cmd db DB_HWs_hash.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(not re.search('\'UPDV\' failed', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO1 host 0:0 /HelloWorld_simple.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('Hello World!', ''.join(output))) + + def test_efi_unsigned_image_auth3(self, u_boot_console, efi_boot_env): + """ + Test Case 3 - rejected by DBX with hash + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 3a'): + # Test Case 3a, rejected by DBX + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 UPDV host 0:0 /UpdateVars-signed.efi ""', + 'setenv bootargs "cmd dbx DBX_HWs_hash.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(not re.search('\'UPDV\' failed', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO1 host 0:0 /HelloWorld_simple.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('\'HELLO1\' failed', ''.join(output))) + + # TODO: can be merged with auth3 + def test_efi_unsigned_image_auth4(self, u_boot_console, efi_boot_env): + """ + Test Case 4 - rejected by DBX with hash + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 4a'): + # Test Case 4a, rejected by DBX even if DB allows + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'efidebug boot add 1 UPDV host 0:0 /UpdateVars-signed.efi ""', + 'setenv bootargs "cmd db DB_HWs_hash.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd dbx DBX_HWs_hash.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd KEK KEK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr', + 'setenv bootargs "cmd PK PK.auth"', + 'efidebug boot next 1', + 'bootefi bootmgr']) + assert(not re.search('\'UPDV\' failed', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'efidebug boot add 2 HELLO1 host 0:0 /HelloWorld_simple.efi ""', + 'efidebug boot next 2', + 'bootefi bootmgr']) + assert(re.search('\'HELLO1\' failed', ''.join(output))) From patchwork Wed Sep 18 01:26:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 1163650 X-Patchwork-Delegate: xypron.glpk@gmx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="wOjdx8DL"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46Y2Vb3TVrz9s4Y for ; Wed, 18 Sep 2019 11:30:47 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id 3661BC22072; Wed, 18 Sep 2019 01:27:06 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E2D3DC22017; Wed, 18 Sep 2019 01:26:45 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id CD2D6C2203A; Wed, 18 Sep 2019 01:24:19 +0000 (UTC) Received: from mail-pg1-f194.google.com (mail-pg1-f194.google.com [209.85.215.194]) by lists.denx.de (Postfix) with ESMTPS id DE3DFC21EBF for ; Wed, 18 Sep 2019 01:24:13 +0000 (UTC) Received: by mail-pg1-f194.google.com with SMTP id u72so2978577pgb.10 for ; Tue, 17 Sep 2019 18:24:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SrqGKDwVou+/f7wIeergsET2h2Mvd+i4LR52iI9fBeE=; b=wOjdx8DLrQjEBlTvVs73khhhTA4GmcWBP7/hfQpccM7zVlYjCDCjjqcf4VI7EwZLQx 9jvvT9zGG/NUDt8pIkwXRjFujT6dNuIwjO55CVbTKhQmfUvNkxqCERQn8angEFWBr1V8 S1ZpP99IAvnf/rJyggja2iJ/RiDkXylghHd7z9nPIQZ5ttvpYlG3H0mPd4XOxdKNemVG H+q0X8Lx8JwXcX3RjDj/XQ+4v8nnTNJbqSbwelbpielT4YKqzasLKGeTONpiUjJ1Ky1W DQdWwMncpkZr6aS1aRwBSos9FdzsMQl4BXy3LBKh4EVsxfEtA87YfRtoYwt4LMTEAQFd HxJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SrqGKDwVou+/f7wIeergsET2h2Mvd+i4LR52iI9fBeE=; b=VWsX9U3yOmHc3VGuUiKFO8HT1PnNFkZxodSPQW2bXTdt7EEFeElZFmAW565ieF1XB8 NjnO6ChCNRcFyFMenjzaRDy+w+bIPDcavKuoxTxIYAAKkCcce0L6ANoZQ9XBkPLk84y6 /8ZjqYEAXcJjPqqtMydCx6IFeLk0eOIwjmXPogiKglROWOpfZfCefnbt0O7Nu7rE7pww 9EqaiMjVFR55Fblw1jAVSnYHxzqv5pHTiUurrRhtS3o2sW/GdE6OKcfrUJRekC7XVe2H zMdL9wkzuUdIEpWgBylXrb38T4k9Z/LC5LCPSEO8ip5l461JQVWKheX9J0SpJH85W7w7 B7AA== X-Gm-Message-State: APjAAAUtnqJR9A1nmd+sFS1XMCwQp0drZYlQ9gR3iSSh+6wTeLZrzEZm SopdCL1Jj9J4UMLRW8ibGey7Fg== X-Google-Smtp-Source: APXvYqyMKAQFf0wFfR5bDpwPatDgV9oV1FsDcFaObrqDSdc7enhyhLC7pp4bMpc5c/1k+Z/oDTZivw== X-Received: by 2002:a17:90a:9a8b:: with SMTP id e11mr1041387pjp.98.1568769852374; Tue, 17 Sep 2019 18:24:12 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id j1sm400148pjs.28.2019.09.17.18.24.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 17 Sep 2019 18:24:11 -0700 (PDT) From: AKASHI Takahiro To: xypron.glpk@gmx.de, agraf@csgraf.de, trini@konsulko.com Date: Wed, 18 Sep 2019 10:26:43 +0900 Message-Id: <20190918012643.25192-16-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190918012643.25192-1-takahiro.akashi@linaro.org> References: <20190918012643.25192-1-takahiro.akashi@linaro.org> MIME-Version: 1.0 Cc: u-boot@lists.denx.de Subject: [U-Boot] [RFC 15/15] efi_loader, pytest: add UEFI secure boot tests (authenticated variables) X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" test_efi_secboot/test_authvar.py: provide test cases of variable authentication This test relies on efitools and user should compile it on his own. (Currently some local change has been applied.) Signed-off-by: AKASHI Takahiro --- .../py/tests/test_efi_secboot/test_authvar.py | 287 ++++++++++++++++++ 1 file changed, 287 insertions(+) create mode 100644 test/py/tests/test_efi_secboot/test_authvar.py diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py new file mode 100644 index 000000000000..2ae25e8ce7eb --- /dev/null +++ b/test/py/tests/test_efi_secboot/test_authvar.py @@ -0,0 +1,287 @@ +# SPDX-License-Identifier: GPL-2.0+ +# Copyright (c) 2019, Linaro Limited +# Author: AKASHI Takahiro +# +# U-Boot UEFI: Variable Authentication Test + +""" +This test verifies variable authentication +""" + +import pytest +import re +from defs import * + +@pytest.mark.boardspec('sandbox') +@pytest.mark.buildconfigspec('efi_secure_boot') +@pytest.mark.slow +class TestEfiAuthVar(object): + def test_efi_var_auth1(self, u_boot_console, efi_boot_env): + """ + Test Case 1 - Install signature database + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 1a'): + # Test Case 1a, Initial secure state + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'printenv -e -v SecureBoot']) + assert(re.search('00000000: 00', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 00' in output) + output = u_boot_console.run_command( + 'printenv -e -v SetupMode') + assert('00000000: 01' in output) + + with u_boot_console.log.section('Test Case 1b'): + # Test Case 1b, PK without AUTHENTICATED_WRITE_ACCESS + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -i 4000000,$filesize PK']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 1c'): + # Test Case 1c, install PK + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'printenv -e PK']) + assert(re.search('PK:', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 01' in output) + output = u_boot_console.run_command( + 'printenv -e -v SetupMode') + assert('00000000: 00' in output) + + with u_boot_console.log.section('Test Case 1d'): + # Test Case 1d, db/dbx without KEK + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 1e'): + # Test Case 1e, install KEK + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -i 4000000,$filesize KEK']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'printenv -e KEK']) + assert(re.search('KEK:', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 01' in output) + + with u_boot_console.log.section('Test Case 1f'): + # Test Case 1f, install db + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e db']) + assert(re.search('db:', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 01' in output) + + with u_boot_console.log.section('Test Case 1g'): + # Test Case 1g, install dbx + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -i 4000000,$filesize dbx']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx', + 'printenv -e dbx']) + # FIXME: currently failed + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('dbx:', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 01' in output) + + def test_efi_var_auth2(self, u_boot_console, efi_boot_env): + """ + Test Case 2 - Update database by overwriting + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 2a'): + # Test Case 2a, update without AUTHENTICATED_WRITE_ACCESS + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31d', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 2b'): + # Test Case 2b, update without correct signature + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.esl', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 2c'): + # Test Case 2c, update with correct signature + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31f', ''.join(output))) + + def test_efi_var_auth3(self, u_boot_console, efi_boot_env): + """ + Test Case 3 - Append database + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 3a'): + # Test Case 3a, update without AUTHENTICATED_WRITE_ACCESS + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31d', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -a -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 3b'): + # Test Case 3b, update without correct signature + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB.esl', + 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + + with u_boot_console.log.section('Test Case 3c'): + # Test Case 3c, update with correct signature + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 DB1.auth', + 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db', + 'printenv -e db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x63c', ''.join(output))) + + def test_efi_var_auth4(self, u_boot_console, efi_boot_env): + """ + Test Case 4 - Delete database without authentication + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 4a'): + # Test Case 4a, update without AUTHENTICATED_WRITE_ACCESS + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e db']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31d', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'setenv -e -nv -bs -rt db', + 'printenv -e db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31d', ''.join(output))) + + with u_boot_console.log.section('Test Case 4b'): + # Test Case 4b, update without correct signature/data + output = u_boot_console.run_command_list([ + 'setenv -e -nv -bs -rt -at db', + 'printenv -e db']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('db:', ''.join(output))) + assert(re.search('DataSize = 0x31d', ''.join(output))) + + def test_efi_var_auth5(self, u_boot_console, efi_boot_env): + """ + Test Case 5 - Uninstall(delete) PK + """ + disk_img = efi_boot_env + with u_boot_console.log.section('Test Case 4a'): + # Test Case 5a, Uninstall PK without correct signature + output = u_boot_console.run_command_list([ + 'host bind 0 %s' % disk_img, + 'fatload host 0:0 4000000 PK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'fatload host 0:0 4000000 KEK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK', + 'fatload host 0:0 4000000 DB.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db', + 'printenv -e PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('PK:', ''.join(output))) +# assert(re.search('DataSize = 0x31d', ''.join(output))) + + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 noPK.esl', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'printenv -e PK']) + assert(re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('PK:', ''.join(output))) + + with u_boot_console.log.section('Test Case 5b'): + # Test Case 5b, Uninstall PK with correct signature + output = u_boot_console.run_command_list([ + 'fatload host 0:0 4000000 noPK.auth', + 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK', + 'printenv -e PK']) + assert(not re.search('Failed to set EFI variable', ''.join(output))) + assert(re.search('\"PK\" not defined', ''.join(output))) + + output = u_boot_console.run_command( + 'printenv -e -v SecureBoot') + assert('00000000: 00' in output) + output = u_boot_console.run_command( + 'printenv -e -v SetupMode') + assert('00000000: 01' in output)