diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 57552f99fc..8154efde52 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include @@ -14,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +65,7 @@ static efi_status_t set_load_options(efi_handle_t handle, const char *env_var, size = utf8_utf16_strlen(env) + 1; loaded_image_info->load_options = calloc(size, sizeof(u16)); if (!loaded_image_info->load_options) { - printf("ERROR: Out of memory\n"); + log_err("ERROR: Out of memory\n"); EFI_CALL(systab.boottime->close_protocol(handle, &efi_guid_loaded_image, efi_root, NULL)); @@ -137,7 +140,7 @@ static efi_status_t copy_fdt(void **fdtp) EFI_ACPI_RECLAIM_MEMORY, fdt_pages, &new_fdt_addr); if (ret != EFI_SUCCESS) { - printf("ERROR: Failed to reserve space for FDT\n"); + log_err("ERROR: Failed to reserve space for FDT\n"); goto done; } } @@ -156,8 +159,8 @@ static void efi_reserve_memory(u64 addr, u64 size) addr = (uintptr_t)map_sysmem(addr, 0); if (efi_add_memory_map(addr, size, EFI_RESERVED_MEMORY_TYPE) != EFI_SUCCESS) - printf("Reserved memory mapping failed addr %llx size %llx\n", - addr, size); + log_err("Reserved memory mapping failed addr %llx size %llx\n", + addr, size); } /** @@ -252,7 +255,7 @@ efi_status_t efi_install_fdt(void *fdt) */ #if CONFIG_IS_ENABLED(GENERATE_ACPI_TABLE) if (fdt) { - printf("ERROR: can't have ACPI table and device tree.\n"); + log_err("ERROR: can't have ACPI table and device tree.\n"); return EFI_LOAD_ERROR; } #else @@ -272,13 +275,13 @@ efi_status_t efi_install_fdt(void *fdt) if (!fdt_opt) { fdt_opt = env_get("fdtcontroladdr"); if (!fdt_opt) { - printf("ERROR: need device tree\n"); + log_err("ERROR: need device tree\n"); return EFI_NOT_FOUND; } } fdt_addr = simple_strtoul(fdt_opt, NULL, 16); if (!fdt_addr) { - printf("ERROR: invalid $fdt_addr or $fdtcontroladdr\n"); + log_err("ERROR: invalid $fdt_addr or $fdtcontroladdr\n"); return EFI_LOAD_ERROR; } fdt = map_sysmem(fdt_addr, 0); @@ -286,19 +289,19 @@ efi_status_t efi_install_fdt(void *fdt) /* Install device tree */ if (fdt_check_header(fdt)) { - printf("ERROR: invalid device tree\n"); + log_err("ERROR: invalid device tree\n"); return EFI_LOAD_ERROR; } /* Prepare device tree for payload */ ret = copy_fdt(&fdt); if (ret) { - printf("ERROR: out of memory\n"); + log_err("ERROR: out of memory\n"); return EFI_OUT_OF_RESOURCES; } if (image_setup_libfdt(&img, fdt, 0, NULL)) { - printf("ERROR: failed to process device tree\n"); + log_err("ERROR: failed to process device tree\n"); return EFI_LOAD_ERROR; } @@ -308,7 +311,7 @@ efi_status_t efi_install_fdt(void *fdt) /* Install device tree as UEFI table */ ret = efi_install_configuration_table(&efi_guid_fdt, fdt); if (ret != EFI_SUCCESS) { - printf("ERROR: failed to install device tree\n"); + log_err("ERROR: failed to install device tree\n"); return ret; } #endif /* GENERATE_ACPI_TABLE */ @@ -339,10 +342,13 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle) /* Call our payload! */ ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data)); - printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK); - if (ret && exit_data) { - printf("## %ls\n", exit_data); - efi_free_pool(exit_data); + if (ret != EFI_SUCCESS) { + log_err("## Application failed, r = %lu\n", + ret & ~EFI_ERROR_MASK); + if (exit_data) { + log_err("## %ls\n", exit_data); + efi_free_pool(exit_data); + } } efi_restore_gd(); @@ -364,7 +370,7 @@ static int do_efibootmgr(void) ret = efi_bootmgr_load(&handle); if (ret != EFI_SUCCESS) { - printf("EFI boot manager: Cannot load any image\n"); + log_notice("EFI boot manager: Cannot load any image\n"); return CMD_RET_FAILURE; } @@ -611,8 +617,8 @@ static int do_bootefi(struct cmd_tbl *cmdtp, int flag, int argc, /* Initialize EFI drivers */ ret = efi_init_obj_list(); if (ret != EFI_SUCCESS) { - printf("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); return CMD_RET_FAILURE; } diff --git a/common/bootm_os.c b/common/bootm_os.c index 6a95e0de33..e9aaddf3e6 100644 --- a/common/bootm_os.c +++ b/common/bootm_os.c @@ -542,15 +542,14 @@ static int do_bootm_efi(int flag, int argc, char *const argv[], images->ep); bootstage_mark(BOOTSTAGE_ID_RUN_OS); + /* We expect to return */ + images->os.type = IH_TYPE_STANDALONE; + image_buf = map_sysmem(images->ep, images->os.image_len); efi_ret = efi_run_image(image_buf, images->os.image_len); - if (efi_ret != EFI_SUCCESS) { - printf("## Failed to run EFI image: r = %lu\n", - efi_ret & ~EFI_ERROR_MASK); + if (efi_ret != EFI_SUCCESS) return 1; - } - return 0; } #endif diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h index 8f5c8a7ee3..ca35df29f6 100644 --- a/include/crypto/pkcs7.h +++ b/include/crypto/pkcs7.h @@ -27,7 +27,14 @@ extern int pkcs7_get_content_data(const struct pkcs7_message *pkcs7, const void **_data, size_t *_datalen, size_t *_headerlen); -#ifndef __UBOOT__ +#ifdef __UBOOT__ +struct pkcs7_signed_info; +struct x509_certificate; + +int pkcs7_verify_one(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo, + struct x509_certificate **signer); +#else /* * pkcs7_trust.c */ diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 436a1ee1ee..3ba90fcc34 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -82,9 +82,9 @@ extern int decrypt_blob(struct kernel_pkey_params *, const void *, void *); extern int create_signature(struct kernel_pkey_params *, const void *, void *); extern int verify_signature(const struct key *, const struct public_key_signature *); +#endif /* __UBOOT__ */ int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig); -#endif /* !__UBOOT__ */ #endif /* _LINUX_PUBLIC_KEY_H */ diff --git a/include/mm_communication.h b/include/mm_communication.h index f9c05bb7f1..e464cbb48e 100644 --- a/include/mm_communication.h +++ b/include/mm_communication.h @@ -52,14 +52,14 @@ struct efi_mm_communicate_header { #define MM_COMMUNICATE_HEADER_SIZE \ (sizeof(struct efi_mm_communicate_header)) -/* Defined in EDK2 ArmPkg/Include/IndustryStandard/ArmStdSmc.h */ +/* Defined in EDK2 ArmPkg/Include/IndustryStandard/ArmMmSvc.h */ -/* MM return error codes */ -#define ARM_SMC_MM_RET_SUCCESS 0 -#define ARM_SMC_MM_RET_NOT_SUPPORTED -1 -#define ARM_SMC_MM_RET_INVALID_PARAMS -2 -#define ARM_SMC_MM_RET_DENIED -3 -#define ARM_SMC_MM_RET_NO_MEMORY -4 +/* SPM return error codes */ +#define ARM_SVC_SPM_RET_SUCCESS 0 +#define ARM_SVC_SPM_RET_NOT_SUPPORTED -1 +#define ARM_SVC_SPM_RET_INVALID_PARAMS -2 +#define ARM_SVC_SPM_RET_DENIED -3 +#define ARM_SVC_SPM_RET_NO_MEMORY -5 /* Defined in EDK2 MdeModulePkg/Include/Guid/SmmVariableCommon.h */ diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 2b221b915a..6369bafac0 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -49,4 +49,7 @@ config PKCS7_MESSAGE_PARSER This option provides support for parsing PKCS#7 format messages for signature data and provides the ability to verify the signature. +config PKCS7_VERIFY + bool + endif # ASYMMETRIC_KEY_TYPE diff --git a/lib/crypto/Makefile b/lib/crypto/Makefile index 8267fee0a7..f3a414525d 100644 --- a/lib/crypto/Makefile +++ b/lib/crypto/Makefile @@ -44,6 +44,7 @@ obj-$(CONFIG_PKCS7_MESSAGE_PARSER) += pkcs7_message.o pkcs7_message-y := \ pkcs7.asn1.o \ pkcs7_parser.o +obj-$(CONFIG_PKCS7_VERIFY) += pkcs7_verify.o $(obj)/pkcs7_parser.o: $(obj)/pkcs7.asn1.h $(obj)/pkcs7.asn1.o: $(obj)/pkcs7.asn1.c $(obj)/pkcs7.asn1.h diff --git a/lib/crypto/pkcs7_verify.c b/lib/crypto/pkcs7_verify.c new file mode 100644 index 0000000000..320ba49f79 --- /dev/null +++ b/lib/crypto/pkcs7_verify.c @@ -0,0 +1,657 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* Verify the signature on a PKCS#7 message. + * + * Imported from crypto/asymmetric_keys/pkcs7_verify.c of linux 5.7 + * with modification marked as __UBOOT__. + * + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + */ + +#define pr_fmt(fmt) "PKCS7: "fmt +#ifdef __UBOOT__ +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#include "pkcs7_parser.h" +#endif + +/* + * pkcs7_digest - Digest the relevant parts of the PKCS#7 data + * @pkcs7: PKCS7 Signed Data + * @sinfo: PKCS7 Signed Info + * + * Digest the relevant parts of the PKCS#7 data, @pkcs7, using signature + * information in @sinfo. But if there are authentication attributes, + * i.e. signed image case, the digest must be calculated against + * the authentication attributes. + * + * Return: 0 - on success, non-zero error code - otherwise + */ +#ifdef __UBOOT__ +static int pkcs7_digest(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo) +{ + struct public_key_signature *sig = sinfo->sig; + struct image_region regions[2]; + int ret = 0; + + /* The digest was calculated already. */ + if (sig->digest) + return 0; + + if (!sinfo->sig->hash_algo) + return -ENOPKG; + if (!strcmp(sinfo->sig->hash_algo, "sha256")) + sig->digest_size = SHA256_SUM_LEN; + else if (!strcmp(sinfo->sig->hash_algo, "sha1")) + sig->digest_size = SHA1_SUM_LEN; + else + return -ENOPKG; + + sig->digest = calloc(1, sig->digest_size); + if (!sig->digest) { + pr_warn("Sig %u: Out of memory\n", sinfo->index); + return -ENOMEM; + } + + regions[0].data = pkcs7->data; + regions[0].size = pkcs7->data_len; + + /* Digest the message [RFC2315 9.3] */ + hash_calculate(sinfo->sig->hash_algo, regions, 1, sig->digest); + + /* However, if there are authenticated attributes, there must be a + * message digest attribute amongst them which corresponds to the + * digest we just calculated. + */ + if (sinfo->authattrs) { + u8 tag; + + if (!sinfo->msgdigest) { + pr_warn("Sig %u: No messageDigest\n", sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + + if (sinfo->msgdigest_len != sig->digest_size) { + pr_debug("Sig %u: Invalid digest size (%u)\n", + sinfo->index, sinfo->msgdigest_len); + ret = -EBADMSG; + goto error; + } + + if (memcmp(sig->digest, sinfo->msgdigest, + sinfo->msgdigest_len) != 0) { + pr_debug("Sig %u: Message digest doesn't match\n", + sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + + /* We then calculate anew, using the authenticated attributes + * as the contents of the digest instead. Note that we need to + * convert the attributes from a CONT.0 into a SET before we + * hash it. + */ + memset(sig->digest, 0, sig->digest_size); + + tag = 0x31; + regions[0].data = &tag; + regions[0].size = 1; + regions[1].data = sinfo->authattrs; + regions[1].size = sinfo->authattrs_len; + + hash_calculate(sinfo->sig->hash_algo, regions, 2, sig->digest); + + ret = 0; + } +error: + return ret; +} +#else /* !__UBOOT__ */ +static int pkcs7_digest(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo) +{ + struct public_key_signature *sig = sinfo->sig; + struct crypto_shash *tfm; + struct shash_desc *desc; + size_t desc_size; + int ret; + + kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); + + /* The digest was calculated already. */ + if (sig->digest) + return 0; + + if (!sinfo->sig->hash_algo) + return -ENOPKG; + + /* Allocate the hashing algorithm we're going to need and find out how + * big the hash operational data will be. + */ + tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0); + if (IS_ERR(tfm)) + return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); + + desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); + sig->digest_size = crypto_shash_digestsize(tfm); + + ret = -ENOMEM; + sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); + if (!sig->digest) + goto error_no_desc; + + desc = kzalloc(desc_size, GFP_KERNEL); + if (!desc) + goto error_no_desc; + + desc->tfm = tfm; + + /* Digest the message [RFC2315 9.3] */ + ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len, + sig->digest); + if (ret < 0) + goto error; + pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest); + + /* However, if there are authenticated attributes, there must be a + * message digest attribute amongst them which corresponds to the + * digest we just calculated. + */ + if (sinfo->authattrs) { + u8 tag; + + if (!sinfo->msgdigest) { + pr_warn("Sig %u: No messageDigest\n", sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + + if (sinfo->msgdigest_len != sig->digest_size) { + pr_debug("Sig %u: Invalid digest size (%u)\n", + sinfo->index, sinfo->msgdigest_len); + ret = -EBADMSG; + goto error; + } + + if (memcmp(sig->digest, sinfo->msgdigest, + sinfo->msgdigest_len) != 0) { + pr_debug("Sig %u: Message digest doesn't match\n", + sinfo->index); + ret = -EKEYREJECTED; + goto error; + } + + /* We then calculate anew, using the authenticated attributes + * as the contents of the digest instead. Note that we need to + * convert the attributes from a CONT.0 into a SET before we + * hash it. + */ + memset(sig->digest, 0, sig->digest_size); + + ret = crypto_shash_init(desc); + if (ret < 0) + goto error; + tag = ASN1_CONS_BIT | ASN1_SET; + ret = crypto_shash_update(desc, &tag, 1); + if (ret < 0) + goto error; + ret = crypto_shash_finup(desc, sinfo->authattrs, + sinfo->authattrs_len, sig->digest); + if (ret < 0) + goto error; + pr_devel("AADigest = [%*ph]\n", 8, sig->digest); + } + +error: + kfree(desc); +error_no_desc: + crypto_free_shash(tfm); + kleave(" = %d", ret); + return ret; +} + +int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len, + enum hash_algo *hash_algo) +{ + struct pkcs7_signed_info *sinfo = pkcs7->signed_infos; + int i, ret; + + /* + * This function doesn't support messages with more than one signature. + */ + if (sinfo == NULL || sinfo->next != NULL) + return -EBADMSG; + + ret = pkcs7_digest(pkcs7, sinfo); + if (ret) + return ret; + + *buf = sinfo->sig->digest; + *len = sinfo->sig->digest_size; + + for (i = 0; i < HASH_ALGO__LAST; i++) + if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) { + *hash_algo = i; + break; + } + + return 0; +} +#endif /* !__UBOOT__ */ + +/* + * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 + * uses the issuer's name and the issuing certificate serial number for + * matching purposes. These must match the certificate issuer's name (not + * subject's name) and the certificate serial number [RFC 2315 6.7]. + */ +static int pkcs7_find_key(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo) +{ + struct x509_certificate *x509; + unsigned certix = 1; + + kenter("%u", sinfo->index); + + for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { + /* I'm _assuming_ that the generator of the PKCS#7 message will + * encode the fields from the X.509 cert in the same way in the + * PKCS#7 message - but I can't be 100% sure of that. It's + * possible this will need element-by-element comparison. + */ + if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0])) + continue; + pr_devel("Sig %u: Found cert serial match X.509[%u]\n", + sinfo->index, certix); + + if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) { + pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", + sinfo->index); + continue; + } + + sinfo->signer = x509; + return 0; + } + + /* The relevant X.509 cert isn't found here, but it might be found in + * the trust keyring. + */ + pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", + sinfo->index, + sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data); + return 0; +} + +/* + * pkcs7_verify_sig_chain - Verify the internal certificate chain as best + * as we can. + * @pkcs7: PKCS7 Signed Data + * @sinfo: PKCS7 Signed Info + * @signer: Singer's certificate + * + * Build up and verify the internal certificate chain against a signature + * in @sinfo, using certificates contained in @pkcs7 as best as we can. + * If the chain reaches the end, the last certificate will be returned + * in @signer. + * + * Return: 0 - on success, non-zero error code - otherwise + */ +#ifdef __UBOOT__ +static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo, + struct x509_certificate **signer) +#else +static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo) +#endif +{ + struct public_key_signature *sig; + struct x509_certificate *x509 = sinfo->signer, *p; + struct asymmetric_key_id *auth; + int ret; + + kenter(""); + + *signer = NULL; + + for (p = pkcs7->certs; p; p = p->next) + p->seen = false; + + for (;;) { + pr_debug("verify %s: %*phN\n", + x509->subject, + x509->raw_serial_size, x509->raw_serial); + x509->seen = true; + + if (x509->blacklisted) { + /* If this cert is blacklisted, then mark everything + * that depends on this as blacklisted too. + */ + sinfo->blacklisted = true; + for (p = sinfo->signer; p != x509; p = p->signer) + p->blacklisted = true; + pr_debug("- blacklisted\n"); +#ifdef __UBOOT__ + *signer = x509; +#endif + return 0; + } + + if (x509->unsupported_key) + goto unsupported_crypto_in_x509; + + pr_debug("- issuer %s\n", x509->issuer); + sig = x509->sig; + if (sig->auth_ids[0]) + pr_debug("- authkeyid.id %*phN\n", + sig->auth_ids[0]->len, sig->auth_ids[0]->data); + if (sig->auth_ids[1]) + pr_debug("- authkeyid.skid %*phN\n", + sig->auth_ids[1]->len, sig->auth_ids[1]->data); + + if (x509->self_signed) { + /* If there's no authority certificate specified, then + * the certificate must be self-signed and is the root + * of the chain. Likewise if the cert is its own + * authority. + */ + if (x509->unsupported_sig) + goto unsupported_crypto_in_x509; + x509->signer = x509; + pr_debug("- self-signed\n"); +#ifdef __UBOOT__ + *signer = x509; +#endif + return 0; + } + + /* Look through the X.509 certificates in the PKCS#7 message's + * list to see if the next one is there. + */ + auth = sig->auth_ids[0]; + if (auth) { + pr_debug("- want %*phN\n", auth->len, auth->data); + for (p = pkcs7->certs; p; p = p->next) { + pr_debug("- cmp [%u] %*phN\n", + p->index, p->id->len, p->id->data); + if (asymmetric_key_id_same(p->id, auth)) + goto found_issuer_check_skid; + } + } else if (sig->auth_ids[1]) { + auth = sig->auth_ids[1]; + pr_debug("- want %*phN\n", auth->len, auth->data); + for (p = pkcs7->certs; p; p = p->next) { + if (!p->skid) + continue; + pr_debug("- cmp [%u] %*phN\n", + p->index, p->skid->len, p->skid->data); + if (asymmetric_key_id_same(p->skid, auth)) + goto found_issuer; + } + } + + /* We didn't find the root of this chain */ + pr_debug("- top\n"); +#ifdef __UBOOT__ + *signer = x509; +#endif + return 0; + + found_issuer_check_skid: + /* We matched issuer + serialNumber, but if there's an + * authKeyId.keyId, that must match the CA subjKeyId also. + */ + if (sig->auth_ids[1] && + !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) { + pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n", + sinfo->index, x509->index, p->index); + return -EKEYREJECTED; + } + found_issuer: + pr_debug("- subject %s\n", p->subject); + if (p->seen) { + pr_warn("Sig %u: X.509 chain contains loop\n", + sinfo->index); +#ifdef __UBOOT__ + *signer = p; +#endif + return 0; + } + ret = public_key_verify_signature(p->pub, x509->sig); + if (ret < 0) + return ret; + x509->signer = p; + if (x509 == p) { + pr_debug("- self-signed\n"); +#ifdef __UBOOT__ + *signer = p; +#endif + return 0; + } + x509 = p; +#ifndef __UBOOT__ + might_sleep(); +#endif + } + +unsupported_crypto_in_x509: + /* Just prune the certificate chain at this point if we lack some + * crypto module to go further. Note, however, we don't want to set + * sinfo->unsupported_crypto as the signed info block may still be + * validatable against an X.509 cert lower in the chain that we have a + * trusted copy of. + */ + return 0; +} + +/* + * pkcs7_verify_one - Verify one signed information block from a PKCS#7 + * message. + * @pkcs7: PKCS7 Signed Data + * @sinfo: PKCS7 Signed Info + * @signer: Signer's certificate + * + * Verify one signature in @sinfo and follow the certificate chain. + * If the chain reaches the end, the last certificate will be returned + * in @signer. + * + * Return: 0 - on success, non-zero error code - otherwise + */ +#ifdef __UBOOT__ +int pkcs7_verify_one(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo, + struct x509_certificate **signer) +#else +static int pkcs7_verify_one(struct pkcs7_message *pkcs7, + struct pkcs7_signed_info *sinfo) +#endif +{ + int ret; + + kenter(",%u", sinfo->index); + + /* First of all, digest the data in the PKCS#7 message and the + * signed information block + */ + ret = pkcs7_digest(pkcs7, sinfo); + if (ret < 0) + return ret; + + /* Find the key for the signature if there is one */ + ret = pkcs7_find_key(pkcs7, sinfo); + if (ret < 0) + return ret; + + if (!sinfo->signer) + return 0; + + pr_devel("Using X.509[%u] for sig %u\n", + sinfo->signer->index, sinfo->index); + + /* Check that the PKCS#7 signing time is valid according to the X.509 + * certificate. We can't, however, check against the system clock + * since that may not have been set yet and may be wrong. + */ + if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { + if (sinfo->signing_time < sinfo->signer->valid_from || + sinfo->signing_time > sinfo->signer->valid_to) { + pr_warn("Message signed outside of X.509 validity window\n"); + return -EKEYREJECTED; + } + } + + /* Verify the PKCS#7 binary against the key */ + ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig); + if (ret < 0) + return ret; + + pr_devel("Verified signature %u\n", sinfo->index); + + /* Verify the internal certificate chain */ + return pkcs7_verify_sig_chain(pkcs7, sinfo, signer); +} + +#ifndef __UBOOT__ +/** + * pkcs7_verify - Verify a PKCS#7 message + * @pkcs7: The PKCS#7 message to be verified + * @usage: The use to which the key is being put + * + * Verify a PKCS#7 message is internally consistent - that is, the data digest + * matches the digest in the AuthAttrs and any signature in the message or one + * of the X.509 certificates it carries that matches another X.509 cert in the + * message can be verified. + * + * This does not look to match the contents of the PKCS#7 message against any + * external public keys. + * + * Returns, in order of descending priority: + * + * (*) -EKEYREJECTED if a key was selected that had a usage restriction at + * odds with the specified usage, or: + * + * (*) -EKEYREJECTED if a signature failed to match for which we found an + * appropriate X.509 certificate, or: + * + * (*) -EBADMSG if some part of the message was invalid, or: + * + * (*) 0 if a signature chain passed verification, or: + * + * (*) -EKEYREJECTED if a blacklisted key was encountered, or: + * + * (*) -ENOPKG if none of the signature chains are verifiable because suitable + * crypto modules couldn't be found. + */ +int pkcs7_verify(struct pkcs7_message *pkcs7, + enum key_being_used_for usage) +{ + struct pkcs7_signed_info *sinfo; + int actual_ret = -ENOPKG; + int ret; + + kenter(""); + + switch (usage) { + case VERIFYING_MODULE_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid module sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + if (pkcs7->have_authattrs) { + pr_warn("Invalid module sig (has authattrs)\n"); + return -EKEYREJECTED; + } + break; + case VERIFYING_FIRMWARE_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid firmware sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + if (!pkcs7->have_authattrs) { + pr_warn("Invalid firmware sig (missing authattrs)\n"); + return -EKEYREJECTED; + } + break; + case VERIFYING_KEXEC_PE_SIGNATURE: + if (pkcs7->data_type != OID_msIndirectData) { + pr_warn("Invalid kexec sig (not Authenticode)\n"); + return -EKEYREJECTED; + } + /* Authattr presence checked in parser */ + break; + case VERIFYING_UNSPECIFIED_SIGNATURE: + if (pkcs7->data_type != OID_data) { + pr_warn("Invalid unspecified sig (not pkcs7-data)\n"); + return -EKEYREJECTED; + } + break; + default: + return -EINVAL; + } + + for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { + ret = pkcs7_verify_one(pkcs7, sinfo); + if (sinfo->blacklisted) { + if (actual_ret == -ENOPKG) + actual_ret = -EKEYREJECTED; + continue; + } + if (ret < 0) { + if (ret == -ENOPKG) { + sinfo->unsupported_crypto = true; + continue; + } + kleave(" = %d", ret); + return ret; + } + actual_ret = 0; + } + + kleave(" = %d", actual_ret); + return actual_ret; +} +EXPORT_SYMBOL_GPL(pkcs7_verify); + +/** + * pkcs7_supply_detached_data - Supply the data needed to verify a PKCS#7 message + * @pkcs7: The PKCS#7 message + * @data: The data to be verified + * @datalen: The amount of data + * + * Supply the detached data needed to verify a PKCS#7 message. Note that no + * attempt to retain/pin the data is made. That is left to the caller. The + * data will not be modified by pkcs7_verify() and will not be freed when the + * PKCS#7 message is freed. + * + * Returns -EINVAL if data is already supplied in the message, 0 otherwise. + */ +int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, + const void *data, size_t datalen) +{ + if (pkcs7->data) { + pr_debug("Data already supplied\n"); + return -EINVAL; + } + pkcs7->data = data; + pkcs7->data_len = datalen; + return 0; +} +#endif /* __UBOOT__ */ diff --git a/lib/crypto/public_key.c b/lib/crypto/public_key.c index e12ebbb3d0..a8f7fbed45 100644 --- a/lib/crypto/public_key.c +++ b/lib/crypto/public_key.c @@ -25,7 +25,10 @@ #include #endif #include -#ifndef __UBOOT__ +#ifdef __UBOOT__ +#include +#include +#else #include #endif @@ -80,6 +83,71 @@ void public_key_signature_free(struct public_key_signature *sig) } EXPORT_SYMBOL_GPL(public_key_signature_free); +/** + * public_key_verify_signature - Verify a signature using a public key. + * + * @pkey: Public key + * @sig: Signature + * + * Verify a signature, @sig, using a RSA public key, @pkey. + * + * Return: 0 - verified, non-zero error code - otherwise + */ +int public_key_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig) +{ + struct image_sign_info info; + struct image_region region; + int ret; + + pr_devel("==>%s()\n", __func__); + + if (!pkey || !sig) + return -EINVAL; + + if (pkey->key_is_private) + return -EINVAL; + + memset(&info, '\0', sizeof(info)); + info.padding = image_get_padding_algo("pkcs-1.5"); + /* + * Note: image_get_[checksum|crypto]_algo takes a string + * argument like "," + * TODO: support other hash algorithms + */ + if (strcmp(sig->pkey_algo, "rsa") || (sig->s_size * 8) != 2048) { + pr_warn("Encryption is not RSA2048: %s%d\n", + sig->pkey_algo, sig->s_size * 8); + return -ENOPKG; + } + if (!strcmp(sig->hash_algo, "sha1")) { + info.checksum = image_get_checksum_algo("sha1,rsa2048"); + info.name = "sha1,rsa2048"; + } else if (!strcmp(sig->hash_algo, "sha256")) { + info.checksum = image_get_checksum_algo("sha256,rsa2048"); + info.name = "sha256,rsa2048"; + } else { + pr_warn("unknown msg digest algo: %s\n", sig->hash_algo); + return -ENOPKG; + } + info.crypto = image_get_crypto_algo(info.name); + if (IS_ERR(info.checksum) || IS_ERR(info.crypto)) + return -ENOPKG; + + info.key = pkey->key; + info.keylen = pkey->keylen; + + region.data = sig->digest; + region.size = sig->digest_size; + + if (rsa_verify_with_pkey(&info, sig->digest, sig->s, sig->s_size)) + ret = -EKEYREJECTED; + else + ret = 0; + + pr_devel("<==%s() = %d\n", __func__, ret); + return ret; +} #else /* * Destroy a public key algorithm key. diff --git a/lib/crypto/x509_cert_parser.c b/lib/crypto/x509_cert_parser.c index 5f984b9dfd..eb24349460 100644 --- a/lib/crypto/x509_cert_parser.c +++ b/lib/crypto/x509_cert_parser.c @@ -142,12 +142,10 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen) } cert->id = kid; -#ifndef __UBOOT__ /* Detect self-signed certificates */ ret = x509_check_for_self_signed(cert); if (ret < 0) goto error_decode; -#endif kfree(ctx); return cert; diff --git a/lib/crypto/x509_public_key.c b/lib/crypto/x509_public_key.c index 571af9a0ad..91810a8640 100644 --- a/lib/crypto/x509_public_key.c +++ b/lib/crypto/x509_public_key.c @@ -8,6 +8,7 @@ #define pr_fmt(fmt) "X.509: "fmt #ifdef __UBOOT__ #include +#include #include #include #include @@ -18,6 +19,7 @@ #include #ifdef __UBOOT__ #include +#include #else #include #include @@ -35,7 +37,9 @@ int x509_get_sig_params(struct x509_certificate *cert) { struct public_key_signature *sig = cert->sig; -#ifndef __UBOOT__ +#ifdef __UBOOT__ + struct image_region region; +#else struct crypto_shash *tfm; struct shash_desc *desc; size_t desc_size; @@ -63,12 +67,25 @@ int x509_get_sig_params(struct x509_certificate *cert) sig->s_size = cert->raw_sig_size; #ifdef __UBOOT__ - /* - * Note: - * This part (filling sig->digest) should be implemented if - * x509_check_for_self_signed() is enabled x509_cert_parse(). - * Currently, this check won't affect UEFI secure boot. - */ + if (!sig->hash_algo) + return -ENOPKG; + if (!strcmp(sig->hash_algo, "sha256")) + sig->digest_size = SHA256_SUM_LEN; + else if (!strcmp(sig->hash_algo, "sha1")) + sig->digest_size = SHA1_SUM_LEN; + else + return -ENOPKG; + + sig->digest = calloc(1, sig->digest_size); + if (!sig->digest) + return -ENOMEM; + + region.data = cert->tbs; + region.size = cert->tbs_size; + hash_calculate(sig->hash_algo, ®ion, 1, sig->digest); + + /* TODO: is_hash_blacklisted()? */ + ret = 0; #else /* Allocate the hashing algorithm we're going to need and find out how @@ -118,7 +135,6 @@ error: return ret; } -#ifndef __UBOOT__ /* * Check for self-signedness in an X.509 cert and if found, check the signature * immediately if we can. @@ -175,6 +191,7 @@ not_self_signed: return 0; } +#ifndef __UBOOT__ /* * Attempt to parse a data blob for a key as an X509 certificate. */ diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 0b16554ba2..d49145fc76 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -104,7 +104,15 @@ int __efi_exit_check(void) return ret; } -/* Called from do_bootefi_exec() */ +/** + * efi_save_gd() - save global data register + * + * On the ARM architecture gd is mapped to a fixed register (r9 or x18). + * As this register may be overwritten by an EFI payload we save it here + * and restore it on every callback entered. + * + * This function is called after relocation from initr_reloc_global_data(). + */ void efi_save_gd(void) { #ifdef CONFIG_ARM @@ -112,10 +120,12 @@ void efi_save_gd(void) #endif } -/* - * Special case handler for error/abort that just forces things back to u-boot - * world so we can dump out an abort message, without any care about returning - * back to UEFI world. +/** + * efi_restore_gd() - restore global data register + * + * On the ARM architecture gd is mapped to a fixed register (r9 or x18). + * Restore it after returning from the UEFI world to the value saved via + * efi_save_gd(). */ void efi_restore_gd(void) { diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 670bf2b8ef..7bd1ccec45 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -5,11 +5,14 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include #include #include #include #include +#include #include #include @@ -490,7 +493,7 @@ int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, ret = efi_disk_add_dev(parent, dp, if_typename, desc, diskid, info.start, part, NULL); if (ret != EFI_SUCCESS) { - printf("Adding partition %s failed\n", pdevname); + log_err("Adding partition %s failed\n", pdevname); continue; } disks++; @@ -528,16 +531,16 @@ efi_status_t efi_disk_register(void) const char *if_typename = blk_get_if_type_name(desc->if_type); /* Add block device for the full device */ - printf("Scanning disk %s...\n", dev->name); + log_info("Scanning disk %s...\n", dev->name); ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, desc->devnum, 0, 0, &disk); if (ret == EFI_NOT_READY) { - printf("Disk %s not ready\n", dev->name); + log_notice("Disk %s not ready\n", dev->name); continue; } if (ret) { - printf("ERROR: failure to add disk device %s, r = %lu\n", - dev->name, ret & ~EFI_ERROR_MASK); + log_err("ERROR: failure to add disk device %s, r = %lu\n", + dev->name, ret & ~EFI_ERROR_MASK); return ret; } disks++; @@ -560,7 +563,7 @@ efi_status_t efi_disk_register(void) continue; if_typename = cur_drvr->if_typename; - printf("Scanning disks on %s...\n", if_typename); + log_info("Scanning disks on %s...\n", if_typename); for (i = 0; i < 4; i++) { struct blk_desc *desc; char devname[32] = { 0 }; /* dp->str is u16[32] long */ @@ -578,12 +581,12 @@ efi_status_t efi_disk_register(void) ret = efi_disk_add_dev(NULL, NULL, if_typename, desc, i, 0, 0, &disk); if (ret == EFI_NOT_READY) { - printf("Disk %s not ready\n", devname); + log_notice("Disk %s not ready\n", devname); continue; } if (ret) { - printf("ERROR: failure to add disk device %s, r = %lu\n", - devname, ret & ~EFI_ERROR_MASK); + log_err("ERROR: failure to add disk device %s, r = %lu\n", + devname, ret & ~EFI_ERROR_MASK); return ret; } disks++; @@ -595,7 +598,7 @@ efi_status_t efi_disk_register(void) } } #endif - printf("Found %d disks\n", disks); + log_info("Found %d disks\n", disks); return EFI_SUCCESS; } diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 19afa69f53..44fafae058 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -349,6 +349,11 @@ static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, efi_status_t ret; loff_t file_size; + if (!buffer) { + ret = EFI_INVALID_PARAMETER; + return ret; + } + ret = efi_get_file_size(fh, &file_size); if (ret != EFI_SUCCESS) return ret; @@ -414,6 +419,8 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, fh->dent = dent; return EFI_BUFFER_TOO_SMALL; } + if (!buffer) + return EFI_INVALID_PARAMETER; fh->dent = NULL; *buffer_size = required_size; @@ -443,7 +450,7 @@ static efi_status_t EFIAPI efi_file_read(struct efi_file_handle *file, EFI_ENTRY("%p, %p, %p", file, buffer_size, buffer); - if (!buffer_size || !buffer) { + if (!buffer_size) { ret = EFI_INVALID_PARAMETER; goto error; } diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 91a4551448..78fd8014d9 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -144,6 +144,8 @@ efi_status_t efi_init_runtime_supported(void) * * At runtime memcpy() is not available. * + * Overlapping memory areas can be copied safely if src >= dest. + * * @dest: destination buffer * @src: source buffer * @n: number of bytes to copy diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index 7a2dba7dc2..bfa8a56a8f 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -120,7 +120,8 @@ void __efi_runtime efi_var_mem_del(struct efi_var_entry *var) ALIGN((uintptr_t)data + var->length, 8); efi_var_buf->length -= (uintptr_t)next - (uintptr_t)var; - memmove(var, next, (uintptr_t)last - (uintptr_t)next); + /* efi_memcpy_runtime() can be used because next >= var. */ + efi_memcpy_runtime(var, next, (uintptr_t)last - (uintptr_t)next); efi_var_buf->crc32 = crc32(0, (u8 *)efi_var_buf->var, efi_var_buf->length - sizeof(struct efi_var_file)); @@ -231,6 +232,7 @@ static void EFIAPI __efi_runtime efi_var_mem_notify_virtual_address_map(struct efi_event *event, void *context) { efi_convert_pointer(0, (void **)&efi_var_buf); + efi_current_var = NULL; } efi_status_t efi_var_mem_init(void) diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index c042348938..94c4de8703 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -100,25 +100,25 @@ static efi_status_t optee_mm_communicate(void *comm_buf, ulong dsize) param[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT; rc = tee_invoke_func(conn.tee, &arg, 2, param); - if (rc) - return EFI_INVALID_PARAMETER; tee_shm_free(shm); tee_close_session(conn.tee, conn.session); + if (rc || arg.ret != TEE_SUCCESS) + return EFI_DEVICE_ERROR; switch (param[1].u.value.a) { - case ARM_SMC_MM_RET_SUCCESS: + case ARM_SVC_SPM_RET_SUCCESS: ret = EFI_SUCCESS; break; - case ARM_SMC_MM_RET_INVALID_PARAMS: + case ARM_SVC_SPM_RET_INVALID_PARAMS: ret = EFI_INVALID_PARAMETER; break; - case ARM_SMC_MM_RET_DENIED: + case ARM_SVC_SPM_RET_DENIED: ret = EFI_ACCESS_DENIED; break; - case ARM_SMC_MM_RET_NO_MEMORY: + case ARM_SVC_SPM_RET_NO_MEMORY: ret = EFI_OUT_OF_RESOURCES; break; diff --git a/test/py/tests/test_efi_fit.py b/test/py/tests/test_efi_fit.py index 06fb151c13..068a35a559 100644 --- a/test/py/tests/test_efi_fit.py +++ b/test/py/tests/test_efi_fit.py @@ -420,12 +420,11 @@ def test_efi_fit_launch(u_boot_console): fit_config = 'config-efi-fdt' if enable_fdt else 'config-efi-nofdt' # Try booting. - cons.run_command( - 'bootm %x#%s' % (addr, fit_config), wait_for_prompt=False) + output = cons.run_command('bootm %x#%s' % (addr, fit_config)) if enable_fdt: - cons.wait_for('Booting using the fdt blob') - cons.wait_for('Hello, world') - cons.wait_for('## Application terminated, r = 0') + assert 'Booting using the fdt blob' in output + assert 'Hello, world' in output + assert '## Application failed' not in output cons.restart_uboot() cons = u_boot_console diff --git a/test/py/tests/test_efi_loader.py b/test/py/tests/test_efi_loader.py index 7aa422e764..ca68626cec 100644 --- a/test/py/tests/test_efi_loader.py +++ b/test/py/tests/test_efi_loader.py @@ -161,8 +161,8 @@ def test_efi_helloworld_net(u_boot_console): output = u_boot_console.run_command('bootefi %x' % addr) expected_text = 'Hello, world' assert expected_text in output - expected_text = '## Application terminated, r = 0' - assert expected_text in output + expected_text = '## Application failed' + assert expected_text not in output @pytest.mark.buildconfigspec('cmd_bootefi_hello') def test_efi_helloworld_builtin(u_boot_console): @@ -198,8 +198,7 @@ def test_efi_grub_net(u_boot_console): # Then exit cleanly u_boot_console.wait_for('grub>') - output = u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False) - u_boot_console.wait_for('r = 0') - + u_boot_console.run_command('exit', wait_for_prompt=False, wait_for_echo=False) + u_boot_console.wait_for('=>') # And give us our U-Boot prompt back u_boot_console.run_command('') diff --git a/test/py/tests/test_efi_secboot/conftest.py b/test/py/tests/test_efi_secboot/conftest.py index c6709700a8..c0943b6250 100644 --- a/test/py/tests/test_efi_secboot/conftest.py +++ b/test/py/tests/test_efi_secboot/conftest.py @@ -8,15 +8,6 @@ from subprocess import call, check_call, check_output, CalledProcessError import pytest from defs import * -# from test/py/conftest.py - - -def tool_is_in_path(tool): - for path in os.environ["PATH"].split(os.pathsep): - full_path = os.path.join(path, tool) - if os.path.isfile(full_path) and os.access(full_path, os.X_OK): - return True - return False # # Fixture for UEFI secure boot test @@ -87,21 +78,21 @@ def efi_boot_env(request, u_boot_config): # db1-update 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 (TEST_dbx certificate) + # 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 -t "2020-04-05" -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) + # 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 -t "2020-04-05" -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) + # 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 -t "2020-04-05" -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) + # dbx_db (with TEST_db certificate) check_call('cd %s; %ssign-efi-sig-list -t "2020-04-05" -c KEK.crt -k KEK.key dbx db.esl dbx_db.auth' % (mnt_point, EFITOOLS_PATH), shell=True) @@ -112,10 +103,10 @@ 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 + # 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 + # Digest image 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) @@ -126,7 +117,8 @@ def efi_boot_env(request, u_boot_config): % (mnt_point, EFITOOLS_PATH), shell=True) - check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat {} {}'.format(mnt_point, image_path), shell=True) + check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat {} {}'.format( + mnt_point, image_path), shell=True) check_call('rm -rf {}'.format(mnt_point), shell=True) except CalledProcessError as exception: