All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code
@ 2020-06-09  5:09 AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 01/17] efi_loader: change efi objects initialization order AKASHI Takahiro
                   ` (16 more replies)
  0 siblings, 17 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Summary
=======
I'm currently working on reworking UEFI secure boot, aiming to add
"intermediate certificates" support. In this effort, I found a couple
of issues that should immediately be fixed or useful improvements even
without intermediate certificates support.

Each commit in this patch series has self-explained description of
the issue to be addressed.
While they are independent in terms of functionality, they are compiled
in a set since the one may depend on the other in terms of code change
overlap. All the changes can and should be merged at once for best
convenience.

I hope that I will post intermediate certificates support sometime
in the next week.

Patch structure
===============
Patch#1-#5,#9: rather preparatory patches
Patch#6-#8,#10-#11: main commits
Patch#12-#17: pytests
  Patch#15-#16 for Patch#10
  Patch#17 for Patch#11

Prerequisite
============
The version of "sbsign" command must be 0.7 or higher to sign an image
with multiple signatures. It is required here for testing.

Test
====
- The added new pytests in test_signed.py passed locally.
- Travis CI passed, except Test Case 5 for signed image
  (test_efi_signed_image_auth5) because the version of "sbsign" command
  is old and it doesn't support multiple signatures.

v2 (Jun 9, 2020)
* on top of v2020.07-rc4
* add patch#1,#2 to remove unnecessary hacks in pytest
* use EFI_PRINT() instead of debug() everywhere (patch#3-#5)
* fix a verification logic so that we should reject an image if, at least,
  one of signaures be verified by dbx. New efi_signature_verify_one() has
  a main role. (patch#10)
* use "llu" format instead of "llx" to print out the revocation time
  (patch#10)
* add some description about verification logic against multiple signatures
  (patch#11)

v1 (May 29, 2020)
* initial release

AKASHI Takahiro (17):
  efi_loader: change efi objects initialization order
  Revert "test: stabilize test_efi_secboot"
  efi_loader: signature: replace debug to EFI_PRINT
  efi_loader: variable: replace debug to EFI_PRINT
  efi_loader: image_loader: replace debug to EFI_PRINT
  efi_loader: image_loader: add a check against certificate type of
    authenticode
  efi_loader: image_loader: retrieve authenticode only if it exists
  efi_loader: signature: fix a size check against revocation list
  efi_loader: signature: make efi_hash_regions more generic
  efi_loader: image_loader: verification for all signatures should pass
  efi_loader: image_loader: add digest-based verification for signed
    image
  test/py: efi_secboot: remove all "re.search"
  test/py: efi_secboot: fix test case 1g of test_authvar
  test/py: efi_secboot: split "signed image" test case-1 into two cases
  test/py: efi_secboot: add a test against certificate revocation
  test/py: efi_secboot: add a test for multiple signatures
  test/py: efi_secboot: add a test for verifying with digest of signed
    image

 include/efi_loader.h                          |  15 +-
 lib/efi_loader/efi_image_loader.c             | 210 ++++---
 lib/efi_loader/efi_setup.c                    |   7 +-
 lib/efi_loader/efi_signature.c                | 512 +++++++++---------
 lib/efi_loader/efi_variable.c                 |  27 +-
 test/py/tests/test_efi_secboot/conftest.py    |  24 +-
 .../py/tests/test_efi_secboot/test_authvar.py |  91 ++--
 test/py/tests/test_efi_secboot/test_signed.py | 212 ++++++--
 .../tests/test_efi_secboot/test_unsigned.py   |  38 +-
 9 files changed, 696 insertions(+), 440 deletions(-)

-- 
2.27.0

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 01/17] efi_loader: change efi objects initialization order
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 10:29   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot" AKASHI Takahiro
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

The simplest solution to revert the commit b32ac16f9a32 ("test/py: fix
test_efi_secboot/conftest.py") is to move efi_console_register()
forward before efi_disk_register().

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_setup.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c
index dd0c53fc2399..671f6da12b30 100644
--- a/lib/efi_loader/efi_setup.c
+++ b/lib/efi_loader/efi_setup.c
@@ -140,6 +140,10 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 
+	ret = efi_console_register();
+	if (ret != EFI_SUCCESS)
+		goto out;
+
 #ifdef CONFIG_PARTITIONS
 	ret = efi_disk_register();
 	if (ret != EFI_SUCCESS)
@@ -185,9 +189,6 @@ efi_status_t efi_init_obj_list(void)
 	if (ret != EFI_SUCCESS)
 		goto out;
 
-	ret = efi_console_register();
-	if (ret != EFI_SUCCESS)
-		goto out;
 #if defined(CONFIG_LCD) || defined(CONFIG_DM_VIDEO)
 	ret = efi_gop_register();
 	if (ret != EFI_SUCCESS)
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot"
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 01/17] efi_loader: change efi objects initialization order AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 10:30   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT AKASHI Takahiro
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

This reverts commit 5827c2545849441dd60467565aac11964259972f.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/test_authvar.py  | 8 ++++----
 test/py/tests/test_efi_secboot/test_signed.py   | 4 ++--
 test/py/tests/test_efi_secboot/test_unsigned.py | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py
index 9912694a3e3d..55dcaa95f1ea 100644
--- a/test/py/tests/test_efi_secboot/test_authvar.py
+++ b/test/py/tests/test_efi_secboot/test_authvar.py
@@ -133,7 +133,7 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 PK.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK; echo',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 db.auth',
@@ -174,7 +174,7 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 PK.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK; echo',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 db.auth',
@@ -215,7 +215,7 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 PK.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK; echo',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 db.auth',
@@ -249,7 +249,7 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 PK.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK; echo',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 db.auth',
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index fc722ab506c9..584282b338bc 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -29,7 +29,7 @@ class TestEfiSignedImage(object):
             # 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:1 /helloworld.efi.signed ""; echo',
+                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
             assert(re.search('Hello, world!', ''.join(output)))
@@ -81,7 +81,7 @@ class TestEfiSignedImage(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 db.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx; echo',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 PK.auth',
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index a4af845c514e..22d849afb89b 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -30,7 +30,7 @@ class TestEfiUnsignedImage(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
 		'fatload host 0:1 4000000 KEK.auth',
-		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK; echo',
+		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
             assert(not re.search('Failed to set EFI variable', ''.join(output)))
@@ -58,7 +58,7 @@ class TestEfiUnsignedImage(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
 		'fatload host 0:1 4000000 db_hello.auth',
-		'setenv -e -nv -bs -rt -at -i 4000000,$filesize db; echo',
+		'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
 		'fatload host 0:1 4000000 KEK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
@@ -82,7 +82,7 @@ class TestEfiUnsignedImage(object):
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
 		'fatload host 0:1 4000000 db_hello.auth',
-		'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx; echo',
+		'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
 		'fatload host 0:1 4000000 KEK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 01/17] efi_loader: change efi objects initialization order AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot" AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 10:30   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 04/17] efi_loader: variable: " AKASHI Takahiro
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Just for style consistency, replace all the uses of debug to
EFI_PRINT in efi_signature.c

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_signature.c | 121 +++++++++++++++++----------------
 1 file changed, 62 insertions(+), 59 deletions(-)

diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index be6491c6e255..a05c75472721 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -43,14 +43,14 @@ static bool efi_hash_regions(struct efi_image_regions *regs, void **hash,
 	*size = 0;
 	*hash = calloc(1, SHA256_SUM_LEN);
 	if (!*hash) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		return false;
 	}
 	*size = SHA256_SUM_LEN;
 
 	hash_calculate("sha256", regs->reg, regs->num, *hash);
 #ifdef DEBUG
-	debug("hash calculated:\n");
+	EFI_PRINT("hash calculated:\n");
 	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 		       *hash, SHA256_SUM_LEN, false);
 #endif
@@ -76,7 +76,7 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
 	*size = 0;
 	*hash = calloc(1, SHA256_SUM_LEN);
 	if (!*hash) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		free(msg);
 		return false;
 	}
@@ -87,7 +87,7 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
 
 	hash_calculate("sha256", &regtmp, 1, *hash);
 #ifdef DEBUG
-	debug("hash calculated based on contentInfo:\n");
+	EFI_PRINT("hash calculated based on contentInfo:\n");
 	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 		       *hash, SHA256_SUM_LEN, false);
 #endif
@@ -120,8 +120,8 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 	char c;
 	bool verified;
 
-	debug("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__,
-	      regs, ps_info, cert, cert->issuer, cert->subject);
+	EFI_PRINT("%s: Enter, %p, %p, %p(issuer: %s, subject: %s)\n", __func__,
+		  regs, ps_info, cert, cert->issuer, cert->subject);
 
 	verified = false;
 
@@ -139,7 +139,8 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 		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);
+		EFI_PRINT("unknown msg digest algo: %s\n",
+			  ps_info->sig->hash_algo);
 		goto out;
 	}
 	info.crypto = image_get_crypto_algo(info.name);
@@ -148,21 +149,22 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 	info.keylen = cert->pub->keylen;
 
 	/* verify signature */
-	debug("%s: crypto: %s, signature len:%x\n", __func__,
-	      info.name, ps_info->sig->s_size);
+	EFI_PRINT("%s: crypto: %s, signature len:%x\n", __func__,
+		  info.name, ps_info->sig->s_size);
 	if (ps_info->aa_set & (1UL << sinfo_has_message_digest)) {
-		debug("%s: RSA verify authentication attribute\n", __func__);
+		EFI_PRINT("%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);
+		EFI_PRINT("checking msg digest first, len:0x%x\n",
+			  ps_info->msgdigest_len);
 
 #ifdef DEBUG
-		debug("hash in database:\n");
+		EFI_PRINT("hash in database:\n");
 		print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 			       ps_info->msgdigest, ps_info->msgdigest_len,
 			       false);
@@ -174,14 +176,14 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 				/* for authenticated variable */
 			if (ps_info->msgdigest_len != size ||
 			    memcmp(hash, ps_info->msgdigest, size)) {
-				debug("Digest doesn't match\n");
+				EFI_PRINT("Digest doesn't match\n");
 				free(hash);
 				goto out;
 			}
 
 			free(hash);
 		} else {
-			debug("Digesting image failed\n");
+			EFI_PRINT("Digesting image failed\n");
 			goto out;
 		}
 
@@ -196,7 +198,7 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 				ps_info->sig->s, ps_info->sig->s_size))
 			verified = true;
 	} else {
-		debug("%s: RSA verify content data\n", __func__);
+		EFI_PRINT("%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))
@@ -204,7 +206,7 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 	}
 
 out:
-	debug("%s: Exit, verified: %d\n", __func__, verified);
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
 	return verified;
 }
 
@@ -234,26 +236,26 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 	struct efi_sig_data *sig_data;
 	bool verified = false;
 
-	debug("%s: Enter, %p, %p, %p, %p\n", __func__,
-	      regs, signed_info, siglist, valid_cert);
+	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
+		  regs, signed_info, siglist, valid_cert);
 
 	if (!signed_info) {
 		void *hash;
 		size_t size;
 
-		debug("%s: unsigned image\n", __func__);
+		EFI_PRINT("%s: unsigned image\n", __func__);
 		/*
 		 * verify based on calculated hash value
 		 * TODO: support other hash algorithms
 		 */
 		if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
-			debug("Digest algorithm is not supported: %pUl\n",
-			      &siglist->sig_type);
+			EFI_PRINT("Digest algorithm is not supported: %pUl\n",
+				  &siglist->sig_type);
 			goto out;
 		}
 
 		if (!efi_hash_regions(regs, &hash, &size)) {
-			debug("Digesting unsigned image failed\n");
+			EFI_PRINT("Digesting unsigned image failed\n");
 			goto out;
 		}
 
@@ -261,7 +263,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 		for (sig_data = siglist->sig_data_list; sig_data;
 		     sig_data = sig_data->next) {
 #ifdef DEBUG
-			debug("Msg digest in database:\n");
+			EFI_PRINT("Msg digest in database:\n");
 			print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 				       sig_data->data, sig_data->size, false);
 #endif
@@ -276,10 +278,10 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 		goto out;
 	}
 
-	debug("%s: signed image\n", __func__);
+	EFI_PRINT("%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);
+		EFI_PRINT("Signature type is not supported: %pUl\n",
+			  &siglist->sig_type);
 		goto out;
 	}
 
@@ -290,7 +292,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 
 		cert = x509_cert_parse(sig_data->data, sig_data->size);
 		if (IS_ERR(cert)) {
-			debug("Parsing x509 certificate failed\n");
+			EFI_PRINT("Parsing x509 certificate failed\n");
 			goto out;
 		}
 
@@ -307,7 +309,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 	}
 
 out:
-	debug("%s: Exit, verified: %d\n", __func__, verified);
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
 	return verified;
 }
 
@@ -332,7 +334,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 	struct efi_signature_store *siglist;
 	bool verified = false;
 
-	debug("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert);
+	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert);
 
 	if (!db)
 		goto out;
@@ -342,7 +344,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 
 	/* for unsigned image */
 	if (!msg) {
-		debug("%s: Verify unsigned image with db\n", __func__);
+		EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
 		for (siglist = db; siglist; siglist = siglist->next)
 			if (efi_signature_verify_with_list(regs, NULL, NULL,
 							   siglist, cert)) {
@@ -354,10 +356,10 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 	}
 
 	/* for signed image or variable */
-	debug("%s: Verify signed image with db\n", __func__);
+	EFI_PRINT("%s: Verify signed image with db\n", __func__);
 	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);
+		EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
+			  info->sig->hash_algo, info->sig->pkey_algo);
 
 		for (siglist = db; siglist; siglist = siglist->next) {
 			if (efi_signature_verify_with_list(regs, msg, info,
@@ -369,7 +371,7 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 	}
 
 out:
-	debug("%s: Exit, verified: %d\n", __func__, verified);
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
 	return verified;
 }
 
@@ -401,21 +403,21 @@ static bool efi_search_siglist(struct x509_certificate *cert,
 
 	if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256)) {
 		/* TODO: other hash algos */
-		debug("Certificate's digest type is not supported: %pUl\n",
-		      &siglist->sig_type);
+		EFI_PRINT("Certificate's digest type is not supported: %pUl\n",
+			  &siglist->sig_type);
 		goto out;
 	}
 
 	/* calculate hash of TBSCertificate */
 	msg = calloc(1, SHA256_SUM_LEN);
 	if (!msg) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		goto out;
 	}
 
 	hash = calloc(1, SHA256_SUM_LEN);
 	if (!hash) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		goto out;
 	}
 
@@ -466,7 +468,7 @@ bool efi_signature_verify_cert(struct x509_certificate *cert,
 	time64_t revoc_time;
 	bool found = false;
 
-	debug("%s: Enter, %p, %p\n", __func__, dbx, cert);
+	EFI_PRINT("%s: Enter, %p, %p\n", __func__, dbx, cert);
 
 	if (!cert)
 		return false;
@@ -481,7 +483,7 @@ bool efi_signature_verify_cert(struct x509_certificate *cert,
 		}
 	}
 
-	debug("%s: Exit, verified: %d\n", __func__, !found);
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
 	return !found;
 }
 
@@ -502,7 +504,7 @@ bool efi_signature_verify_signers(struct pkcs7_message *msg,
 	struct pkcs7_signed_info *info;
 	bool found = false;
 
-	debug("%s: Enter, %p, %p\n", __func__, msg, dbx);
+	EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
 
 	if (!msg)
 		goto out;
@@ -515,7 +517,7 @@ bool efi_signature_verify_signers(struct pkcs7_message *msg,
 		}
 	}
 out:
-	debug("%s: Exit, verified: %d\n", __func__, !found);
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
 	return !found;
 }
 
@@ -540,7 +542,7 @@ efi_status_t efi_image_region_add(struct efi_image_regions *regs,
 	int i, j;
 
 	if (regs->num >= regs->max) {
-		debug("%s: no more room for regions\n", __func__);
+		EFI_PRINT("%s: no more room for regions\n", __func__);
 		return EFI_OUT_OF_RESOURCES;
 	}
 
@@ -557,8 +559,8 @@ efi_status_t efi_image_region_add(struct efi_image_regions *regs,
 
 		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__);
+			EFI_PRINT("%s: new region already part of another\n",
+				  __func__);
 			return EFI_INVALID_PARAMETER;
 		}
 
@@ -650,14 +652,14 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl)
 
 	if (esl->signature_list_size
 			<= (sizeof(*esl) + esl->signature_header_size)) {
-		debug("Siglist in wrong format\n");
+		EFI_PRINT("Siglist in wrong format\n");
 		return NULL;
 	}
 
 	/* Create a head */
 	siglist = calloc(sizeof(*siglist), 1);
 	if (!siglist) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		goto err;
 	}
 	memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
@@ -672,14 +674,14 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl)
 	while (left > 0) {
 		/* Signature must exist if there is remaining data. */
 		if (left < esl->signature_size) {
-			debug("Certificate is too small\n");
+			EFI_PRINT("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");
+			EFI_PRINT("Out of memory\n");
 			goto err;
 		}
 
@@ -690,7 +692,7 @@ efi_sigstore_parse_siglist(struct efi_signature_list *esl)
 					- sizeof(esd->signature_owner);
 		sig_data->data = malloc(sig_data->size);
 		if (!sig_data->data) {
-			debug("Out of memory\n");
+			EFI_PRINT("Out of memory\n");
 			goto err;
 		}
 		memcpy(sig_data->data, esd->signature_data, sig_data->size);
@@ -736,7 +738,7 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
 	} 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);
+		EFI_PRINT("unknown signature database, %ls\n", name);
 		return NULL;
 	}
 
@@ -744,23 +746,23 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
 	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);
+		EFI_PRINT("variable, %ls, not found\n", name);
 		sigstore = calloc(sizeof(*sigstore), 1);
 		return sigstore;
 	} else if (ret != EFI_BUFFER_TOO_SMALL) {
-		debug("Getting variable, %ls, failed\n", name);
+		EFI_PRINT("Getting variable, %ls, failed\n", name);
 		return NULL;
 	}
 
 	db = malloc(db_size);
 	if (!db) {
-		debug("Out of memory\n");
+		EFI_PRINT("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);
+		EFI_PRINT("Getting variable, %ls, failed\n", name);
 		goto err;
 	}
 
@@ -769,19 +771,20 @@ struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
 	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);
+			EFI_PRINT("variable, %ls, in wrong format\n", name);
 			goto err;
 		}
 
 		if (db_size < esl->signature_list_size) {
-			debug("variable, %ls, in wrong format\n", name);
+			EFI_PRINT("variable, %ls, in wrong format\n", name);
 			goto err;
 		}
 
 		/* Parse a single siglist. */
 		siglist = efi_sigstore_parse_siglist(esl);
 		if (!siglist) {
-			debug("Parsing signature list of %ls failed\n", name);
+			EFI_PRINT("Parsing signature list of %ls failed\n",
+				  name);
 			goto err;
 		}
 
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 04/17] efi_loader: variable: replace debug to EFI_PRINT
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 05/17] efi_loader: image_loader: " AKASHI Takahiro
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Just for style consistency, replace all the uses of debug() to
EFI_PRINT in efi_variable.c.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_variable.c | 27 ++++++++++++++-------------
 1 file changed, 14 insertions(+), 13 deletions(-)

diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index e097670e2832..90d740fbda2c 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -243,7 +243,8 @@ static efi_status_t efi_transfer_secure_state(enum efi_secure_mode mode)
 {
 	efi_status_t ret;
 
-	debug("Switching secure state from %d to %d\n", efi_secure_mode, mode);
+	EFI_PRINT("Switching secure state from %d to %d\n", efi_secure_mode,
+		  mode);
 
 	if (mode == EFI_MODE_DEPLOYED) {
 		ret = efi_set_secure_state(1, 0, 0, 1);
@@ -394,16 +395,16 @@ static struct pkcs7_message *efi_variable_parse_signature(const void *buf,
 	 * TODO:
 	 * The header should be composed in a more refined manner.
 	 */
-	debug("Makeshift prefix added to authentication data\n");
+	EFI_PRINT("Makeshift prefix added to authentication data\n");
 	ebuflen = sizeof(pkcs7_hdr) + buflen;
 	if (ebuflen <= 0x7f) {
-		debug("Data is too short\n");
+		EFI_PRINT("Data is too short\n");
 		return NULL;
 	}
 
 	ebuf = malloc(ebuflen);
 	if (!ebuf) {
-		debug("Out of memory\n");
+		EFI_PRINT("Out of memory\n");
 		return NULL;
 	}
 
@@ -527,7 +528,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
 					       auth->auth_info.hdr.dwLength
 						   - sizeof(auth->auth_info));
 	if (!var_sig) {
-		debug("Parsing variable's signature failed\n");
+		EFI_PRINT("Parsing variable's signature failed\n");
 		goto err;
 	}
 
@@ -558,14 +559,14 @@ static efi_status_t efi_variable_authenticate(u16 *variable,
 
 	/* verify signature */
 	if (efi_signature_verify_with_sigdb(regs, var_sig, truststore, NULL)) {
-		debug("Verified\n");
+		EFI_PRINT("Verified\n");
 	} else {
 		if (truststore2 &&
 		    efi_signature_verify_with_sigdb(regs, var_sig,
 						    truststore2, NULL)) {
-			debug("Verified\n");
+			EFI_PRINT("Verified\n");
 		} else {
-			debug("Verifying variable's signature failed\n");
+			EFI_PRINT("Verifying variable's signature failed\n");
 			goto err;
 		}
 	}
@@ -640,7 +641,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name,
 		}
 
 		if (!data) {
-			debug("Variable with no data shouldn't exist.\n");
+			EFI_PRINT("Variable with no data shouldn't exist.\n");
 			return EFI_INVALID_PARAMETER;
 		}
 
@@ -659,7 +660,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name,
 		}
 
 		if (!data) {
-			debug("Variable with no data shouldn't exist.\n");
+			EFI_PRINT("Variable with no data shouldn't exist.\n");
 			return EFI_INVALID_PARAMETER;
 		}
 
@@ -940,8 +941,8 @@ static efi_status_t efi_set_variable_common(u16 *variable_name,
 		/* authentication is mandatory */
 		if (!(attributes &
 		      EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
-			debug("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
-			      variable_name);
+			EFI_PRINT("%ls: AUTHENTICATED_WRITE_ACCESS required\n",
+				  variable_name);
 			ret = EFI_INVALID_PARAMETER;
 			goto err;
 		}
@@ -970,7 +971,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name,
 		if (attributes &
 		    (EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS |
 		     EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS)) {
-			debug("Secure boot is not configured\n");
+			EFI_PRINT("Secure boot is not configured\n");
 			ret = EFI_INVALID_PARAMETER;
 			goto err;
 		}
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 05/17] efi_loader: image_loader: replace debug to EFI_PRINT
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (3 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 04/17] efi_loader: variable: " AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 10:38   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode AKASHI Takahiro
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Just for style consistency, replace all the uses of debug() to
EFI_PRINT() in efi_image_loader.c.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_image_loader.c | 64 ++++++++++++++++---------------
 1 file changed, 33 insertions(+), 31 deletions(-)

diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 80b3ff0f76e1..5b00fea2f113 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -326,8 +326,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 		authoff = opt->DataDirectory[ctidx].VirtualAddress;
 		authsz = opt->DataDirectory[ctidx].Size;
 	} else {
-		debug("%s: Invalid optional header magic %x\n", __func__,
-		      nt->OptionalHeader.Magic);
+		EFI_PRINT("%s: Invalid optional header magic %x\n", __func__,
+			  nt->OptionalHeader.Magic);
 		goto err;
 	}
 
@@ -337,7 +337,7 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 			    nt->FileHeader.SizeOfOptionalHeader);
 	sorted = calloc(sizeof(IMAGE_SECTION_HEADER *), num_sections);
 	if (!sorted) {
-		debug("%s: Out of memory\n", __func__);
+		EFI_PRINT("%s: Out of memory\n", __func__);
 		goto err;
 	}
 
@@ -356,13 +356,13 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 		efi_image_region_add(regs, efi + sorted[i]->PointerToRawData,
 				     efi + sorted[i]->PointerToRawData + size,
 				     0);
-		debug("section[%d](%s): raw: 0x%x-0x%x, virt: %x-%x\n",
-		      i, sorted[i]->Name,
-		      sorted[i]->PointerToRawData,
-		      sorted[i]->PointerToRawData + size,
-		      sorted[i]->VirtualAddress,
-		      sorted[i]->VirtualAddress
-			+ sorted[i]->Misc.VirtualSize);
+		EFI_PRINT("section[%d](%s): raw: 0x%x-0x%x, virt: %x-%x\n",
+			  i, sorted[i]->Name,
+			  sorted[i]->PointerToRawData,
+			  sorted[i]->PointerToRawData + size,
+			  sorted[i]->VirtualAddress,
+			  sorted[i]->VirtualAddress
+			    + sorted[i]->Misc.VirtualSize);
 
 		bytes_hashed += size;
 	}
@@ -370,8 +370,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 
 	/* 3. Extra data excluding Certificates Table */
 	if (bytes_hashed + authsz < len) {
-		debug("extra data for hash: %lu\n",
-		      len - (bytes_hashed + authsz));
+		EFI_PRINT("extra data for hash: %lu\n",
+			  len - (bytes_hashed + authsz));
 		efi_image_region_add(regs, efi + bytes_hashed,
 				     efi + len - authsz, 0);
 	}
@@ -379,18 +379,19 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 	/* Return Certificates Table */
 	if (authsz) {
 		if (len < authoff + authsz) {
-			debug("%s: Size for auth too large: %u >= %zu\n",
-			      __func__, authsz, len - authoff);
+			EFI_PRINT("%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));
+			EFI_PRINT("%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);
+		EFI_PRINT("WIN_CERTIFICATE: 0x%x, size: 0x%x\n", authoff,
+			  authsz);
 	} else {
 		*auth = NULL;
 		*auth_len = 0;
@@ -424,19 +425,19 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
 
 	dbx = efi_sigstore_parse_sigdb(L"dbx");
 	if (!dbx) {
-		debug("Getting signature database(dbx) failed\n");
+		EFI_PRINT("Getting signature database(dbx) failed\n");
 		goto out;
 	}
 
 	db = efi_sigstore_parse_sigdb(L"db");
 	if (!db) {
-		debug("Getting signature database(db) failed\n");
+		EFI_PRINT("Getting signature database(db) failed\n");
 		goto out;
 	}
 
 	/* try black-list first */
 	if (efi_signature_verify_with_sigdb(regs, NULL, dbx, NULL)) {
-		debug("Image is not signed and rejected by \"dbx\"\n");
+		EFI_PRINT("Image is not signed and rejected by \"dbx\"\n");
 		goto out;
 	}
 
@@ -444,7 +445,7 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
 	if (efi_signature_verify_with_sigdb(regs, NULL, db, NULL))
 		ret = true;
 	else
-		debug("Image is not signed and not found in \"db\" or \"dbx\"\n");
+		EFI_PRINT("Image is not signed and not found in \"db\" or \"dbx\"\n");
 
 out:
 	efi_sigstore_free(db);
@@ -505,7 +506,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 
 	if (!efi_image_parse(efi, efi_size, &regs, &wincerts,
 			     &wincerts_len)) {
-		debug("Parsing PE executable image failed\n");
+		EFI_PRINT("Parsing PE executable image failed\n");
 		goto err;
 	}
 
@@ -521,13 +522,13 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 	 */
 	db = efi_sigstore_parse_sigdb(L"db");
 	if (!db) {
-		debug("Getting signature database(db) failed\n");
+		EFI_PRINT("Getting signature database(db) failed\n");
 		goto err;
 	}
 
 	dbx = efi_sigstore_parse_sigdb(L"dbx");
 	if (!dbx) {
-		debug("Getting signature database(dbx) failed\n");
+		EFI_PRINT("Getting signature database(dbx) failed\n");
 		goto err;
 	}
 
@@ -536,26 +537,27 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 	     (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));
+			EFI_PRINT("%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 (IS_ERR(msg)) {
-			debug("Parsing image's signature failed\n");
+			EFI_PRINT("Parsing image's signature failed\n");
 			msg = NULL;
 			goto err;
 		}
 
 		/* try black-list first */
 		if (efi_signature_verify_with_sigdb(regs, msg, dbx, NULL)) {
-			debug("Signature was rejected by \"dbx\"\n");
+			EFI_PRINT("Signature was rejected by \"dbx\"\n");
 			goto err;
 		}
 
 		if (!efi_signature_verify_signers(msg, dbx)) {
-			debug("Signer was rejected by \"dbx\"\n");
+			EFI_PRINT("Signer was rejected by \"dbx\"\n");
 			goto err;
 		} else {
 			ret = true;
@@ -563,14 +565,14 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 
 		/* try white-list */
 		if (!efi_signature_verify_with_sigdb(regs, msg, db, &cert)) {
-			debug("Verifying signature with \"db\" failed\n");
+			EFI_PRINT("Verifying signature with \"db\" failed\n");
 			goto err;
 		} else {
 			ret = true;
 		}
 
 		if (!efi_signature_verify_cert(cert, dbx)) {
-			debug("Certificate was rejected by \"dbx\"\n");
+			EFI_PRINT("Certificate was rejected by \"dbx\"\n");
 			goto err;
 		} else {
 			ret = true;
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (4 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 05/17] efi_loader: image_loader: " AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 10:56   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 07/17] efi_loader: image_loader: retrieve authenticode only if it exists AKASHI Takahiro
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

UEFI specification requires that we shall support three type of
certificates of authenticode in PE image:
  WIN_CERT_TYPE_EFI_GUID with the guid, EFI_CERT_TYPE_PCKS7_GUID
  WIN_CERT_TYPE_PKCS_SIGNED_DATA
  WIN_CERT_TYPE_EFI_PKCS1_15

As EDK2 does, we will support the first two that are pkcs7 SignedData.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_image_loader.c | 56 ++++++++++++++++++++++++-------
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 5b00fea2f113..38b2c24ab1d6 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -484,7 +484,8 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 	struct efi_signature_store *db = NULL, *dbx = NULL;
 	struct x509_certificate *cert = NULL;
 	void *new_efi = NULL;
-	size_t new_efi_size;
+	u8 *auth, *wincerts_end;
+	size_t new_efi_size, auth_size;
 	bool ret = false;
 
 	if (!efi_secure_boot_enabled())
@@ -533,21 +534,52 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 	}
 
 	/* 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)) {
-			EFI_PRINT("%s: dwLength too small: %u < %zu\n",
-				  __func__, wincert->dwLength,
-				  sizeof(*wincert));
-			goto err;
+	for (wincert = wincerts, wincerts_end = (u8 *)wincerts + wincerts_len;
+	     (u8 *)wincert < wincerts_end;
+	     wincert = (WIN_CERTIFICATE *)
+			((u8 *)wincert + ALIGN(wincert->dwLength, 8))) {
+		if ((u8 *)wincert + sizeof(*wincert) >= wincerts_end)
+			break;
+
+		if (wincert->dwLength <= sizeof(*wincert)) {
+			EFI_PRINT("dwLength too small: %u < %zu\n",
+				  wincert->dwLength, sizeof(*wincert));
+			continue;
+		}
+
+		EFI_PRINT("WIN_CERTIFICATE_TYPE: 0x%x\n",
+			  wincert->wCertificateType);
+
+		auth = (u8 *)wincert + sizeof(*wincert);
+		auth_size = wincert->dwLength - sizeof(*wincert);
+		if (wincert->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
+			if (auth + sizeof(efi_guid_t) >= wincerts_end)
+				break;
+
+			if (auth_size <= sizeof(efi_guid_t)) {
+				EFI_PRINT("dwLength too small: %u < %zu\n",
+					  wincert->dwLength, sizeof(*wincert));
+				continue;
+			}
+			if (guidcmp(auth, &efi_guid_cert_type_pkcs7)) {
+				EFI_PRINT("Certificate type not supported: %pUl\n",
+					  auth);
+				continue;
+			}
+
+			auth += sizeof(efi_guid_t);
+			auth_size -= sizeof(efi_guid_t);
+		} else if (wincert->wCertificateType
+				!= WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
+			EFI_PRINT("Certificate type not supported\n");
+			continue;
 		}
-		msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert),
-					  wincert->dwLength - sizeof(*wincert));
+
+		msg = pkcs7_parse_message(auth, auth_size);
 		if (IS_ERR(msg)) {
 			EFI_PRINT("Parsing image's signature failed\n");
 			msg = NULL;
-			goto err;
+			continue;
 		}
 
 		/* try black-list first */
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 07/17] efi_loader: image_loader: retrieve authenticode only if it exists
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (5 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list AKASHI Takahiro
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Since the certificate table, which is indexed by
IMAGE_DIRECTORY_ENTRY_SECURITY and contains authenticode in PE image,
doesn't always exist, we should make sure that we will retrieve its pointer
only if it exists.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_image_loader.c | 29 +++++++++++++++++++++--------
 1 file changed, 21 insertions(+), 8 deletions(-)

diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 38b2c24ab1d6..a617693fe651 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -268,6 +268,8 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 
 	dos = (void *)efi;
 	nt = (void *)(efi + dos->e_lfanew);
+	authoff = 0;
+	authsz = 0;
 
 	/*
 	 * Count maximum number of regions to be digested.
@@ -306,25 +308,36 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
 			efi_image_region_add(regs,
 					     &opt->DataDirectory[ctidx] + 1,
 					     efi + opt->SizeOfHeaders, 0);
+
+			authoff = opt->DataDirectory[ctidx].VirtualAddress;
+			authsz = opt->DataDirectory[ctidx].Size;
 		}
 
 		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;
 
+		/* Skip CheckSum */
 		efi_image_region_add(regs, efi, &opt->CheckSum, 0);
-		efi_image_region_add(regs, &opt->Subsystem,
-				     &opt->DataDirectory[ctidx], 0);
-		efi_image_region_add(regs, &opt->DataDirectory[ctidx] + 1,
-				     efi + opt->SizeOfHeaders, 0);
+		if (nt->OptionalHeader.NumberOfRvaAndSizes <= ctidx) {
+			efi_image_region_add(regs,
+					     &opt->Subsystem,
+					     efi + opt->SizeOfHeaders, 0);
+		} else {
+			/* Skip Certificates Table */
+			efi_image_region_add(regs, &opt->Subsystem,
+					     &opt->DataDirectory[ctidx], 0);
+			efi_image_region_add(regs,
+					     &opt->DataDirectory[ctidx] + 1,
+					     efi + opt->SizeOfHeaders, 0);
+
+			authoff = opt->DataDirectory[ctidx].VirtualAddress;
+			authsz = opt->DataDirectory[ctidx].Size;
+		}
 
 		bytes_hashed = opt->SizeOfHeaders;
 		align = opt->FileAlignment;
-		authoff = opt->DataDirectory[ctidx].VirtualAddress;
-		authsz = opt->DataDirectory[ctidx].Size;
 	} else {
 		EFI_PRINT("%s: Invalid optional header magic %x\n", __func__,
 			  nt->OptionalHeader.Magic);
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (6 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 07/17] efi_loader: image_loader: retrieve authenticode only if it exists AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 11:00   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic AKASHI Takahiro
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Since the size check against an entry in efi_search_siglist() is
incorrect, this function will never find out a to-be-matched certificate
and its associated revocation time in the signature list.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_signature.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index a05c75472721..f22dc151971f 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -434,10 +434,11 @@ static bool efi_search_siglist(struct x509_certificate *cert,
 		 *	time64_t revocation_time;
 		 * };
 		 */
-		if ((sig_data->size == SHA256_SUM_LEN) &&
-		    !memcmp(sig_data->data, hash, SHA256_SUM_LEN)) {
+		if ((sig_data->size >= SHA256_SUM_LEN + sizeof(time64_t)) &&
+		    !memcmp(sig_data->data, msg, SHA256_SUM_LEN)) {
 			memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
 			       sizeof(*revoc_time));
+			EFI_PRINT("revocation time: %llu\n", *revoc_time);
 			found = true;
 			goto out;
 		}
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (7 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 11:08   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass AKASHI Takahiro
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

There are a couple of occurrences of hash calculations in which a new
efi_hash_regions will be commonly used.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 lib/efi_loader/efi_signature.c | 44 +++++++++++++---------------------
 1 file changed, 16 insertions(+), 28 deletions(-)

diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index f22dc151971f..03080bc0b11c 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -30,6 +30,7 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 /**
  * efi_hash_regions - calculate a hash value
  * @regs:	List of regions
+ * @count:	Number of regions
  * @hash:	Pointer to a pointer to buffer holding a hash value
  * @size:	Size of buffer to be returned
  *
@@ -37,18 +38,20 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
  *
  * Return:	true on success, false on error
  */
-static bool efi_hash_regions(struct efi_image_regions *regs, void **hash,
-			     size_t *size)
+static bool efi_hash_regions(struct image_region *regs, int count,
+			     void **hash, size_t *size)
 {
-	*size = 0;
-	*hash = calloc(1, SHA256_SUM_LEN);
 	if (!*hash) {
-		EFI_PRINT("Out of memory\n");
-		return false;
+		*hash = calloc(1, SHA256_SUM_LEN);
+		if (!*hash) {
+			EFI_PRINT("Out of memory\n");
+			return false;
+		}
 	}
-	*size = SHA256_SUM_LEN;
+	if (size)
+		*size = SHA256_SUM_LEN;
 
-	hash_calculate("sha256", regs->reg, regs->num, *hash);
+	hash_calculate("sha256", regs, count, *hash);
 #ifdef DEBUG
 	EFI_PRINT("hash calculated:\n");
 	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
@@ -73,26 +76,10 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
 {
 	struct image_region regtmp;
 
-	*size = 0;
-	*hash = calloc(1, SHA256_SUM_LEN);
-	if (!*hash) {
-		EFI_PRINT("Out of memory\n");
-		free(msg);
-		return false;
-	}
-	*size = SHA256_SUM_LEN;
-
 	regtmp.data = msg->data;
 	regtmp.size = msg->data_len;
 
-	hash_calculate("sha256", &regtmp, 1, *hash);
-#ifdef DEBUG
-	EFI_PRINT("hash calculated based on contentInfo:\n");
-	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
-		       *hash, SHA256_SUM_LEN, false);
-#endif
-
-	return true;
+	return efi_hash_regions(&regtmp, 1, hash, size);
 }
 
 /**
@@ -170,9 +157,10 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
 			       false);
 #endif
 		/* against contentInfo first */
+		hash = NULL;
 		if ((msg->data && efi_hash_msg_content(msg, &hash, &size)) ||
 				/* for signed image */
-		    efi_hash_regions(regs, &hash, &size)) {
+		    efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
 				/* for authenticated variable */
 			if (ps_info->msgdigest_len != size ||
 			    memcmp(hash, ps_info->msgdigest, size)) {
@@ -240,7 +228,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 		  regs, signed_info, siglist, valid_cert);
 
 	if (!signed_info) {
-		void *hash;
+		void *hash = NULL;
 		size_t size;
 
 		EFI_PRINT("%s: unsigned image\n", __func__);
@@ -254,7 +242,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 			goto out;
 		}
 
-		if (!efi_hash_regions(regs, &hash, &size)) {
+		if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
 			EFI_PRINT("Digesting unsigned image failed\n");
 			goto out;
 		}
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (8 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  7:14   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 11/17] efi_loader: image_loader: add digest-based verification for signed image AKASHI Takahiro
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

A signed image may have multiple signatures in
  - each WIN_CERTIFICATE in authenticode, and/or
  - each SignerInfo in pkcs7 SignedData (of WIN_CERTIFICATE)

In the initial implementation of efi_image_authenticate(), the criteria
of verification check for multiple signatures case is a bit ambiguous
and it may cause inconsistent result.

With this patch, we will make sure that verification check in
efi_image_authenticate() should pass against all the signatures.
The only exception would be
  - the case where a digest algorithm used in signature is not supported by
    U-Boot, or
  - the case where parsing some portion of authenticode has failed
In those cases, we don't know how the signature be handled and should
just ignore them.

Please note that, due to this change, efi_signature_verify_with_sigdb()'s
function prototype will be modified, taking "dbx" as well as "db"
instead of outputing a "certificate." If "dbx" is null, the behavior would
be the exact same as before.
The function's name will be changed to efi_signature_verify() once
current efi_signature_verify() has gone due to further improvement
in intermediate certificates support.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_loader.h              |  13 +-
 lib/efi_loader/efi_image_loader.c |  43 ++---
 lib/efi_loader/efi_signature.c    | 298 +++++++++++++++++-------------
 3 files changed, 198 insertions(+), 156 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index c2cae814b652..9f49a8a349fa 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -762,14 +762,15 @@ struct efi_signature_store {
 struct x509_certificate;
 struct pkcs7_message;
 
-bool efi_signature_verify_cert(struct x509_certificate *cert,
-			       struct efi_signature_store *dbx);
-bool efi_signature_verify_signers(struct pkcs7_message *msg,
-				  struct efi_signature_store *dbx);
+bool efi_signature_verify_one(struct efi_image_regions *regs,
+			      struct pkcs7_message *msg,
+			      struct efi_signature_store *db);
 bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 				     struct pkcs7_message *msg,
-				  struct efi_signature_store *db,
-				  struct x509_certificate **cert);
+				     struct efi_signature_store *db,
+				     struct efi_signature_store *dbx);
+bool efi_signature_check_signers(struct pkcs7_message *msg,
+				 struct efi_signature_store *dbx);
 
 efi_status_t efi_image_region_add(struct efi_image_regions *regs,
 				  const void *start, const void *end,
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index a617693fe651..222396b49eda 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -449,13 +449,13 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
 	}
 
 	/* try black-list first */
-	if (efi_signature_verify_with_sigdb(regs, NULL, dbx, NULL)) {
+	if (efi_signature_verify_one(regs, NULL, dbx)) {
 		EFI_PRINT("Image is not signed and rejected by \"dbx\"\n");
 		goto out;
 	}
 
 	/* try white-list */
-	if (efi_signature_verify_with_sigdb(regs, NULL, db, NULL))
+	if (efi_signature_verify_one(regs, NULL, db))
 		ret = true;
 	else
 		EFI_PRINT("Image is not signed and not found in \"db\" or \"dbx\"\n");
@@ -495,12 +495,13 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 	size_t wincerts_len;
 	struct pkcs7_message *msg = NULL;
 	struct efi_signature_store *db = NULL, *dbx = NULL;
-	struct x509_certificate *cert = NULL;
 	void *new_efi = NULL;
 	u8 *auth, *wincerts_end;
 	size_t new_efi_size, auth_size;
 	bool ret = false;
 
+	debug("%s: Enter, %d\n", __func__, ret);
+
 	if (!efi_secure_boot_enabled())
 		return true;
 
@@ -546,7 +547,17 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 		goto err;
 	}
 
-	/* go through WIN_CERTIFICATE list */
+	/*
+	 * go through WIN_CERTIFICATE list
+	 * NOTE:
+	 * We may have multiple signatures either as WIN_CERTIFICATE's
+	 * in PE header, or as pkcs7 SignerInfo's in SignedData.
+	 * So the verification policy here is:
+	 *   - Success if, at least, one of signatures is verified
+	 *   - unless
+	 *       any of signatures is rejected explicitly, or
+	 *       none of digest algorithms are supported
+	 */
 	for (wincert = wincerts, wincerts_end = (u8 *)wincerts + wincerts_len;
 	     (u8 *)wincert < wincerts_end;
 	     wincert = (WIN_CERTIFICATE *)
@@ -596,42 +607,32 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 		}
 
 		/* try black-list first */
-		if (efi_signature_verify_with_sigdb(regs, msg, dbx, NULL)) {
+		if (efi_signature_verify_one(regs, msg, dbx)) {
 			EFI_PRINT("Signature was rejected by \"dbx\"\n");
 			goto err;
 		}
 
-		if (!efi_signature_verify_signers(msg, dbx)) {
-			EFI_PRINT("Signer was rejected by \"dbx\"\n");
+		if (!efi_signature_check_signers(msg, dbx)) {
+			EFI_PRINT("Signer(s) in \"dbx\"\n");
 			goto err;
-		} else {
-			ret = true;
 		}
 
 		/* try white-list */
-		if (!efi_signature_verify_with_sigdb(regs, msg, db, &cert)) {
-			EFI_PRINT("Verifying signature with \"db\" failed\n");
+		if (!efi_signature_verify_with_sigdb(regs, msg, db, dbx)) {
+			EFI_PRINT("Signature was not verified by \"db\"\n");
 			goto err;
-		} else {
-			ret = true;
-		}
-
-		if (!efi_signature_verify_cert(cert, dbx)) {
-			EFI_PRINT("Certificate was rejected by \"dbx\"\n");
-			goto err;
-		} else {
-			ret = true;
 		}
 	}
+	ret = true;
 
 err:
-	x509_free_certificate(cert);
 	efi_sigstore_free(db);
 	efi_sigstore_free(dbx);
 	pkcs7_free_message(msg);
 	free(regs);
 	free(new_efi);
 
+	debug("%s: Exit, %d\n", __func__, ret);
 	return ret;
 }
 #else
diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index 03080bc0b11c..f76c24a6fa25 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -302,27 +302,110 @@ out:
 }
 
 /**
- * efi_signature_verify_with_sigdb - verify a signature with db
+ * efi_signature_check_revocation - check revocation with dbx
+ * @sinfo:	Signer's info
+ * @cert:	x509 certificate
+ * @dbx:	Revocation signature database
+ *
+ * Search revocation signature database pointed to by @dbx and find
+ * an entry matching to certificate pointed to by @cert.
+ *
+ * While this entry contains revocation time, we don't support timestamp
+ * protocol@this time and any image will be unconditionally revoked
+ * when this match occurs.
+ *
+ * Return:	true if check passed, false otherwise.
+ */
+static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
+					   struct x509_certificate *cert,
+					   struct efi_signature_store *dbx)
+{
+	struct efi_signature_store *siglist;
+	struct efi_sig_data *sig_data;
+	struct image_region reg[1];
+	void *hash = NULL;
+	size_t size = 0;
+	time64_t revoc_time;
+	bool revoked = false;
+
+	EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
+
+	if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
+		goto out;
+
+	EFI_PRINT("Checking revocation against %s\n", cert->subject);
+	for (siglist = dbx; siglist; siglist = siglist->next) {
+		if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
+			continue;
+
+		/* calculate hash of TBSCertificate */
+		reg[0].data = cert->tbs;
+		reg[0].size = cert->tbs_size;
+		if (!efi_hash_regions(reg, 1, &hash, &size))
+			goto out;
+
+		for (sig_data = siglist->sig_data_list; sig_data;
+		     sig_data = sig_data->next) {
+			/*
+			 * struct efi_cert_x509_sha256 {
+			 *	u8 tbs_hash[256/8];
+			 *	time64_t revocation_time;
+			 * };
+			 */
+#ifdef DEBUG
+			if (sig_data->size >= size) {
+				EFI_PRINT("hash in db:\n");
+				print_hex_dump("    ", DUMP_PREFIX_OFFSET,
+					       16, 1,
+					       sig_data->data, size, false);
+			}
+#endif
+			if ((sig_data->size < size + sizeof(time64_t)) ||
+			    memcmp(sig_data->data, hash, size))
+				continue;
+
+			memcpy(&revoc_time, sig_data->data + size,
+			       sizeof(revoc_time));
+			EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
+			/*
+			 * TODO: compare signing timestamp in sinfo
+			 * with revocation time
+			 */
+
+			revoked = true;
+			free(hash);
+			goto out;
+		}
+		free(hash);
+		hash = NULL;
+	}
+out:
+	EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
+	return !revoked;
+}
+
+/**
+ * efi_signature_verify_one - verify signatures with database
  * @regs:	List of regions to be authenticated
  * @msg:	Signature
- * @db:		Signature database for trusted certificates
- * @cert:	x509 certificate that verifies this signature
+ * @db:		Signature database
  *
- * Signature pointed to by @msg against image pointed to by @regs
- * is verified by signature database pointed to by @db.
+ * All the signature pointed to by @msg against image pointed to by @regs
+ * will be verified by signature database pointed to by @db.
  *
- * Return:	true if signature is verified, false if not
+ * Return:	true if verification for one of signatures passed, false
+ *		otherwise
  */
-bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
-				     struct pkcs7_message *msg,
-				     struct efi_signature_store *db,
-				     struct x509_certificate **cert)
+bool efi_signature_verify_one(struct efi_image_regions *regs,
+			      struct pkcs7_message *msg,
+			      struct efi_signature_store *db)
 {
-	struct pkcs7_signed_info *info;
+	struct pkcs7_signed_info *sinfo;
 	struct efi_signature_store *siglist;
+	struct x509_certificate *cert;
 	bool verified = false;
 
-	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, cert);
+	EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, regs, msg, db);
 
 	if (!db)
 		goto out;
@@ -335,27 +418,26 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 		EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
 		for (siglist = db; siglist; siglist = siglist->next)
 			if (efi_signature_verify_with_list(regs, NULL, NULL,
-							   siglist, cert)) {
+							   siglist, &cert)) {
 				verified = true;
-				goto out;
+				break;
 			}
-
 		goto out;
 	}
 
 	/* for signed image or variable */
 	EFI_PRINT("%s: Verify signed image with db\n", __func__);
-	for (info = msg->signed_infos; info; info = info->next) {
+	for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
 		EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
-			  info->sig->hash_algo, info->sig->pkey_algo);
+			  sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
 
-		for (siglist = db; siglist; siglist = siglist->next) {
-			if (efi_signature_verify_with_list(regs, msg, info,
-							   siglist, cert)) {
+		for (siglist = db; siglist; siglist = siglist->next)
+			if (efi_signature_verify_with_list(regs, msg, sinfo,
+							   siglist, &cert)) {
 				verified = true;
 				goto out;
 			}
-		}
+		EFI_PRINT("Valid certificate not in \"db\"\n");
 	}
 
 out:
@@ -364,150 +446,108 @@ out:
 }
 
 /**
- * efi_search_siglist - search signature list for a certificate
- * @cert:	x509 certificate
- * @siglist:	Signature list
- * @revoc_time:	Pointer to buffer for revocation time
+ * efi_signature_verify_with_sigdb - verify signatures with db and dbx
+ * @regs:	List of regions to be authenticated
+ * @msg:	Signature
+ * @db:		Signature database for trusted certificates
+ * @dbx:	Revocation signature database
  *
- * Search signature list pointed to by @siglist and find a certificate
- * pointed to by @cert.
- * If found, revocation time that is specified in signature database is
- * returned in @revoc_time.
+ * All the signature pointed to by @msg against image pointed to by @regs
+ * will be verified by signature database pointed to by @db and @dbx.
  *
- * Return:	true if certificate is found, false if not
+ * Return:	true if verification for all signatures passed, false otherwise
  */
-static bool efi_search_siglist(struct x509_certificate *cert,
-			       struct efi_signature_store *siglist,
-			       time64_t *revoc_time)
+bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
+				     struct pkcs7_message *msg,
+				     struct efi_signature_store *db,
+				     struct efi_signature_store *dbx)
 {
-	struct image_region reg[1];
-	void *hash = NULL, *msg = NULL;
-	struct efi_sig_data *sig_data;
-	bool found = false;
+	struct pkcs7_signed_info *info;
+	struct efi_signature_store *siglist;
+	struct x509_certificate *cert;
+	bool verified = false;
 
-	/* can be null */
-	if (!siglist->sig_data_list)
-		return false;
+	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
 
-	if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256)) {
-		/* TODO: other hash algos */
-		EFI_PRINT("Certificate's digest type is not supported: %pUl\n",
-			  &siglist->sig_type);
+	if (!db)
 		goto out;
-	}
 
-	/* calculate hash of TBSCertificate */
-	msg = calloc(1, SHA256_SUM_LEN);
-	if (!msg) {
-		EFI_PRINT("Out of memory\n");
+	if (!db->sig_data_list)
 		goto out;
-	}
 
-	hash = calloc(1, SHA256_SUM_LEN);
-	if (!hash) {
-		EFI_PRINT("Out of memory\n");
+	/* for unsigned image */
+	if (!msg) {
+		EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
+		for (siglist = db; siglist; siglist = siglist->next)
+			if (efi_signature_verify_with_list(regs, NULL, NULL,
+							   siglist, &cert)) {
+				verified = true;
+				break;
+			}
 		goto out;
 	}
 
-	reg[0].data = cert->tbs;
-	reg[0].size = cert->tbs_size;
-	hash_calculate("sha256", reg, 1, msg);
+	/* for signed image or variable */
+	EFI_PRINT("%s: Verify signed image with db\n", __func__);
+	for (info = msg->signed_infos; info; info = info->next) {
+		EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
+			  info->sig->hash_algo, info->sig->pkey_algo);
 
-	/* go through signature list */
-	for (sig_data = siglist->sig_data_list; sig_data;
-	     sig_data = sig_data->next) {
-		/*
-		 * struct efi_cert_x509_sha256 {
-		 *	u8 tbs_hash[256/8];
-		 *	time64_t revocation_time;
-		 * };
-		 */
-		if ((sig_data->size >= SHA256_SUM_LEN + sizeof(time64_t)) &&
-		    !memcmp(sig_data->data, msg, SHA256_SUM_LEN)) {
-			memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
-			       sizeof(*revoc_time));
-			EFI_PRINT("revocation time: %llu\n", *revoc_time);
-			found = true;
+		for (siglist = db; siglist; siglist = siglist->next) {
+			if (efi_signature_verify_with_list(regs, msg, info,
+							   siglist, &cert))
+				break;
+		}
+		if (!siglist) {
+			EFI_PRINT("Valid certificate not in \"db\"\n");
 			goto out;
 		}
-	}
-
-out:
-	free(hash);
-	free(msg);
-
-	return found;
-}
-
-/**
- * efi_signature_verify_cert - verify a certificate with dbx
- * @cert:	x509 certificate
- * @dbx:	Signature database
- *
- * Search signature database pointed to by @dbx and find a certificate
- * pointed to by @cert.
- * This function is expected to be used against "dbx".
- *
- * Return:	true if a certificate is not rejected, false otherwise.
- */
-bool efi_signature_verify_cert(struct x509_certificate *cert,
-			       struct efi_signature_store *dbx)
-{
-	struct efi_signature_store *siglist;
-	time64_t revoc_time;
-	bool found = false;
 
-	EFI_PRINT("%s: Enter, %p, %p\n", __func__, dbx, cert);
-
-	if (!cert)
-		return false;
-
-	for (siglist = dbx; siglist; siglist = siglist->next) {
-		if (efi_search_siglist(cert, siglist, &revoc_time)) {
-			/* TODO */
-			/* compare signing time with revocation time */
+		if (!dbx || efi_signature_check_revocation(info, cert, dbx))
+			continue;
 
-			found = true;
-			break;
-		}
+		EFI_PRINT("Certificate in \"dbx\"\n");
+		goto out;
 	}
+	verified = true;
 
-	EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
-	return !found;
+out:
+	EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
+	return verified;
 }
 
 /**
- * efi_signature_verify_signers - verify signers' certificates with dbx
+ * efi_signature_check_signers - check revocation against all signers with dbx
  * @msg:	Signature
- * @dbx:	Signature database
+ * @dbx:	Revocation signature database
  *
- * Determine if any of signers' certificates in @msg may be verified
- * by any of certificates in signature database pointed to by @dbx.
- * This function is expected to be used against "dbx".
+ * Determine if none of signers' certificates in @msg are revoked
+ * by signature database pointed to by @dbx.
  *
- * Return:	true if none of certificates is rejected, false otherwise.
+ * Return:	true if all signers passed, false otherwise.
  */
-bool efi_signature_verify_signers(struct pkcs7_message *msg,
-				  struct efi_signature_store *dbx)
+bool efi_signature_check_signers(struct pkcs7_message *msg,
+				 struct efi_signature_store *dbx)
 {
-	struct pkcs7_signed_info *info;
-	bool found = false;
+	struct pkcs7_signed_info *sinfo;
+	bool revoked = false;
 
 	EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
 
-	if (!msg)
+	if (!msg || !dbx)
 		goto out;
 
-	for (info = msg->signed_infos; info; info = info->next) {
-		if (info->signer &&
-		    !efi_signature_verify_cert(info->signer, dbx)) {
-			found = true;
-			goto out;
+	for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
+		if (sinfo->signer &&
+		    !efi_signature_check_revocation(sinfo, sinfo->signer,
+						    dbx)) {
+			revoked = true;
+			break;
 		}
 	}
 out:
-	EFI_PRINT("%s: Exit, verified: %d\n", __func__, !found);
-	return !found;
+	EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
+	return !revoked;
 }
 
 /**
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 11/17] efi_loader: image_loader: add digest-based verification for signed image
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (9 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search" AKASHI Takahiro
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

In case that a type of certificate in "db" or "dbx" is
EFI_CERT_X509_SHA256_GUID, it is actually not a certificate which contains
a public key for RSA decryption, but a digest of image to be loaded.
If the value matches to a value calculated from a given binary image, it is
granted for loading.

With this patch, common digest check code, which used to be used for
unsigned image verification, will be extracted from
efi_signature_verify_with_sigdb() into efi_signature_lookup_digest(), and
extra step for digest check will be added to efi_image_authenticate().

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 include/efi_loader.h              |   2 +
 lib/efi_loader/efi_image_loader.c |  44 ++++++++--
 lib/efi_loader/efi_signature.c    | 128 ++++++++++++++----------------
 3 files changed, 99 insertions(+), 75 deletions(-)

diff --git a/include/efi_loader.h b/include/efi_loader.h
index 9f49a8a349fa..a95f9b339027 100644
--- a/include/efi_loader.h
+++ b/include/efi_loader.h
@@ -762,6 +762,8 @@ struct efi_signature_store {
 struct x509_certificate;
 struct pkcs7_message;
 
+bool efi_signature_lookup_digest(struct efi_image_regions *regs,
+				 struct efi_signature_store *db);
 bool efi_signature_verify_one(struct efi_image_regions *regs,
 			      struct pkcs7_message *msg,
 			      struct efi_signature_store *db);
diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
index 222396b49eda..584a841116df 100644
--- a/lib/efi_loader/efi_image_loader.c
+++ b/lib/efi_loader/efi_image_loader.c
@@ -449,16 +449,16 @@ static bool efi_image_unsigned_authenticate(struct efi_image_regions *regs)
 	}
 
 	/* try black-list first */
-	if (efi_signature_verify_one(regs, NULL, dbx)) {
-		EFI_PRINT("Image is not signed and rejected by \"dbx\"\n");
+	if (efi_signature_lookup_digest(regs, dbx)) {
+		EFI_PRINT("Image is not signed and its digest found in \"dbx\"\n");
 		goto out;
 	}
 
 	/* try white-list */
-	if (efi_signature_verify_one(regs, NULL, db))
+	if (efi_signature_lookup_digest(regs, db))
 		ret = true;
 	else
-		EFI_PRINT("Image is not signed and not found in \"db\" or \"dbx\"\n");
+		EFI_PRINT("Image is not signed and its digest not found in \"db\" or \"dbx\"\n");
 
 out:
 	efi_sigstore_free(db);
@@ -606,6 +606,25 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 			continue;
 		}
 
+		/*
+		 * NOTE:
+		 * UEFI specification defines two signature types possible
+		 * in signature database:
+		 * a. x509 certificate, where a signature in image is
+		 *    a message digest encrypted by RSA public key
+		 *    (EFI_CERT_X509_GUID)
+		 * b. bare hash value of message digest
+		 *    (EFI_CERT_SHAxxx_GUID)
+		 *
+		 * efi_signature_verify() handles case (a), while
+		 * efi_signature_lookup_digest() handles case (b).
+		 *
+		 * There is a third type:
+		 * c. message digest of a certificate
+		 *    (EFI_CERT_X509_SHAAxxx_GUID)
+		 * This type of signature is used only in revocation list
+		 * (dbx) and handled as part of efi_signatgure_verify().
+		 */
 		/* try black-list first */
 		if (efi_signature_verify_one(regs, msg, dbx)) {
 			EFI_PRINT("Signature was rejected by \"dbx\"\n");
@@ -617,11 +636,22 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
 			goto err;
 		}
 
-		/* try white-list */
-		if (!efi_signature_verify_with_sigdb(regs, msg, db, dbx)) {
-			EFI_PRINT("Signature was not verified by \"db\"\n");
+		if (efi_signature_lookup_digest(regs, dbx)) {
+			EFI_PRINT("Image's digest was found in \"dbx\"\n");
 			goto err;
 		}
+
+		/* try white-list */
+		if (efi_signature_verify_with_sigdb(regs, msg, db, dbx))
+			continue;
+
+		debug("Signature was not verified by \"db\"\n");
+
+		if (efi_signature_lookup_digest(regs, db))
+			continue;
+
+		debug("Image's digest was not found in \"db\" or \"dbx\"\n");
+		goto err;
 	}
 	ret = true;
 
diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
index f76c24a6fa25..a87cbe520f56 100644
--- a/lib/efi_loader/efi_signature.c
+++ b/lib/efi_loader/efi_signature.c
@@ -199,55 +199,43 @@ out:
 }
 
 /**
- * efi_signature_verify_with_list - verify a signature with signature list
- * @regs:		List of regions to be authenticated
- * @msg:		Signature
- * @signed_info:	Pointer to PKCS7's signed_info
- * @siglist:		Signature list for certificates
- * @valid_cert:		x509 certificate that verifies this signature
+ * efi_signature_lookup_digest - search for an image's digest in sigdb
+ * @regs:	List of regions to be authenticated
+ * @db:		Signature database for trusted certificates
  *
- * Signature pointed to by @signed_info against image pointed to by @regs
- * is verified by signature list pointed to by @siglist.
- * Signature database is a simple concatenation of one or more
- * signature list(s).
+ * A message digest of image pointed to by @regs is calculated and
+ * its hash value is compared to entries in signature database pointed
+ * to by @db.
  *
- * Return:	true if signature is verified, false if not
+ * Return:	true if found, false if not
  */
-static
-bool efi_signature_verify_with_list(struct efi_image_regions *regs,
-				    struct pkcs7_message *msg,
-				    struct pkcs7_signed_info *signed_info,
-				    struct efi_signature_store *siglist,
-				    struct x509_certificate **valid_cert)
+bool efi_signature_lookup_digest(struct efi_image_regions *regs,
+				 struct efi_signature_store *db)
 {
-	struct x509_certificate *cert;
+	struct efi_signature_store *siglist;
 	struct efi_sig_data *sig_data;
-	bool verified = false;
+	void *hash = NULL;
+	size_t size = 0;
+	bool found = false;
 
-	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
-		  regs, signed_info, siglist, valid_cert);
+	EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
 
-	if (!signed_info) {
-		void *hash = NULL;
-		size_t size;
+	if (!regs || !db || !db->sig_data_list)
+		goto out;
 
-		EFI_PRINT("%s: unsigned image\n", __func__);
-		/*
-		 * verify based on calculated hash value
-		 * TODO: support other hash algorithms
-		 */
+	for (siglist = db; siglist; siglist = siglist->next) {
+		/* TODO: support other hash algorithms */
 		if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
 			EFI_PRINT("Digest algorithm is not supported: %pUl\n",
 				  &siglist->sig_type);
-			goto out;
+			break;
 		}
 
 		if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
-			EFI_PRINT("Digesting unsigned image failed\n");
-			goto out;
+			EFI_PRINT("Digesting an image failed\n");
+			break;
 		}
 
-		/* go through the list */
 		for (sig_data = siglist->sig_data_list; sig_data;
 		     sig_data = sig_data->next) {
 #ifdef DEBUG
@@ -255,18 +243,52 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
 			print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 				       sig_data->data, sig_data->size, false);
 #endif
-			if ((sig_data->size == size) &&
+			if (sig_data->size == size &&
 			    !memcmp(sig_data->data, hash, size)) {
-				verified = true;
+				found = true;
 				free(hash);
 				goto out;
 			}
 		}
+
 		free(hash);
-		goto out;
+		hash = NULL;
 	}
 
-	EFI_PRINT("%s: signed image\n", __func__);
+out:
+	EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
+	return found;
+}
+
+/**
+ * efi_signature_verify_with_list - verify a signature with signature list
+ * @regs:		List of regions to be authenticated
+ * @msg:		Signature
+ * @signed_info:	Pointer to PKCS7's signed_info
+ * @siglist:		Signature list for certificates
+ * @valid_cert:		x509 certificate that verifies this signature
+ *
+ * Signature pointed to by @signed_info against image pointed to by @regs
+ * is verified by signature list pointed to by @siglist.
+ * Signature database is a simple concatenation of one or more
+ * signature list(s).
+ *
+ * Return:	true if signature is verified, false if not
+ */
+static
+bool efi_signature_verify_with_list(struct efi_image_regions *regs,
+				    struct pkcs7_message *msg,
+				    struct pkcs7_signed_info *signed_info,
+				    struct efi_signature_store *siglist,
+				    struct x509_certificate **valid_cert)
+{
+	struct x509_certificate *cert;
+	struct efi_sig_data *sig_data;
+	bool verified = false;
+
+	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__,
+		  regs, signed_info, siglist, valid_cert);
+
 	if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509)) {
 		EFI_PRINT("Signature type is not supported: %pUl\n",
 			  &siglist->sig_type);
@@ -413,19 +435,6 @@ bool efi_signature_verify_one(struct efi_image_regions *regs,
 	if (!db->sig_data_list)
 		goto out;
 
-	/* for unsigned image */
-	if (!msg) {
-		EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
-		for (siglist = db; siglist; siglist = siglist->next)
-			if (efi_signature_verify_with_list(regs, NULL, NULL,
-							   siglist, &cert)) {
-				verified = true;
-				break;
-			}
-		goto out;
-	}
-
-	/* for signed image or variable */
 	EFI_PRINT("%s: Verify signed image with db\n", __func__);
 	for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
 		EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
@@ -469,26 +478,9 @@ bool efi_signature_verify_with_sigdb(struct efi_image_regions *regs,
 
 	EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
 
-	if (!db)
-		goto out;
-
-	if (!db->sig_data_list)
+	if (!regs || !msg || !db || !db->sig_data_list)
 		goto out;
 
-	/* for unsigned image */
-	if (!msg) {
-		EFI_PRINT("%s: Verify unsigned image with db\n", __func__);
-		for (siglist = db; siglist; siglist = siglist->next)
-			if (efi_signature_verify_with_list(regs, NULL, NULL,
-							   siglist, &cert)) {
-				verified = true;
-				break;
-			}
-		goto out;
-	}
-
-	/* for signed image or variable */
-	EFI_PRINT("%s: Verify signed image with db\n", __func__);
 	for (info = msg->signed_infos; info; info = info->next) {
 		EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
 			  info->sig->hash_algo, info->sig->pkey_algo);
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search"
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (10 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 11/17] efi_loader: image_loader: add digest-based verification for signed image AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 15:52   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar AKASHI Takahiro
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Currently, we don't use any regular expression in matching outputs from
U-Boot. Since its use is just redundant, we can remove all.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 .../py/tests/test_efi_secboot/test_authvar.py | 73 +++++++++----------
 test/py/tests/test_efi_secboot/test_signed.py | 34 ++++-----
 .../tests/test_efi_secboot/test_unsigned.py   | 32 ++++----
 3 files changed, 65 insertions(+), 74 deletions(-)

diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py
index 55dcaa95f1ea..766ed9283605 100644
--- a/test/py/tests/test_efi_secboot/test_authvar.py
+++ b/test/py/tests/test_efi_secboot/test_authvar.py
@@ -9,7 +9,6 @@ This test verifies variable authentication
 """
 
 import pytest
-import re
 from defs import *
 
 @pytest.mark.boardspec('sandbox')
@@ -40,7 +39,7 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 PK.auth',
                 'setenv -e -nv -bs -rt -i 4000000,$filesize PK'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 1c'):
             # Test Case 1c, install PK
@@ -48,7 +47,7 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 PK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'printenv -e -n PK'])
-            assert(re.search('PK:', ''.join(output)))
+            assert('PK:' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
@@ -62,25 +61,25 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.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:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -i 4000000,$filesize KEK'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'printenv -e -n KEK'])
-            assert(re.search('KEK:', ''.join(output)))
+            assert('KEK:' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
@@ -91,14 +90,14 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
@@ -109,14 +108,14 @@ class TestEfiAuthVar(object):
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
@@ -139,20 +138,20 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db1.auth',
                 'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.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:1 4000000 db.esl',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 2c'):
             # Test Case 2c, update with correct signature
@@ -160,8 +159,8 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db1.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
     def test_efi_var_auth3(self, u_boot_console, efi_boot_env):
         """
@@ -180,20 +179,20 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db1.auth',
                 'setenv -e -nv -bs -rt -a -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.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:1 4000000 db.esl',
                 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 3c'):
             # Test Case 3c, update with correct signature
@@ -201,8 +200,8 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db1.auth',
                 'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
     def test_efi_var_auth4(self, u_boot_console, efi_boot_env):
         """
@@ -221,22 +220,22 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'setenv -e -nv -bs -rt db',
                 'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.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 -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('db:', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
+            assert('db:' in ''.join(output))
 
     def test_efi_var_auth5(self, u_boot_console, efi_boot_env):
         """
@@ -255,15 +254,15 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
                 'printenv -e -n PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('PK:', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('PK:' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 PK_null.esl',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'printenv -e -n PK'])
-            assert(re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('PK:', ''.join(output)))
+            assert('Failed to set EFI variable' in ''.join(output))
+            assert('PK:' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 5b'):
             # Test Case 5b, Uninstall PK with correct signature
@@ -271,8 +270,8 @@ class TestEfiAuthVar(object):
                 'fatload host 0:1 4000000 PK_null.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK',
                 'printenv -e -n PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
-            assert(re.search('\"PK\" not defined', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            assert('\"PK\" not defined' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 584282b338bc..19d78b1b64e0 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -9,7 +9,6 @@ This test verifies image authentication for signed images.
 """
 
 import pytest
-import re
 from defs import *
 
 @pytest.mark.boardspec('sandbox')
@@ -32,7 +31,7 @@ class TestEfiSignedImage(object):
                 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('Hello, world!', ''.join(output)))
+            assert('Hello, world!' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 1b'):
             # Test Case 1b, run unsigned image if no db/dbx
@@ -40,7 +39,7 @@ class TestEfiSignedImage(object):
                 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
-            assert(re.search('Hello, world!', ''.join(output)))
+            assert('Hello, world!' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 1c'):
             # Test Case 1c, not authenticated by db
@@ -51,24 +50,23 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 PK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO2\' failed', ''.join(output)))
+            assert('\'HELLO2\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 2',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.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)))
+            assert('Hello, world!' in ''.join(output))
 
     def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
         """
@@ -86,32 +84,30 @@ class TestEfiSignedImage(object):
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 PK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO\' failed', ''.join(output)))
+            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.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([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO\' failed', ''.join(output)))
+            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.join(output))
diff --git a/test/py/tests/test_efi_secboot/test_unsigned.py b/test/py/tests/test_efi_secboot/test_unsigned.py
index 22d849afb89b..c42c5ddc4774 100644
--- a/test/py/tests/test_efi_secboot/test_unsigned.py
+++ b/test/py/tests/test_efi_secboot/test_unsigned.py
@@ -9,7 +9,6 @@ This test verifies image authentication for unsigned images.
 """
 
 import pytest
-import re
 from defs import *
 
 @pytest.mark.boardspec('sandbox')
@@ -33,19 +32,18 @@ class TestEfiUnsignedImage(object):
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO\' failed', ''.join(output)))
+            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.join(output))
 
     def test_efi_unsigned_image_auth2(self, u_boot_console, efi_boot_env):
         """
@@ -63,13 +61,13 @@ class TestEfiUnsignedImage(object):
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('Hello, world!', ''.join(output)))
+            assert('Hello, world!' in ''.join(output))
 
     def test_efi_unsigned_image_auth3(self, u_boot_console, efi_boot_env):
         """
@@ -87,35 +85,33 @@ class TestEfiUnsignedImage(object):
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
 		'fatload host 0:1 4000000 PK.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO\' failed', ''.join(output)))
+            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 3b'):
             # Test Case 3b, rejected by dbx even if db allows
             output = u_boot_console.run_command_list([
 		'fatload host 0:1 4000000 db_hello.auth',
 		'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
-            assert(not re.search('Failed to set EFI variable', ''.join(output)))
+            assert(not 'Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi ""',
                 'efidebug boot next 1',
                 'bootefi bootmgr'])
-            assert(re.search('\'HELLO\' failed', ''.join(output)))
+            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
-            assert(re.search('efi_start_image[(][)] returned: 26',
-                ''.join(output)))
-            assert(not re.search('Hello, world!', ''.join(output)))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            assert(not 'Hello, world!' in ''.join(output))
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (11 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search" AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 16:08   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases AKASHI Takahiro
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

In the test case (1g) of test_authvar, "db" is mistakenly used,
and it ends up being the exact same as (1f).
So correct it as "dbx" test case.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/test_authvar.py | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/test/py/tests/test_efi_secboot/test_authvar.py b/test/py/tests/test_efi_secboot/test_authvar.py
index 766ed9283605..148aa3123e4f 100644
--- a/test/py/tests/test_efi_secboot/test_authvar.py
+++ b/test/py/tests/test_efi_secboot/test_authvar.py
@@ -106,16 +106,16 @@ class TestEfiAuthVar(object):
         with u_boot_console.log.section('Test Case 1g'):
             # Test Case 1g, install dbx
             output = u_boot_console.run_command_list([
-                'fatload host 0:1 4000000 db.auth',
-                'setenv -e -nv -bs -rt -i 4000000,$filesize db'])
+                'fatload host 0:1 4000000 dbx.auth',
+                'setenv -e -nv -bs -rt -i 4000000,$filesize dbx'])
             assert('Failed to set EFI variable' in ''.join(output))
 
             output = u_boot_console.run_command_list([
-                'fatload host 0:1 4000000 db.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
-                'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f db'])
+                'fatload host 0:1 4000000 dbx.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
+                'printenv -e -n -guid d719b2cb-3d3a-4596-a3bc-dad00e67656f dbx'])
             assert(not 'Failed to set EFI variable' in ''.join(output))
-            assert('db:' in ''.join(output))
+            assert('dbx:' in ''.join(output))
 
             output = u_boot_console.run_command(
                 'printenv -e SecureBoot')
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (12 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-07-03 16:14   ` Heinrich Schuchardt
  2020-06-09  5:09 ` [PATCH v2 15/17] test/py: efi_secboot: add a test against certificate revocation AKASHI Takahiro
                   ` (2 subsequent siblings)
  16 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Split the existing test case-1 into case1 and a new case-2:
case-1 for non-SecureBoot mode; case-2 for SecureBoot mode.

In addition, one corner case is added to case-2; a image is signed
but a corresponding certificate is not yet installed in "db."

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/test_signed.py | 66 +++++++++++--------
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 19d78b1b64e0..5267b7ab4e86 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -20,12 +20,12 @@ from defs import *
 class TestEfiSignedImage(object):
     def test_efi_signed_image_auth1(self, u_boot_console, efi_boot_env):
         """
-        Test Case 1 - authenticated by db
+        Test Case 1 - Secure boot is not in force
         """
         u_boot_console.restart_uboot()
         disk_img = efi_boot_env
         with u_boot_console.log.section('Test Case 1a'):
-            # Test Case 1a, run signed image if no db/dbx
+            # Test Case 1a, run signed image if no PK
             output = u_boot_console.run_command_list([
                 'host bind 0 %s' % disk_img,
                 'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
@@ -34,48 +34,66 @@ class TestEfiSignedImage(object):
             assert('Hello, world!' in ''.join(output))
 
         with u_boot_console.log.section('Test Case 1b'):
-            # Test Case 1b, run unsigned image if no db/dbx
+            # Test Case 1b, run unsigned image if no PK
             output = u_boot_console.run_command_list([
                 'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
                 'bootefi bootmgr'])
             assert('Hello, world!' in ''.join(output))
 
-        with u_boot_console.log.section('Test Case 1c'):
-            # Test Case 1c, not authenticated by db
+    def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
+        """
+        Test Case 2 - Secure boot is in force,
+                      authenticated by db (TEST_db certificate in db)
+        """
+        u_boot_console.restart_uboot()
+        disk_img = efi_boot_env
+        with u_boot_console.log.section('Test Case 2a'):
+            # Test Case 2a, db is not yet installed
             output = u_boot_console.run_command_list([
-                'fatload host 0:1 4000000 db.auth',
-                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+                'host bind 0 %s' % disk_img,
                 'fatload host 0:1 4000000 KEK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
                 'fatload host 0:1 4000000 PK.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
             assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO1 host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO1\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 2 HELLO2 host 0:1 /helloworld.efi ""',
                 'efidebug boot next 2',
-                'bootefi bootmgr'])
+                'efidebug test bootmgr'])
             assert('\'HELLO2\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+
+        with u_boot_console.log.section('Test Case 2b'):
+            # Test Case 2b, authenticated by db
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 db.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 2',
                 'efidebug test bootmgr'])
+            assert('\'HELLO2\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
-            assert(not 'Hello, world!' in ''.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('Hello, world!' in ''.join(output))
 
-    def test_efi_signed_image_auth2(self, u_boot_console, efi_boot_env):
+    def test_efi_signed_image_auth3(self, u_boot_console, efi_boot_env):
         """
-        Test Case 2 - rejected by dbx
+        Test Case 3 - rejected by dbx (TEST_db certificate in dbx)
         """
         u_boot_console.restart_uboot()
         disk_img = efi_boot_env
-        with u_boot_console.log.section('Test Case 2a'):
-            # Test Case 2a, rejected by dbx
+        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,
                 'fatload host 0:1 4000000 db.auth',
@@ -87,27 +105,19 @@ class TestEfiSignedImage(object):
             assert(not 'Failed to set EFI variable' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
-                'efidebug boot next 1',
-                'bootefi bootmgr'])
-            assert('\'HELLO\' failed' in ''.join(output))
-            output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
-            assert(not 'Hello, world!' in ''.join(output))
 
-        with u_boot_console.log.section('Test Case 2b'):
-            # Test Case 2b, rejected by dbx even if db allows
+        with u_boot_console.log.section('Test Case 3b'):
+            # Test Case 3b, rejected by dbx even if db allows
             output = u_boot_console.run_command_list([
                 'fatload host 0:1 4000000 db.auth',
                 'setenv -e -nv -bs -rt -at -i 4000000,$filesize db'])
             assert(not 'Failed to set EFI variable' in ''.join(output))
-            output = u_boot_console.run_command_list([
-                'efidebug boot next 1',
-                'bootefi bootmgr'])
-            assert('\'HELLO\' failed' in ''.join(output))
             output = u_boot_console.run_command_list([
                 'efidebug boot next 1',
                 'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
-            assert(not 'Hello, world!' in ''.join(output))
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 15/17] test/py: efi_secboot: add a test against certificate revocation
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (13 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 16/17] test/py: efi_secboot: add a test for multiple signatures AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 17/17] test/py: efi_secboot: add a test for verifying with digest of signed image AKASHI Takahiro
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Revocation database (dbx) may have not only certificates, but also
message digests of certificates with revocation time
(EFI_CERT_X509_SHA256_GUILD).

In this test case, if the database has such a digest and if the value
matches to a certificate that created a given image's signature,
authentication should fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/conftest.py    |  6 ++++-
 test/py/tests/test_efi_secboot/test_signed.py | 26 +++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py
index 5d99b8b7189e..13687a2da1a6 100644
--- a/test/py/tests/test_efi_secboot/conftest.py
+++ b/test/py/tests/test_efi_secboot/conftest.py
@@ -103,12 +103,16 @@ def efi_boot_env(request, u_boot_config):
         ## db1-update
         check_call('cd %s; %ssign-efi-sig-list -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth'
                             % (mnt_point, EFITOOLS_PATH), shell=True)
-        ## dbx
+        ## dbx (TEST_dbx certificate)
         check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_dbx/ -keyout dbx.key -out dbx.crt -nodes -days 365'
                             % mnt_point, shell=True)
         check_call('cd %s; %scert-to-efi-sig-list -g %s dbx.crt dbx.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx.esl dbx.auth'
                             % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                             shell=True)
+        ## dbx_hash (digest of TEST_db certificate)
+        check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db.crt dbx_hash.crl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx_hash.crl dbx_hash.auth'
+                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+                            shell=True)
 
         # Copy image
         check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True)
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 5267b7ab4e86..21ae2bc5ed48 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -121,3 +121,29 @@ class TestEfiSignedImage(object):
                 'efidebug test bootmgr'])
             assert('\'HELLO\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
+
+    def test_efi_signed_image_auth4(self, u_boot_console, efi_boot_env):
+        """
+        Test Case 4 - revoked by dbx (digest of TEST_db certificate in dbx)
+        """
+        u_boot_console.restart_uboot()
+        disk_img = efi_boot_env
+        with u_boot_console.log.section('Test Case 4'):
+            # Test Case 4, rejected by dbx
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatload host 0:1 4000000 dbx_hash.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx',
+                'fatload host 0:1 4000000 db.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+                'fatload host 0:1 4000000 KEK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+                'fatload host 0:1 4000000 PK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 16/17] test/py: efi_secboot: add a test for multiple signatures
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (14 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 15/17] test/py: efi_secboot: add a test against certificate revocation AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  2020-06-09  5:09 ` [PATCH v2 17/17] test/py: efi_secboot: add a test for verifying with digest of signed image AKASHI Takahiro
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

In this test case, an image is signed multiple times with different
keys. If any of signatures contained is not verified, the whole
authentication check should fail.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/conftest.py    |  7 +++
 test/py/tests/test_efi_secboot/test_signed.py | 51 +++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py
index 13687a2da1a6..6b6a40c22336 100644
--- a/test/py/tests/test_efi_secboot/conftest.py
+++ b/test/py/tests/test_efi_secboot/conftest.py
@@ -113,6 +113,10 @@ def efi_boot_env(request, u_boot_config):
         check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db.crt dbx_hash.crl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx_hash.crl dbx_hash.auth'
                             % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                             shell=True)
+        ## dbx_hash1 (digest of TEST_db1 certificate)
+        check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db1.crt dbx_hash1.crl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx_hash1.crl dbx_hash1.auth'
+                            % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
+                            shell=True)
 
         # Copy image
         check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True)
@@ -120,6 +124,9 @@ def efi_boot_env(request, u_boot_config):
         ## Sign image
         check_call('cd %s; sbsign --key db.key --cert db.crt helloworld.efi'
                             % mnt_point, shell=True)
+        ## Sign already-signed image with another key
+        check_call('cd %s; sbsign --key db1.key --cert db1.crt --output helloworld.efi.signed_2sigs helloworld.efi.signed'
+                            % mnt_point, shell=True)
         ## Digest image
         check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth'
                             % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index 21ae2bc5ed48..bcd796324a77 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -147,3 +147,54 @@ class TestEfiSignedImage(object):
                 'efidebug test bootmgr'])
             assert('\'HELLO\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
+
+    def test_efi_signed_image_auth5(self, u_boot_console, efi_boot_env):
+        """
+        Test Case 5 - multiple signatures
+                        one signed with TEST_db, and
+                        one signed with TEST_db1
+        """
+        u_boot_console.restart_uboot()
+        disk_img = efi_boot_env
+        with u_boot_console.log.section('Test Case 5a'):
+            # Test Case 5a, rejected if any of signatures is not verified
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatload host 0:1 4000000 db.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+                'fatload host 0:1 4000000 KEK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+                'fatload host 0:1 4000000 PK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+
+        with u_boot_console.log.section('Test Case 5b'):
+            # Test Case 5b, authenticated if both signatures are verified
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 db1.auth',
+                'setenv -e -nv -bs -rt -at -a -i 4000000,$filesize db'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+                'efidebug boot next 1',
+                'bootefi bootmgr'])
+            assert('Hello, world!' in ''.join(output))
+
+        with u_boot_console.log.section('Test Case 5c'):
+            # Test Case 5c, rejected if any of signatures is revoked
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 dbx_hash1.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed_2sigs ""',
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 17/17] test/py: efi_secboot: add a test for verifying with digest of signed image
  2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
                   ` (15 preceding siblings ...)
  2020-06-09  5:09 ` [PATCH v2 16/17] test/py: efi_secboot: add a test for multiple signatures AKASHI Takahiro
@ 2020-06-09  5:09 ` AKASHI Takahiro
  16 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-06-09  5:09 UTC (permalink / raw)
  To: u-boot

Signature database (db or dbx) may have not only certificates that contain
a public key for RSA decryption, but also digests of signed images.

In this test case, if database has an image's digest (EFI_CERT_SHA256_GUID)
and if the value matches to a hash value calculated from image's binary,
authentication should pass in case of db, and fail in case of dbx.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_secboot/conftest.py    | 11 +++++
 test/py/tests/test_efi_secboot/test_signed.py | 49 +++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py
index 6b6a40c22336..5ac0389064e8 100644
--- a/test/py/tests/test_efi_secboot/conftest.py
+++ b/test/py/tests/test_efi_secboot/conftest.py
@@ -117,6 +117,10 @@ def efi_boot_env(request, u_boot_config):
         check_call('cd %s; %scert-to-efi-hash-list -g %s -t 0 -s 256 db1.crt dbx_hash1.crl; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx dbx_hash1.crl dbx_hash1.auth'
                             % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH),
                             shell=True)
