Pull request for UEFI sub-system for efi-2020-10-rc1 (5)

The series provides bug fixes for:
 
 * crash in OS when accessing UEFI variables
 * returning from UEFI fit images to U-Boot
 * error handling for variable services provided by OP-TEE
 * error handling in EFI_FILE_PROTOCOL.Read()
 * missing function documentation
 
 The first patches needed to use intermediate certificates for
 secure boot are added. (The rest of the series requires
 updating sbsigntool in our CI systems.)
 
 Logging is enabled in the bootefi command.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl8YXdcACgkQxIHbvCwF
 GsQBAQ//ZD0HVRMUKm6YkA7E/+ZnQ+fClf89E7NVTl0HssvEN/mW0qFjvqhX7bdh
 aSyIUvm1sEyhr4vSBobc2QOJW4uQwxRGlV+UongdLALV/XJCD26+qVGZ5QLViowK
 Afp6K8mB6Q/eJCIY22ZCfZYECn7FNs5P6mRfsqcK4IsV7DcB1ltP2pBHloYeZc6g
 dOIcA0eOCq0/VWLw+rIoUSYJf39M+Crx/TwTA/Q78Bphk1fNdGRVGg1RCv5rSq7o
 vR4upEVIW9PG0zwdtn/DtGwUF8rZ9E3T1RHr53O5EmhlhmWe3KJhJnPSLNdhY3F2
 ESyUlT2KHR5kUf6RMbc7BjdfexwQUEI8xlPVQLUKSYpmd9W/t0u3onlTKqOEIIOp
 JJo8lZZX0L3ZbD5w1wJ2HH71qCwwKB/z87ooxWGkVjlnW0RWedqUlEh/Uw4Nq0Ik
 nahpfunu513HLbzJ8Wqqo7n1cifMEkUcgHOrtMccUf3JyN7+UyVikQxZ6GTbIqnl
 a5Dpf4E2dU2vJAWQTzVrmz9/bTkyAzV7VNPhG19NNHMt5GxaWfCpPWV/DkGYZSW/
 QbEaUPDQ3VdqzYvX81eTAPwTSTJrjwKOedOheCRcSmE8/aW93ysjAVbxZgcMb9m+
 Yc6pHYFIRor3GSKrN31J+EYQFALpbSlBxS8x3mcDsvHZWCmXnh4=
 =/wpB
 -----END PGP SIGNATURE-----

Merge tag 'efi-2020-10-rc1-5' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for efi-2020-10-rc1 (5)

The series provides bug fixes for:

* crash in OS when accessing UEFI variables
* returning from UEFI fit images to U-Boot
* error handling for variable services provided by OP-TEE
* error handling in EFI_FILE_PROTOCOL.Read()
* missing function documentation

The first patches needed to use intermediate certificates for
secure boot are added. (The rest of the series requires
updating sbsigntool in our CI systems.)

Logging is enabled in the bootefi command.
This commit is contained in:
Tom Rini 2020-07-23 08:57:35 -04:00
commit 56d37f1c56
20 changed files with 862 additions and 92 deletions

View File

@ -5,6 +5,8 @@
* Copyright (c) 2016 Alexander Graf
*/
#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <charset.h>
#include <command.h>
@ -14,6 +16,7 @@
#include <env.h>
#include <errno.h>
#include <image.h>
#include <log.h>
#include <malloc.h>
#include <linux/libfdt.h>
#include <linux/libfdt_env.h>
@ -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;
}

View File

@ -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

View File

@ -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
*/

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

657
lib/crypto/pkcs7_verify.c Normal file
View File

@ -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 <image.h>
#include <string.h>
#include <linux/bitops.h>
#include <linux/compat.h>
#include <linux/asn1.h>
#include <u-boot/rsa-checksum.h>
#include <crypto/public_key.h>
#include <crypto/pkcs7_parser.h>
#else
#include <linux/kernel.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/asn1.h>
#include <crypto/hash.h>
#include <crypto/hash_info.h>
#include <crypto/public_key.h>
#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__ */

View File

@ -25,7 +25,10 @@
#include <keys/asymmetric-subtype.h>
#endif
#include <crypto/public_key.h>
#ifndef __UBOOT__
#ifdef __UBOOT__
#include <image.h>
#include <u-boot/rsa.h>
#else
#include <crypto/akcipher.h>
#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 "<checksum>,<crypto>"
* 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.

View File

@ -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;

View File

@ -8,6 +8,7 @@
#define pr_fmt(fmt) "X.509: "fmt
#ifdef __UBOOT__
#include <common.h>
#include <image.h>
#include <dm/devres.h>
#include <linux/compat.h>
#include <linux/err.h>
@ -18,6 +19,7 @@
#include <linux/kernel.h>
#ifdef __UBOOT__
#include <crypto/x509_parser.h>
#include <u-boot/rsa-checksum.h>
#else
#include <linux/slab.h>
#include <keys/asymmetric-subtype.h>
@ -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, &region, 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.
*/

View File

@ -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)
{

View File

@ -5,11 +5,14 @@
* Copyright (c) 2016 Alexander Graf
*/
#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <blk.h>
#include <dm.h>
#include <efi_loader.h>
#include <fs.h>
#include <log.h>
#include <part.h>
#include <malloc.h>
@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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('')

View File

@ -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: