From e4c1c48eebd072b2fa6f27fd9b7baa731350ebe8 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Mon, 29 Jun 2020 11:49:58 +0200 Subject: [PATCH 01/19] efi_loader: fix incorrect use of EFI_EXIT() efi_get_variable_common() does not use EFI_ENTRY(). So we should not use EFI_EXIT() either. Fixes: 767f6eeb01d3 ("efi_loader: variable: support variable authentication") Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 6271dbcf41..c262cb5972 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -606,7 +606,7 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, u32 attr; if (!variable_name || !vendor || !data_size) - return EFI_EXIT(EFI_INVALID_PARAMETER); + return EFI_INVALID_PARAMETER; ret = efi_to_native(&native_name, variable_name, vendor); if (ret) From 039d4f50e4894fc5176d4913e68fb8d6a38571cf Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 30 Jun 2020 14:12:43 +0200 Subject: [PATCH 02/19] efi_loader: incorrect check against FDT_ADDR_T_NONE With commit 0d7c2913fdf7 ("cmd: bootefi: Honor the address & size cells properties correctly") addr was replaced by fdt_addr. But not in the check against FDT_ADDR_T_NONE. Fixes: 0d7c2913fdf7 ("cmd: bootefi: Honor the address & size cells properties correctly") Signed-off-by: Heinrich Schuchardt --- cmd/bootefi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 8269153973..57552f99fc 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -200,7 +200,7 @@ static void efi_carve_out_dt_rsv(void *fdt) * The /reserved-memory node may have children with * a size instead of a reg property. */ - if (addr != FDT_ADDR_T_NONE && + if (fdt_addr != FDT_ADDR_T_NONE && fdtdec_get_is_enabled(fdt, subnode)) efi_reserve_memory(fdt_addr, fdt_size); subnode = fdt_next_subnode(fdt, subnode); From b7cae5739741fad1327e64c18a0b30919bc77a0e Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sat, 27 Jun 2020 18:03:17 -0700 Subject: [PATCH 03/19] test/py: test_efi_fit: Update #size-cells to 1 test_efi_fit tests fail on RISC-V currently. This is due to the RISC-V arch_fixup_fdt() checks the #size-cells of the root node in order to correctly fix up the reserved memory node. Per the DT binding, the /reserved-memory node requires both <#address-cells> and <#size-cells> and they should use the same values as the root node. For the root node, it's not very useful if <#size-cells> is zero. Update #size-cells to 1 so tests can pass. Signed-off-by: Bin Meng --- test/py/tests/test_efi_fit.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py index beaf4a3c51..06fb151c13 100644 --- a/test/py/tests/test_efi_fit.py +++ b/test/py/tests/test_efi_fit.py @@ -106,14 +106,14 @@ FDT_DATA = ''' / { #address-cells = <1>; - #size-cells = <0>; + #size-cells = <1>; model = "%(sys-arch)s %(fdt_type)s EFI FIT Boot Test"; compatible = "%(sys-arch)s"; reset@0 { compatible = "%(sys-arch)s,reset"; - reg = <0>; + reg = <0 4>; }; }; ''' From f7a963c6af5a077631a4ff43fcd10533969b14b2 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:31 +0900 Subject: [PATCH 04/19] efi_loader: change efi objects initialization order 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 Reviewed by: Heinrich Schuchardt --- 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 dd0c53fc23..671f6da12b 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) From dc2b47344729d62af15a34e254cf64f4c6916cda Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:32 +0900 Subject: [PATCH 05/19] Revert "test: stabilize test_efi_secboot" This reverts commit 5827c2545849441dd60467565aac11964259972f. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- 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 9912694a3e..55dcaa95f1 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 fc722ab506..584282b338 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 a4af845c51..22d849afb8 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', From 3e9019d4816945f7448e0182f9e5466385503345 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:33 +0900 Subject: [PATCH 06/19] efi_loader: signature: replace debug to EFI_PRINT Just for style consistency, replace all the uses of debug to EFI_PRINT in efi_signature.c Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- 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 6685253856..3a634d7b57 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -42,14 +42,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 @@ -75,7 +75,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; } @@ -86,7 +86,7 @@ static bool efi_hash_msg_content(struct pkcs7_message *msg, void **hash, hash_calculate("sha256", ®tmp, 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 @@ -119,8 +119,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; @@ -138,7 +138,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); @@ -147,21 +148,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); @@ -173,14 +175,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; } @@ -195,7 +197,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)) @@ -203,7 +205,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; } @@ -233,26 +235,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; } @@ -260,7 +262,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 @@ -275,10 +277,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; } @@ -289,7 +291,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; } @@ -306,7 +308,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; } @@ -331,7 +333,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; @@ -341,7 +343,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)) { @@ -353,10 +355,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, @@ -368,7 +370,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; } @@ -400,21 +402,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; } @@ -465,7 +467,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; @@ -480,7 +482,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; } @@ -501,7 +503,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; @@ -514,7 +516,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; } @@ -539,7 +541,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; } @@ -556,8 +558,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; } @@ -649,14 +651,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)); @@ -671,14 +673,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; } @@ -689,7 +691,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); @@ -735,7 +737,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; } @@ -743,23 +745,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; } @@ -768,19 +770,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; } From ce3c3865b0c321116e59437abec96da3745ba619 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:34 +0900 Subject: [PATCH 07/19] efi_loader: variable: replace debug to EFI_PRINT Just for style consistency, replace all the uses of debug() to EFI_PRINT in efi_variable.c. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- 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 c262cb5972..74a9c65402 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; } From 1b6c08548c85ec8bb1d57f12fb219cc2e31547c8 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:35 +0900 Subject: [PATCH 08/19] efi_loader: image_loader: replace debug to EFI_PRINT Just for style consistency, replace all the uses of debug() to EFI_PRINT() in efi_image_loader.c. Signed-off-by: AKASHI Takahiro Reviewed-by: Heinrich Schuchardt --- 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 230d41ae5e..06a2ebdb90 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -325,8 +325,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; } @@ -336,7 +336,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; } @@ -355,13 +355,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; } @@ -369,8 +369,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: %zu\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); } @@ -378,18 +378,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; @@ -423,19 +424,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; } @@ -443,7 +444,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); @@ -504,7 +505,7 @@ static bool efi_image_authenticate(void *efi, size_t efi_size) if (!efi_image_parse(efi, efi_size, ®s, &wincerts, &wincerts_len)) { - debug("Parsing PE executable image failed\n"); + EFI_PRINT("Parsing PE executable image failed\n"); goto err; } @@ -520,13 +521,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; } @@ -535,26 +536,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; @@ -562,14 +564,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; From bed118fb103c4917fd45a652a9026d5e9b62a069 Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:42 +0900 Subject: [PATCH 09/19] test/py: efi_secboot: remove all "re.search" 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 Reviewed-by: Heinrich Schuchardt --- .../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 55dcaa95f1..766ed92836 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 584282b338..19d78b1b64 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 22d849afb8..c42c5ddc47 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)) From 4edd9ccd94a93e153ab95a75a819f2c7436e5acb Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Tue, 9 Jun 2020 14:09:43 +0900 Subject: [PATCH 10/19] test/py: efi_secboot: fix test case 1g of test_authvar 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 Reviewed-by: Heinrich Schuchardt --- 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 766ed92836..148aa3123e 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') From bc246c69aecea107f7286da928ac3c2494109979 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 2 Jul 2020 08:25:46 +0200 Subject: [PATCH 11/19] test: correct time stamps for UEFI authentication A time authenticated variable cannot be overwritten with another value with the same time stamp. So we must ensure the correct sequence of time stamps when generating out test data. Using parameter -t for sign-efi-sig-list gives reproducible results and avoids sleep statements. Signed-off-by: Heinrich Schuchardt --- test/py/tests/test_efi_secboot/conftest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py index 5d99b8b718..ac5a780fdb 100644 --- a/test/py/tests/test_efi_secboot/conftest.py +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -76,37 +76,37 @@ def efi_boot_env(request, u_boot_config): ## PK check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_PK/ -keyout PK.key -out PK.crt -nodes -days 365' % mnt_point, shell=True) - check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK.esl PK.auth' + check_call('cd %s; %scert-to-efi-sig-list -g %s PK.crt PK.esl; %ssign-efi-sig-list -t "2020-04-01" -c PK.crt -k PK.key PK PK.esl PK.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) ## PK_null for deletion - check_call('cd %s; sleep 2; touch PK_null.esl; %ssign-efi-sig-list -c PK.crt -k PK.key PK PK_null.esl PK_null.auth' + check_call('cd %s; touch PK_null.esl; %ssign-efi-sig-list -t "2020-04-02" -c PK.crt -k PK.key PK PK_null.esl PK_null.auth' % (mnt_point, EFITOOLS_PATH), shell=True) ## KEK check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_KEK/ -keyout KEK.key -out KEK.crt -nodes -days 365' % mnt_point, shell=True) - check_call('cd %s; %scert-to-efi-sig-list -g %s KEK.crt KEK.esl; %ssign-efi-sig-list -c PK.crt -k PK.key KEK KEK.esl KEK.auth' + check_call('cd %s; %scert-to-efi-sig-list -g %s KEK.crt KEK.esl; %ssign-efi-sig-list -t "2020-04-03" -c PK.crt -k PK.key KEK KEK.esl KEK.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) ## db check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db/ -keyout db.key -out db.crt -nodes -days 365' % mnt_point, shell=True) - check_call('cd %s; %scert-to-efi-sig-list -g %s db.crt db.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db.esl db.auth' + check_call('cd %s; %scert-to-efi-sig-list -g %s db.crt db.esl; %ssign-efi-sig-list -t "2020-04-04" -c KEK.crt -k KEK.key db db.esl db.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) ## db1 check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_db1/ -keyout db1.key -out db1.crt -nodes -days 365' % mnt_point, shell=True) - check_call('cd %s; %scert-to-efi-sig-list -g %s db1.crt db1.esl; %ssign-efi-sig-list -c KEK.crt -k KEK.key db db1.esl db1.auth' + check_call('cd %s; %scert-to-efi-sig-list -g %s db1.crt db1.esl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key db db1.esl db1.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) ## db1-update - check_call('cd %s; %ssign-efi-sig-list -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth' + check_call('cd %s; %ssign-efi-sig-list -t "2020-04-06" -a -c KEK.crt -k KEK.key db db1.esl db1-update.auth' % (mnt_point, EFITOOLS_PATH), shell=True) ## dbx 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' + check_call('cd %s; %scert-to-efi-sig-list -g %s dbx.crt dbx.esl; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx dbx.esl dbx.auth' % (mnt_point, EFITOOLS_PATH, GUID, EFITOOLS_PATH), shell=True) @@ -117,7 +117,7 @@ def efi_boot_env(request, u_boot_config): check_call('cd %s; sbsign --key db.key --cert db.crt helloworld.efi' % 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' + check_call('cd %s; %shash-to-efi-sig-list helloworld.efi db_hello.hash; %ssign-efi-sig-list -t "2020-04-07" -c KEK.crt -k KEK.key db db_hello.hash db_hello.auth' % (mnt_point, EFITOOLS_PATH, EFITOOLS_PATH), shell=True) From 28164c925ef02082f6320542acee744f8712ae9c Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 1 Jul 2020 20:01:52 +0200 Subject: [PATCH 12/19] efi_loader: fix efi_image_region_add() Use start and end address consistently as half-open interval. Simplify the code. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_signature.c | 35 ++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 3a634d7b57..e05c471c61 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -521,15 +521,19 @@ out: } /** - * efi_image_region_add - add an entry of region + * efi_image_region_add() - add an entry of region * @regs: Pointer to array of regions - * @start: Start address of region - * @end: End address of region + * @start: Start address of region (included) + * @end: End address of region (excluded) * @nocheck: flag against overlapped regions * - * Take one entry of region [@start, @end] and append it to the list - * pointed to by @regs. If @nocheck is false, overlapping among entries - * will be checked first. + * Take one entry of region [@start, @end[ and insert it into the list. + * + * * If @nocheck is false, the list will be sorted ascending by address. + * Overlapping entries will not be allowed. + * + * * If @nocheck is true, the list will be sorted ascending by sequence + * of adding the entries. Overlapping is allowed. * * Return: status code */ @@ -553,22 +557,21 @@ efi_status_t efi_image_region_add(struct efi_image_regions *regs, if (nocheck) continue; - if (start > reg->data + reg->size) + /* new data after registered region */ + if (start >= reg->data + reg->size) continue; - if ((start >= reg->data && start < reg->data + reg->size) || - (end > reg->data && end < reg->data + reg->size)) { - EFI_PRINT("%s: new region already part of another\n", - __func__); - return EFI_INVALID_PARAMETER; - } - - if (start < reg->data && end < reg->data + reg->size) { + /* new data preceding registered region */ + if (end <= reg->data) { for (j = regs->num - 1; j >= i; j--) - memcpy(®s->reg[j], ®s->reg[j + 1], + memcpy(®s->reg[j + 1], ®s->reg[j], sizeof(*reg)); break; } + + /* new data overlapping registered region */ + EFI_PRINT("%s: new region already part of another\n", __func__); + return EFI_INVALID_PARAMETER; } reg = ®s->reg[i]; From ae54b946ca03d92f5d9efdf575a0e7940fb5482f Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 1 Jul 2020 20:01:53 +0200 Subject: [PATCH 13/19] test: provide tests for efi_image_region_add() Provide unit tests for efi_image_region_add(). Signed-off-by: Heinrich Schuchardt --- MAINTAINERS | 1 + test/lib/Makefile | 1 + test/lib/efi_image_region.c | 163 ++++++++++++++++++++++++++++++++++++ 3 files changed, 165 insertions(+) create mode 100644 test/lib/efi_image_region.c diff --git a/MAINTAINERS b/MAINTAINERS index db8cecd5e0..b515bf3d93 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -633,6 +633,7 @@ F: include/pe.h F: include/asm-generic/pe.h F: lib/charset.c F: lib/efi*/ +F: test/lib/efi_* F: test/py/tests/test_efi* F: test/py/tests/test_efi*/ F: test/unicode_ut.c diff --git a/test/lib/Makefile b/test/lib/Makefile index ce9ae4a9be..6ccc2c41bc 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -3,6 +3,7 @@ # (C) Copyright 2018 # Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc obj-y += cmd_ut_lib.o +obj-$(CONFIG_EFI_SECURE_BOOT) += efi_image_region.o obj-y += hexdump.o obj-y += lmb.o obj-y += string.o diff --git a/test/lib/efi_image_region.c b/test/lib/efi_image_region.c new file mode 100644 index 0000000000..0b888f8433 --- /dev/null +++ b/test/lib/efi_image_region.c @@ -0,0 +1,163 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2020, Heinrich Schuchardt + */ + +#include +#include +#include +#include +#include + +#define UT_REG_CAPACITY 6 + +static int lib_test_efi_image_region_add(struct unit_test_state *uts) +{ + struct efi_image_regions *regs; + + regs = calloc(sizeof(*regs) + + sizeof(struct image_region) * UT_REG_CAPACITY, 1); + ut_assert(regs); + + regs->max = UT_REG_CAPACITY; + + ut_asserteq(0, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x4000, + (void *)0x3000, 1)); + ut_asserteq(0, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x3100, + (void *)0x4000, 1)); + ut_asserteq(1, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x2000, + (void *)0x3100, 1)); + ut_asserteq(2, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x1000, + (void *)0x1f00, 1)); + ut_asserteq(3, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x4000, + (void *)0x4e00, 1)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x1f00, + (void *)0x2001, 1)); + ut_asserteq(5, regs->num); + + ut_asserteq_ptr((void *)0x3100, regs->reg[0].data); + ut_asserteq(0x0f00, regs->reg[0].size); + + ut_asserteq_ptr((void *)0x2000, regs->reg[1].data); + ut_asserteq(0x1100, regs->reg[1].size); + + ut_asserteq_ptr((void *)0x1000, regs->reg[2].data); + ut_asserteq(0x0f00, regs->reg[2].size); + + ut_asserteq_ptr((void *)0x4000, regs->reg[3].data); + ut_asserteq(0x0e00, regs->reg[3].size); + + ut_asserteq_ptr((void *)0x1f00, regs->reg[4].data); + ut_asserteq(0x0101, regs->reg[4].size); + + free(regs); + + return 0; +} + +LIB_TEST(lib_test_efi_image_region_add, 0); + +static int lib_test_efi_image_region_sort(struct unit_test_state *uts) +{ + struct efi_image_regions *regs; + + regs = calloc(sizeof(*regs) + + sizeof(struct image_region) * UT_REG_CAPACITY, 1); + ut_assert(regs); + + regs->max = UT_REG_CAPACITY; + + ut_asserteq(0, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x4000, + (void *)0x3000, 0)); + ut_asserteq(0, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x3100, + (void *)0x4000, 0)); + ut_asserteq(1, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x2000, + (void *)0x3100, 0)); + ut_asserteq(2, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x1000, + (void *)0x1f00, 0)); + ut_asserteq(3, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x4000, + (void *)0x4e00, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x1f00, + (void *)0x2001, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x10ff, + (void *)0x11ff, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x0000, + (void *)0x6000, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x3100, + (void *)0x0e00, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x3200, + (void *)0x0e00, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_INVALID_PARAMETER, + efi_image_region_add(regs, (void *)0x3200, + (void *)0x0d00, 0)); + ut_asserteq(4, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x1f00, + (void *)0x2000, 0)); + ut_asserteq(5, regs->num); + ut_asserteq_64(EFI_SUCCESS, + efi_image_region_add(regs, (void *)0x4000, + (void *)0x4000, 0)); + ut_asserteq(6, regs->num); + ut_asserteq_64(EFI_OUT_OF_RESOURCES, + efi_image_region_add(regs, (void *)0x6000, + (void *)0x0100, 0)); + ut_asserteq(6, regs->num); + + ut_asserteq_ptr((void *)0x1000, regs->reg[0].data); + ut_asserteq(0x0f00, regs->reg[0].size); + + ut_asserteq_ptr((void *)0x1f00, regs->reg[1].data); + ut_asserteq(0x0100, regs->reg[1].size); + + ut_asserteq_ptr((void *)0x2000, regs->reg[2].data); + ut_asserteq(0x1100, regs->reg[2].size); + + ut_asserteq_ptr((void *)0x3100, regs->reg[3].data); + ut_asserteq(0x0f00, regs->reg[3].size); + + ut_asserteq_ptr((void *)0x4000, regs->reg[4].data); + ut_asserteq(0x0000, regs->reg[4].size); + + ut_asserteq_ptr((void *)0x4000, regs->reg[5].data); + ut_asserteq(0x0e00, regs->reg[5].size); + + free(regs); + + return 0; +} + +LIB_TEST(lib_test_efi_image_region_sort, 0); From 33f183f68b76226a1053694418d2c283371bee72 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 1 Jul 2020 12:44:00 +0200 Subject: [PATCH 14/19] efi_loader: add missing validation of timestamp The UEFI specification requires that when UEFI variables are set using time based authentication we have to check that unused fields of the timestamp are zero Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 74a9c65402..f9a0efd427 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -481,11 +481,15 @@ static efi_status_t efi_variable_authenticate(u16 *variable, if (guidcmp(&auth->auth_info.cert_type, &efi_guid_cert_type_pkcs7)) goto err; + memcpy(×tamp, &auth->time_stamp, sizeof(timestamp)); + if (timestamp.pad1 || timestamp.nanosecond || timestamp.timezone || + timestamp.daylight || timestamp.pad2) + goto err; + *data += sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength; *data_size -= (sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength); - memcpy(×tamp, &auth->time_stamp, sizeof(timestamp)); memset(&tm, 0, sizeof(tm)); tm.tm_year = timestamp.year; tm.tm_mon = timestamp.month; From cb7116030aff44f48f29bdc3bd7ed22f7ad74bb9 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Wed, 1 Jul 2020 15:32:47 +0200 Subject: [PATCH 15/19] efi_loader: time based authentication When overwriting an existing time base authenticated variable we should compare to the preceding time value and not to the start of the epoch. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index f9a0efd427..4d49fd60dc 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -35,7 +35,8 @@ static u8 efi_vendor_keys; static efi_status_t efi_get_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data); + efi_uintn_t *data_size, void *data, + u64 *timep); static efi_status_t efi_set_variable_common(u16 *variable_name, const efi_guid_t *vendor, @@ -309,7 +310,7 @@ static efi_status_t efi_init_secure_state(void) size = 0; ret = efi_get_variable_common(L"PK", &efi_global_variable_guid, - NULL, &size, NULL); + NULL, &size, NULL, NULL); if (ret == EFI_BUFFER_TOO_SMALL) { if (IS_ENABLED(CONFIG_EFI_SECURE_BOOT)) mode = EFI_MODE_USER; @@ -601,7 +602,8 @@ static efi_status_t efi_variable_authenticate(u16 *variable, static efi_status_t efi_get_variable_common(u16 *variable_name, const efi_guid_t *vendor, u32 *attributes, - efi_uintn_t *data_size, void *data) + efi_uintn_t *data_size, void *data, + u64 *timep) { char *native_name; efi_status_t ret; @@ -626,6 +628,9 @@ static efi_status_t efi_get_variable_common(u16 *variable_name, val = parse_attr(val, &attr, &time); + if (timep) + *timep = time; + in_size = *data_size; if ((s = prefix(val, "(blob)"))) { @@ -709,7 +714,7 @@ efi_status_t EFIAPI efi_get_variable(u16 *variable_name, data_size, data); ret = efi_get_variable_common(variable_name, vendor, attributes, - data_size, data); + data_size, data, NULL); return EFI_EXIT(ret); } @@ -905,7 +910,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, old_size = 0; attr = 0; ret = efi_get_variable_common(variable_name, vendor, &attr, - &old_size, NULL); + &old_size, NULL, &time); append = !!(attributes & EFI_VARIABLE_APPEND_WRITE); attributes &= ~(u32)EFI_VARIABLE_APPEND_WRITE; delete = !append && (!data_size || !attributes); @@ -996,7 +1001,7 @@ static efi_status_t efi_set_variable_common(u16 *variable_name, goto err; } ret = efi_get_variable_common(variable_name, vendor, - &attr, &old_size, old_data); + &attr, &old_size, old_data, NULL); if (ret != EFI_SUCCESS) goto err; } else { From 7a373e54350b8cbc27b402d881a07e29a6107c0d Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sun, 31 May 2020 10:07:31 +0200 Subject: [PATCH 16/19] efi_loader: use log function in boot manager When booting via the boot manager use log function for user messages instead of printf() and debug(). Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_bootmgr.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index e144b3e7f4..e268e9c4b8 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Rob Clark */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include @@ -203,14 +205,14 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (lo.attributes & LOAD_OPTION_ACTIVE) { u32 attributes; - debug("%s: trying to load \"%ls\" from %pD\n", - __func__, lo.label, lo.file_path); + log_debug("%s: trying to load \"%ls\" from %pD\n", + __func__, lo.label, lo.file_path); ret = EFI_CALL(efi_load_image(true, efi_root, lo.file_path, NULL, 0, handle)); if (ret != EFI_SUCCESS) { - printf("Loading from Boot%04X '%ls' failed\n", n, - lo.label); + log_warning("Loading %ls '%ls' failed\n", + varname, lo.label); goto error; } @@ -224,11 +226,11 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle) if (ret != EFI_SUCCESS) { if (EFI_CALL(efi_unload_image(*handle)) != EFI_SUCCESS) - printf("Unloading image failed\n"); + log_err("Unloading image failed\n"); goto error; } - printf("Booting: %ls\n", lo.label); + log_info("Booting: %ls\n", lo.label); } else { ret = EFI_LOAD_ERROR; } @@ -268,7 +270,7 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) if (ret == EFI_SUCCESS || ret == EFI_BUFFER_TOO_SMALL) { /* BootNext does exist here */ if (ret == EFI_BUFFER_TOO_SMALL || size != sizeof(u16)) - printf("BootNext must be 16-bit integer\n"); + log_err("BootNext must be 16-bit integer\n"); /* delete BootNext */ ret = EFI_CALL(efi_set_variable( @@ -283,24 +285,26 @@ efi_status_t efi_bootmgr_load(efi_handle_t *handle) ret = try_load_entry(bootnext, handle); if (ret == EFI_SUCCESS) return ret; - printf("Loading from BootNext failed, falling back to BootOrder\n"); + log_warning( + "Loading from BootNext failed, falling back to BootOrder\n"); } } else { - printf("Deleting BootNext failed\n"); + log_err("Deleting BootNext failed\n"); } } /* BootOrder */ bootorder = get_var(L"BootOrder", &efi_global_variable_guid, &size); if (!bootorder) { - printf("BootOrder not defined\n"); + log_info("BootOrder not defined\n"); ret = EFI_NOT_FOUND; goto error; } num = size / sizeof(uint16_t); for (i = 0; i < num; i++) { - debug("%s: trying to load Boot%04X\n", __func__, bootorder[i]); + log_debug("%s trying to load Boot%04X\n", __func__, + bootorder[i]); ret = try_load_entry(bootorder[i], handle); if (ret == EFI_SUCCESS) break; From 3a92f85f2121bb76061758e2830a5a1572729bcf Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 30 Jun 2020 12:02:14 +0200 Subject: [PATCH 17/19] efi_loader: rtc_mktime() called twice Don't call rtc_mktime() twice with the same argument in efi_variable_authenticate(). Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/efi_variable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index 4d49fd60dc..efaba869ef 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -577,7 +577,7 @@ static efi_status_t efi_variable_authenticate(u16 *variable, } /* finished checking */ - *time = rtc_mktime(&tm); + *time = new_time; ret = EFI_SUCCESS; err: From 15b1bf10d1a1b21ecbf20169e30688df1c8e34be Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 19 Mar 2020 18:21:58 +0000 Subject: [PATCH 18/19] efi_loader: export initialization state Export the UEFI sub-system initialization state. This will allow to treat the setting of UEFI variables during and after initialization differently. Signed-off-by: Heinrich Schuchardt --- include/efi_loader.h | 3 +++ lib/efi_loader/efi_setup.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index c2cae814b6..fc9344c742 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -56,6 +56,9 @@ static inline void *guidcpy(void *dst, const void *src) /* Root node */ extern efi_handle_t efi_root; +/* Set to EFI_SUCCESS when initialized */ +extern efi_status_t efi_obj_list_initialized; + /* EFI system partition */ extern struct efi_system_partition { enum if_type if_type; diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c index 671f6da12b..a3b05a4a9b 100644 --- a/lib/efi_loader/efi_setup.c +++ b/lib/efi_loader/efi_setup.c @@ -11,7 +11,7 @@ #define OBJ_LIST_NOT_INITIALIZED 1 -static efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; +efi_status_t efi_obj_list_initialized = OBJ_LIST_NOT_INITIALIZED; /* * Allow unaligned memory access. From 93f6201af71d9a0a521c99212e6066778270a357 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Sat, 21 Mar 2020 20:45:50 +0100 Subject: [PATCH 19/19] efi_loader: imply FAT, FAT_WRITE The UEFI spec requires support for the FAT file system. Signed-off-by: Heinrich Schuchardt --- lib/efi_loader/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index aad37b7155..6c9df3a767 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -15,6 +15,8 @@ config EFI_LOADER select HAVE_BLOCK_DEVICE select REGEX imply CFB_CONSOLE_ANSI + imply FAT + imply FAT_WRITE imply USB_KEYBOARD_FN_KEYS imply VIDEO_ANSI help