+        ## dbx_db (with TEST_db certificate)
+        check_call('cd %s; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx db.esl dbx_db.auth'
+                            % (mnt_point, EFITOOLS_PATH),
+                            shell=True)
 
         # Copy image
         check_call('cp %s %s' % (HELLO_PATH, mnt_point), shell=True)
@@ -131,6 +135,13 @@ def efi_boot_env(request, u_boot_config):
         check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth'
                             % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
                             shell=True)
+        check_call('cd %s; %shash-to-efi-sig-list helloworld.efi.signed db_hello_signed.hash; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db_hello_signed.hash db_hello_signed.auth'
+                            % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH),
+                            shell=True)
+        check_call('cd %s; %ssign-efi-sig-list -c KEK.crt -k KEK.key dbx db_hello_signed.hash dbx_hello_signed.auth'
+                            % (mnt_point, EFITOOLS_PATH),
+                            shell=True)
+
 
         check_call('sudo umount %s' % loop_dev, shell=True)
         check_call('sudo losetup -d %s' % loop_dev, shell=True)
diff --git a/test/py/tests/test_efi_secboot/test_signed.py b/test/py/tests/test_efi_secboot/test_signed.py
index bcd796324a77..441f4906c865 100644
--- a/test/py/tests/test_efi_secboot/test_signed.py
+++ b/test/py/tests/test_efi_secboot/test_signed.py
@@ -198,3 +198,52 @@ class TestEfiSignedImage(object):
                 'efidebug test bootmgr'])
             assert('\'HELLO\' failed' in ''.join(output))
             assert('efi_start_image() returned: 26' in ''.join(output))
+
+    def test_efi_signed_image_auth6(self, u_boot_console, efi_boot_env):
+        """
+        Test Case 6 - using digest of signed image in database
+        """
+        u_boot_console.restart_uboot()
+        disk_img = efi_boot_env
+        with u_boot_console.log.section('Test Case 6a'):
+            # Test Case 6a, verified by image's digest in db
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatload host 0:1 4000000 db_hello_signed.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+                'fatload host 0:1 4000000 KEK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize KEK',
+                'fatload host 0:1 4000000 PK.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize PK'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot add 1 HELLO host 0:1 /helloworld.efi.signed ""',
+                'efidebug boot next 1',
+                'bootefi bootmgr'])
+            assert('Hello, world!' in ''.join(output))
+
+        with u_boot_console.log.section('Test Case 6b'):
+            # Test Case 6b, rejected by TEST_db certificate in dbx
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 dbx_db.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
+
+        with u_boot_console.log.section('Test Case 6c'):
+            # Test Case 6c, rejected by image's digest in dbx
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 db.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize db',
+                'fatload host 0:1 4000000 dbx_hello_signed.auth',
+                'setenv -e -nv -bs -rt -at -i 4000000,$filesize dbx'])
+            assert(not 'Failed to set EFI variable' in ''.join(output))
+            output = u_boot_console.run_command_list([
+                'efidebug boot next 1',
+                'efidebug test bootmgr'])
+            assert('\'HELLO\' failed' in ''.join(output))
+            assert('efi_start_image() returned: 26' in ''.join(output))
-- 
2.27.0

^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass
  2020-06-09  5:09 ` [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass AKASHI Takahiro
@ 2020-06-09  7:14   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-06-09  7:14 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> A signed image may have multiple signatures in
>   - each WIN_CERTIFICATE in authenticode, and/or
>   - each SignerInfo in pkcs7 SignedData (of WIN_CERTIFICATE)
>
> In the initial implementation of efi_image_authenticate(), the criteria
> of verification check for multiple signatures case is a bit ambiguous
> and it may cause inconsistent result.
>
> With this patch, we will make sure that verification check in
> efi_image_authenticate() should pass against all the signatures.
> The only exception would be
>   - the case where a digest algorithm used in signature is not supported by
>     U-Boot, or
>   - the case where parsing some portion of authenticode has failed
> In those cases, we don't know how the signature be handled and should
> just ignore them.
>
> Please note that, due to this change, efi_signature_verify_with_sigdb()'s
> function prototype will be modified, taking "dbx" as well as "db"
> instead of outputing a "certificate." If "dbx" is null, the behavior would
> be the exact same as before.
> The function's name will be changed to efi_signature_verify() once
> current efi_signature_verify() has gone due to further improvement
> in intermediate certificates support.


Something has been signed by a person you know and additionally by
somebody you do not know. Why would the extra signature make it less
trustworthy?

Is this really what the UEFI spec mandates?

Imagine you have an old device that needs to be updated. It only has
some old db entries.

As certificates expire the upstream maintainer has created a new signing
certificate and signs the firmware with an old and a new certificate.

Or imagine that new firmware is simply cross-signed by another party.

With your rule the firmware cannot be updated.

I think it is sufficient that at least one entry matches db and none
matches dbx.

Best regards

Heinrich

>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 01/17] efi_loader: change efi objects initialization order
  2020-06-09  5:09 ` [PATCH v2 01/17] efi_loader: change efi objects initialization order AKASHI Takahiro
@ 2020-07-03 10:29   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 10:29 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> The simplest solution to revert the commit b32ac16f9a32 ("test/py: fix
> test_efi_secboot/conftest.py") is to move efi_console_register()
> forward before efi_disk_register().
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot"
  2020-06-09  5:09 ` [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot" AKASHI Takahiro
@ 2020-07-03 10:30   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 10:30 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> This reverts commit 5827c2545849441dd60467565aac11964259972f.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT
  2020-06-09  5:09 ` [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT AKASHI Takahiro
@ 2020-07-03 10:30   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 10:30 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> Just for style consistency, replace all the uses of debug to
> EFI_PRINT in efi_signature.c
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 05/17] efi_loader: image_loader: replace debug to EFI_PRINT
  2020-06-09  5:09 ` [PATCH v2 05/17] efi_loader: image_loader: " AKASHI Takahiro
@ 2020-07-03 10:38   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 10:38 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> Just for style consistency, replace all the uses of debug() to
> EFI_PRINT() in efi_image_loader.c.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode
  2020-06-09  5:09 ` [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode AKASHI Takahiro
@ 2020-07-03 10:56   ` Heinrich Schuchardt
  2020-07-08  1:08     ` AKASHI Takahiro
  0 siblings, 1 reply; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 10:56 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> UEFI specification requires that we shall support three type of
> certificates of authenticode in PE image:
>   WIN_CERT_TYPE_EFI_GUID with the guid, EFI_CERT_TYPE_PCKS7_GUID
>   WIN_CERT_TYPE_PKCS_SIGNED_DATA
>   WIN_CERT_TYPE_EFI_PKCS1_15
>
> As EDK2 does, we will support the first two that are pkcs7 SignedData.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  lib/efi_loader/efi_image_loader.c | 56 ++++++++++++++++++++++++-------
>  1 file changed, 44 insertions(+), 12 deletions(-)
>
> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
> index 5b00fea2f113..38b2c24ab1d6 100644
> --- a/lib/efi_loader/efi_image_loader.c
> +++ b/lib/efi_loader/efi_image_loader.c
> @@ -484,7 +484,8 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
>  	struct efi_signature_store *db = NULL, *dbx = NULL;
>  	struct x509_certificate *cert = NULL;
>  	void *new_efi = NULL;
> -	size_t new_efi_size;
> +	u8 *auth, *wincerts_end;
> +	size_t new_efi_size, auth_size;
>  	bool ret = false;
>
>  	if (!efi_secure_boot_enabled())
> @@ -533,21 +534,52 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
>  	}
>
>  	/* 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)) {
> -			EFI_PRINT("%s: dwLength too small: %u < %zu\n",
> -				  __func__, wincert->dwLength,
> -				  sizeof(*wincert));
> -			goto err;
> +	for (wincert = wincerts, wincerts_end = (u8 *)wincerts + wincerts_len;
> +	     (u8 *)wincert < wincerts_end;

Shouldn't you compare the end of the current certificate to wincerts_end?

    ((u8 *)wincert + ALIGN(wincert->dwLength, 8))) <= wincerts_end

But you doing such a comparison anyway two lines below. So there is no
need to duplicate the test here.

> +	     wincert = (WIN_CERTIFICATE *)
> +			((u8 *)wincert + ALIGN(wincert->dwLength, 8))) {
> +		if ((u8 *)wincert + sizeof(*wincert) >= wincerts_end)
> +			break;

Why is this >= and not >?

Best regards

Heinrich

> +
> +		if (wincert->dwLength <= sizeof(*wincert)) {
> +			EFI_PRINT("dwLength too small: %u < %zu\n",
> +				  wincert->dwLength, sizeof(*wincert));
> +			continue;
> +		}
> +
> +		EFI_PRINT("WIN_CERTIFICATE_TYPE: 0x%x\n",
> +			  wincert->wCertificateType);
> +
> +		auth = (u8 *)wincert + sizeof(*wincert);
> +		auth_size = wincert->dwLength - sizeof(*wincert);
> +		if (wincert->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
> +			if (auth + sizeof(efi_guid_t) >= wincerts_end)
> +				break;
> +
> +			if (auth_size <= sizeof(efi_guid_t)) {
> +				EFI_PRINT("dwLength too small: %u < %zu\n",
> +					  wincert->dwLength, sizeof(*wincert));
> +				continue;
> +			}
> +			if (guidcmp(auth, &efi_guid_cert_type_pkcs7)) {
> +				EFI_PRINT("Certificate type not supported: %pUl\n",
> +					  auth);
> +				continue;
> +			}
> +
> +			auth += sizeof(efi_guid_t);
> +			auth_size -= sizeof(efi_guid_t);
> +		} else if (wincert->wCertificateType
> +				!= WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
> +			EFI_PRINT("Certificate type not supported\n");
> +			continue;
>  		}
> -		msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert),
> -					  wincert->dwLength - sizeof(*wincert));
> +
> +		msg = pkcs7_parse_message(auth, auth_size);
>  		if (IS_ERR(msg)) {
>  			EFI_PRINT("Parsing image's signature failed\n");
>  			msg = NULL;
> -			goto err;
> +			continue;
>  		}
>
>  		/* try black-list first */
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list
  2020-06-09  5:09 ` [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list AKASHI Takahiro
@ 2020-07-03 11:00   ` Heinrich Schuchardt
  2020-07-08  1:12     ` AKASHI Takahiro
  0 siblings, 1 reply; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 11:00 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> Since the size check against an entry in efi_search_siglist() is
> incorrect, this function will never find out a to-be-matched certificate
> and its associated revocation time in the signature list.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  lib/efi_loader/efi_signature.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> index a05c75472721..f22dc151971f 100644
> --- a/lib/efi_loader/efi_signature.c
> +++ b/lib/efi_loader/efi_signature.c
> @@ -434,10 +434,11 @@ static bool efi_search_siglist(struct x509_certificate *cert,
>  		 *	time64_t revocation_time;
>  		 * };
>  		 */
> -		if ((sig_data->size == SHA256_SUM_LEN) &&
> -		    !memcmp(sig_data->data, hash, SHA256_SUM_LEN)) {
> +		if ((sig_data->size >= SHA256_SUM_LEN + sizeof(time64_t)) &&
> +		    !memcmp(sig_data->data, msg, SHA256_SUM_LEN)) {
>  			memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
>  			       sizeof(*revoc_time));
> +			EFI_PRINT("revocation time: %llu\n", *revoc_time);

*revoc_time is of type __s64. So this must be %lld. Cf.

include/linux/time.h:156

Best regards

Heinrich

>  			found = true;
>  			goto out;
>  		}
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic
  2020-06-09  5:09 ` [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic AKASHI Takahiro
@ 2020-07-03 11:08   ` Heinrich Schuchardt
  2020-07-08  1:22     ` AKASHI Takahiro
  0 siblings, 1 reply; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 11:08 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> There are a couple of occurrences of hash calculations in which a new
> efi_hash_regions will be commonly used.

Please, describe the difference.

Do you want to calculate the hash over an interval of regions?

>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Please, provide a test for efi_hash_regions() in test/lib/.

> ---
>  lib/efi_loader/efi_signature.c | 44 +++++++++++++---------------------
>  1 file changed, 16 insertions(+), 28 deletions(-)
>
> diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> index f22dc151971f..03080bc0b11c 100644
> --- a/lib/efi_loader/efi_signature.c
> +++ b/lib/efi_loader/efi_signature.c
> @@ -30,6 +30,7 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>  /**
>   * efi_hash_regions - calculate a hash value
>   * @regs:	List of regions

The argument should be renamed and the description corrected:

@reg:	first region

Best regards

Heinrich

> + * @count:	Number of regions
>   * @hash:	Pointer to a pointer to buffer holding a hash value
>   * @size:	Size of buffer to be returned
>   *
> @@ -37,18 +38,20 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>   *
>   * Return:	true on success, false on error
>   */
> -static bool efi_hash_regions(struct efi_image_regions *regs, void **hash,
> -			     size_t *size)
> +static bool efi_hash_regions(struct image_region *regs, int count,
> +			     void **hash, size_t *size)
>  {
> -	*size = 0;
> -	*hash = calloc(1, SHA256_SUM_LEN);
>  	if (!*hash) {
> -		EFI_PRINT("Out of memory\n");
> -		return false;
> +		*hash = calloc(1, SHA256_SUM_LEN);
> +		if (!*hash) {
> +			EFI_PRINT("Out of memory\n");
> +			return false;
> +		}
>  	}
> -	*size = SHA256_SUM_LEN;
> +	if (size)
> +		*size = SHA256_SUM_LEN;
>
> -	hash_calculate("sha256", regs->reg, regs->num, *hash);
> +	hash_calculate("sha256", regs, count, *hash);
>  #ifdef DEBUG
>  	EFI_PRINT("hash calculated:\n");
>  	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
> @@ -73,26 +76,10 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
>  {
>  	struct image_region regtmp;
>
> -	*size = 0;
> -	*hash = calloc(1, SHA256_SUM_LEN);
> -	if (!*hash) {
> -		EFI_PRINT("Out of memory\n");
> -		free(msg);
> -		return false;
> -	}
> -	*size = SHA256_SUM_LEN;
> -
>  	regtmp.data = msg->data;
>  	regtmp.size = msg->data_len;
>
> -	hash_calculate("sha256", &regtmp, 1, *hash);
> -#ifdef DEBUG
> -	EFI_PRINT("hash calculated based on contentInfo:\n");
> -	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
> -		       *hash, SHA256_SUM_LEN, false);
> -#endif
> -
> -	return true;
> +	return efi_hash_regions(&regtmp, 1, hash, size);
>  }
>
>  /**
> @@ -170,9 +157,10 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
>  			       false);
>  #endif
>  		/* against contentInfo first */
> +		hash = NULL;
>  		if ((msg->data && efi_hash_msg_content(msg, &hash, &size)) ||
>  				/* for signed image */
> -		    efi_hash_regions(regs, &hash, &size)) {
> +		    efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
>  				/* for authenticated variable */
>  			if (ps_info->msgdigest_len != size ||
>  			    memcmp(hash, ps_info->msgdigest, size)) {
> @@ -240,7 +228,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
>  		  regs, signed_info, siglist, valid_cert);
>
>  	if (!signed_info) {
> -		void *hash;
> +		void *hash = NULL;
>  		size_t size;
>
>  		EFI_PRINT("%s: unsigned image\n", __func__);
> @@ -254,7 +242,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
>  			goto out;
>  		}
>
> -		if (!efi_hash_regions(regs, &hash, &size)) {
> +		if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
>  			EFI_PRINT("Digesting unsigned image failed\n");
>  			goto out;
>  		}
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search"
  2020-06-09  5:09 ` [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search" AKASHI Takahiro
@ 2020-07-03 15:52   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 15:52 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> Currently, we don't use any regular expression in matching outputs from
> U-Boot. Since its use is just redundant, we can remove all.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar
  2020-06-09  5:09 ` [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar AKASHI Takahiro
@ 2020-07-03 16:08   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 16:08 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> In the test case (1g) of test_authvar, "db" is mistakenly used,
> and it ends up being the exact same as (1f).
> So correct it as "dbx" test case.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases
  2020-06-09  5:09 ` [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases AKASHI Takahiro
@ 2020-07-03 16:14   ` Heinrich Schuchardt
  0 siblings, 0 replies; 33+ messages in thread
From: Heinrich Schuchardt @ 2020-07-03 16:14 UTC (permalink / raw)
  To: u-boot

On 09.06.20 07:09, AKASHI Takahiro wrote:
> Split the existing test case-1 into case1 and a new case-2:
> case-1 for non-SecureBoot mode; case-2 for SecureBoot mode.
>
> In addition, one corner case is added to case-2; a image is signed
> but a corresponding certificate is not yet installed in "db."
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Reviewed-by: Heinrich Schuchardt <xypron.glpk@gmx.de>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode
  2020-07-03 10:56   ` Heinrich Schuchardt
@ 2020-07-08  1:08     ` AKASHI Takahiro
  0 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-07-08  1:08 UTC (permalink / raw)
  To: u-boot

Heinrich,

On Fri, Jul 03, 2020 at 12:56:55PM +0200, Heinrich Schuchardt wrote:
> On 09.06.20 07:09, AKASHI Takahiro wrote:
> > UEFI specification requires that we shall support three type of
> > certificates of authenticode in PE image:
> >   WIN_CERT_TYPE_EFI_GUID with the guid, EFI_CERT_TYPE_PCKS7_GUID
> >   WIN_CERT_TYPE_PKCS_SIGNED_DATA
> >   WIN_CERT_TYPE_EFI_PKCS1_15
> >
> > As EDK2 does, we will support the first two that are pkcs7 SignedData.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  lib/efi_loader/efi_image_loader.c | 56 ++++++++++++++++++++++++-------
> >  1 file changed, 44 insertions(+), 12 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c
> > index 5b00fea2f113..38b2c24ab1d6 100644
> > --- a/lib/efi_loader/efi_image_loader.c
> > +++ b/lib/efi_loader/efi_image_loader.c
> > @@ -484,7 +484,8 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
> >  	struct efi_signature_store *db = NULL, *dbx = NULL;
> >  	struct x509_certificate *cert = NULL;
> >  	void *new_efi = NULL;
> > -	size_t new_efi_size;
> > +	u8 *auth, *wincerts_end;
> > +	size_t new_efi_size, auth_size;
> >  	bool ret = false;
> >
> >  	if (!efi_secure_boot_enabled())
> > @@ -533,21 +534,52 @@ static bool efi_image_authenticate(void *efi, size_t efi_size)
> >  	}
> >
> >  	/* 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)) {
> > -			EFI_PRINT("%s: dwLength too small: %u < %zu\n",
> > -				  __func__, wincert->dwLength,
> > -				  sizeof(*wincert));
> > -			goto err;
> > +	for (wincert = wincerts, wincerts_end = (u8 *)wincerts + wincerts_len;
> > +	     (u8 *)wincert < wincerts_end;
> 
> Shouldn't you compare the end of the current certificate to wincerts_end?

No.

>     ((u8 *)wincert + ALIGN(wincert->dwLength, 8))) <= wincerts_end
> 
> But you doing such a comparison anyway two lines below. So there is no
> need to duplicate the test here.
> 
> > +	     wincert = (WIN_CERTIFICATE *)
> > +			((u8 *)wincert + ALIGN(wincert->dwLength, 8))) {
> > +		if ((u8 *)wincert + sizeof(*wincert) >= wincerts_end)
> > +			break;

Is this the line that you mentioned as "two lines below"?
If so, the check is not the exact same.

As an image is provided by a *user*, we have to be as careful
as possible in handling data in an image.
In this case, the value of size in a header may not always be
correct (or at least, can be corrupted). So we will make sure
that we have enough data for accessing a header at the beginning.

> Why is this >= and not >?

Because "<start> + <size>" would be exclusive.

So I will keep my code unchanged.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> > +
> > +		if (wincert->dwLength <= sizeof(*wincert)) {
> > +			EFI_PRINT("dwLength too small: %u < %zu\n",
> > +				  wincert->dwLength, sizeof(*wincert));
> > +			continue;
> > +		}
> > +
> > +		EFI_PRINT("WIN_CERTIFICATE_TYPE: 0x%x\n",
> > +			  wincert->wCertificateType);
> > +
> > +		auth = (u8 *)wincert + sizeof(*wincert);
> > +		auth_size = wincert->dwLength - sizeof(*wincert);
> > +		if (wincert->wCertificateType == WIN_CERT_TYPE_EFI_GUID) {
> > +			if (auth + sizeof(efi_guid_t) >= wincerts_end)
> > +				break;
> > +
> > +			if (auth_size <= sizeof(efi_guid_t)) {
> > +				EFI_PRINT("dwLength too small: %u < %zu\n",
> > +					  wincert->dwLength, sizeof(*wincert));
> > +				continue;
> > +			}
> > +			if (guidcmp(auth, &efi_guid_cert_type_pkcs7)) {
> > +				EFI_PRINT("Certificate type not supported: %pUl\n",
> > +					  auth);
> > +				continue;
> > +			}
> > +
> > +			auth += sizeof(efi_guid_t);
> > +			auth_size -= sizeof(efi_guid_t);
> > +		} else if (wincert->wCertificateType
> > +				!= WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
> > +			EFI_PRINT("Certificate type not supported\n");
> > +			continue;
> >  		}
> > -		msg = pkcs7_parse_message((void *)wincert + sizeof(*wincert),
> > -					  wincert->dwLength - sizeof(*wincert));
> > +
> > +		msg = pkcs7_parse_message(auth, auth_size);
> >  		if (IS_ERR(msg)) {
> >  			EFI_PRINT("Parsing image's signature failed\n");
> >  			msg = NULL;
> > -			goto err;
> > +			continue;
> >  		}
> >
> >  		/* try black-list first */
> >
> 

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list
  2020-07-03 11:00   ` Heinrich Schuchardt
@ 2020-07-08  1:12     ` AKASHI Takahiro
  2020-07-08  1:30       ` AKASHI Takahiro
  0 siblings, 1 reply; 33+ messages in thread
From: AKASHI Takahiro @ 2020-07-08  1:12 UTC (permalink / raw)
  To: u-boot

On Fri, Jul 03, 2020 at 01:00:21PM +0200, Heinrich Schuchardt wrote:
> On 09.06.20 07:09, AKASHI Takahiro wrote:
> > Since the size check against an entry in efi_search_siglist() is
> > incorrect, this function will never find out a to-be-matched certificate
> > and its associated revocation time in the signature list.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  lib/efi_loader/efi_signature.c | 5 +++--
> >  1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> > index a05c75472721..f22dc151971f 100644
> > --- a/lib/efi_loader/efi_signature.c
> > +++ b/lib/efi_loader/efi_signature.c
> > @@ -434,10 +434,11 @@ static bool efi_search_siglist(struct x509_certificate *cert,
> >  		 *	time64_t revocation_time;
> >  		 * };
> >  		 */
> > -		if ((sig_data->size == SHA256_SUM_LEN) &&
> > -		    !memcmp(sig_data->data, hash, SHA256_SUM_LEN)) {
> > +		if ((sig_data->size >= SHA256_SUM_LEN + sizeof(time64_t)) &&
> > +		    !memcmp(sig_data->data, msg, SHA256_SUM_LEN)) {
> >  			memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
> >  			       sizeof(*revoc_time));
> > +			EFI_PRINT("revocation time: %llu\n", *revoc_time);
> 
> *revoc_time is of type __s64. So this must be %lld. Cf.
> 
> include/linux/time.h:156

I know that because I added the definition.
Interestingly, linux added another type, timeu64_t, later on
to avoid an overflow in some calculation.

While I don't think the current format is harmful, I will change it.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> >  			found = true;
> >  			goto out;
> >  		}
> >
> 

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic
  2020-07-03 11:08   ` Heinrich Schuchardt
@ 2020-07-08  1:22     ` AKASHI Takahiro
  0 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-07-08  1:22 UTC (permalink / raw)
  To: u-boot

Heinrich,

On Fri, Jul 03, 2020 at 01:08:55PM +0200, Heinrich Schuchardt wrote:
> On 09.06.20 07:09, AKASHI Takahiro wrote:
> > There are a couple of occurrences of hash calculations in which a new
> > efi_hash_regions will be commonly used.
> 
> Please, describe the difference.

the difference of what?

> Do you want to calculate the hash over an interval of regions?

I don't get your point.
What do you mean by "over an interval"?

> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> 
> Please, provide a test for efi_hash_regions() in test/lib/.
> 
> > ---
> >  lib/efi_loader/efi_signature.c | 44 +++++++++++++---------------------
> >  1 file changed, 16 insertions(+), 28 deletions(-)
> >
> > diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> > index f22dc151971f..03080bc0b11c 100644
> > --- a/lib/efi_loader/efi_signature.c
> > +++ b/lib/efi_loader/efi_signature.c
> > @@ -30,6 +30,7 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> >  /**
> >   * efi_hash_regions - calculate a hash value
> >   * @regs:	List of regions
> 
> The argument should be renamed and the description corrected:
> 
> @reg:	first region

No. You don't understand the code.
Here, I refactored the code and simply extracted a common code as
efi_hash_regions.
The first argument is an array of "struct image_region".
(To avoid any confusion, I will change the description to "Array of".)

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > + * @count:	Number of regions
> >   * @hash:	Pointer to a pointer to buffer holding a hash value
> >   * @size:	Size of buffer to be returned
> >   *
> > @@ -37,18 +38,20 @@ const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> >   *
> >   * Return:	true on success, false on error
> >   */
> > -static bool efi_hash_regions(struct efi_image_regions *regs, void **hash,
> > -			     size_t *size)
> > +static bool efi_hash_regions(struct image_region *regs, int count,
> > +			     void **hash, size_t *size)
> >  {
> > -	*size = 0;
> > -	*hash = calloc(1, SHA256_SUM_LEN);
> >  	if (!*hash) {
> > -		EFI_PRINT("Out of memory\n");
> > -		return false;
> > +		*hash = calloc(1, SHA256_SUM_LEN);
> > +		if (!*hash) {
> > +			EFI_PRINT("Out of memory\n");
> > +			return false;
> > +		}
> >  	}
> > -	*size = SHA256_SUM_LEN;
> > +	if (size)
> > +		*size = SHA256_SUM_LEN;
> >
> > -	hash_calculate("sha256", regs->reg, regs->num, *hash);
> > +	hash_calculate("sha256", regs, count, *hash);
> >  #ifdef DEBUG
> >  	EFI_PRINT("hash calculated:\n");
> >  	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
> > @@ -73,26 +76,10 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash,
> >  {
> >  	struct image_region regtmp;
> >
> > -	*size = 0;
> > -	*hash = calloc(1, SHA256_SUM_LEN);
> > -	if (!*hash) {
> > -		EFI_PRINT("Out of memory\n");
> > -		free(msg);
> > -		return false;
> > -	}
> > -	*size = SHA256_SUM_LEN;
> > -
> >  	regtmp.data = msg->data;
> >  	regtmp.size = msg->data_len;
> >
> > -	hash_calculate("sha256", &regtmp, 1, *hash);
> > -#ifdef DEBUG
> > -	EFI_PRINT("hash calculated based on contentInfo:\n");
> > -	print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
> > -		       *hash, SHA256_SUM_LEN, false);
> > -#endif
> > -
> > -	return true;
> > +	return efi_hash_regions(&regtmp, 1, hash, size);
> >  }
> >
> >  /**
> > @@ -170,9 +157,10 @@ static bool efi_signature_verify(struct efi_image_regions *regs,
> >  			       false);
> >  #endif
> >  		/* against contentInfo first */
> > +		hash = NULL;
> >  		if ((msg->data && efi_hash_msg_content(msg, &hash, &size)) ||
> >  				/* for signed image */
> > -		    efi_hash_regions(regs, &hash, &size)) {
> > +		    efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
> >  				/* for authenticated variable */
> >  			if (ps_info->msgdigest_len != size ||
> >  			    memcmp(hash, ps_info->msgdigest, size)) {
> > @@ -240,7 +228,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
> >  		  regs, signed_info, siglist, valid_cert);
> >
> >  	if (!signed_info) {
> > -		void *hash;
> > +		void *hash = NULL;
> >  		size_t size;
> >
> >  		EFI_PRINT("%s: unsigned image\n", __func__);
> > @@ -254,7 +242,7 @@ bool efi_signature_verify_with_list(struct efi_image_regions *regs,
> >  			goto out;
> >  		}
> >
> > -		if (!efi_hash_regions(regs, &hash, &size)) {
> > +		if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
> >  			EFI_PRINT("Digesting unsigned image failed\n");
> >  			goto out;
> >  		}
> >
> 

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list
  2020-07-08  1:12     ` AKASHI Takahiro
@ 2020-07-08  1:30       ` AKASHI Takahiro
  0 siblings, 0 replies; 33+ messages in thread
From: AKASHI Takahiro @ 2020-07-08  1:30 UTC (permalink / raw)
  To: u-boot

On Wed, Jul 08, 2020 at 10:12:38AM +0900, AKASHI Takahiro wrote:
> On Fri, Jul 03, 2020 at 01:00:21PM +0200, Heinrich Schuchardt wrote:
> > On 09.06.20 07:09, AKASHI Takahiro wrote:
> > > Since the size check against an entry in efi_search_siglist() is
> > > incorrect, this function will never find out a to-be-matched certificate
> > > and its associated revocation time in the signature list.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > ---
> > >  lib/efi_loader/efi_signature.c | 5 +++--
> > >  1 file changed, 3 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c
> > > index a05c75472721..f22dc151971f 100644
> > > --- a/lib/efi_loader/efi_signature.c
> > > +++ b/lib/efi_loader/efi_signature.c
> > > @@ -434,10 +434,11 @@ static bool efi_search_siglist(struct x509_certificate *cert,
> > >  		 *	time64_t revocation_time;
> > >  		 * };
> > >  		 */
> > > -		if ((sig_data->size == SHA256_SUM_LEN) &&
> > > -		    !memcmp(sig_data->data, hash, SHA256_SUM_LEN)) {
> > > +		if ((sig_data->size >= SHA256_SUM_LEN + sizeof(time64_t)) &&
> > > +		    !memcmp(sig_data->data, msg, SHA256_SUM_LEN)) {
> > >  			memcpy(revoc_time, sig_data->data + SHA256_SUM_LEN,
> > >  			       sizeof(*revoc_time));
> > > +			EFI_PRINT("revocation time: %llu\n", *revoc_time);
> > 
> > *revoc_time is of type __s64. So this must be %lld. Cf.
> > 
> > include/linux/time.h:156
> 
> I know that because I added the definition.
> Interestingly, linux added another type, timeu64_t, later on
> to avoid an overflow in some calculation.
> 
> While I don't think the current format is harmful, I will change it.

Oops, I have already changed the format to "0x%llx" locally.
I will stick to this.


> -Takahiro Akashi
> 
> 
> > Best regards
> > 
> > Heinrich
> > 
> > >  			found = true;
> > >  			goto out;
> > >  		}
> > >
> > 

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2020-07-08  1:30 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-09  5:09 [PATCH v2 00/17] efi_loader: rework/improve UEFI secure boot code AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 01/17] efi_loader: change efi objects initialization order AKASHI Takahiro
2020-07-03 10:29   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 02/17] Revert "test: stabilize test_efi_secboot" AKASHI Takahiro
2020-07-03 10:30   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 03/17] efi_loader: signature: replace debug to EFI_PRINT AKASHI Takahiro
2020-07-03 10:30   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 04/17] efi_loader: variable: " AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 05/17] efi_loader: image_loader: " AKASHI Takahiro
2020-07-03 10:38   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 06/17] efi_loader: image_loader: add a check against certificate type of authenticode AKASHI Takahiro
2020-07-03 10:56   ` Heinrich Schuchardt
2020-07-08  1:08     ` AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 07/17] efi_loader: image_loader: retrieve authenticode only if it exists AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 08/17] efi_loader: signature: fix a size check against revocation list AKASHI Takahiro
2020-07-03 11:00   ` Heinrich Schuchardt
2020-07-08  1:12     ` AKASHI Takahiro
2020-07-08  1:30       ` AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 09/17] efi_loader: signature: make efi_hash_regions more generic AKASHI Takahiro
2020-07-03 11:08   ` Heinrich Schuchardt
2020-07-08  1:22     ` AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 10/17] efi_loader: image_loader: verification for all signatures should pass AKASHI Takahiro
2020-06-09  7:14   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 11/17] efi_loader: image_loader: add digest-based verification for signed image AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 12/17] test/py: efi_secboot: remove all "re.search" AKASHI Takahiro
2020-07-03 15:52   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 13/17] test/py: efi_secboot: fix test case 1g of test_authvar AKASHI Takahiro
2020-07-03 16:08   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 14/17] test/py: efi_secboot: split "signed image" test case-1 into two cases AKASHI Takahiro
2020-07-03 16:14   ` Heinrich Schuchardt
2020-06-09  5:09 ` [PATCH v2 15/17] test/py: efi_secboot: add a test against certificate revocation AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 16/17] test/py: efi_secboot: add a test for multiple signatures AKASHI Takahiro
2020-06-09  5:09 ` [PATCH v2 17/17] test/py: efi_secboot: add a test for verifying with digest of signed image AKASHI Takahiro

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.