summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2020-07-23 08:57:35 -0400
committerTom Rini <trini@konsulko.com>2020-07-23 08:57:35 -0400
commit56d37f1c564107e27d873181d838571b7d7860e7 (patch)
tree41b20866e0a94e34ca76e54a2745ca7a5ba0889b
parent95fc1f164723270b2b0bd8d7e2f7ba21bce66381 (diff)
parent5ee81c6e3f9f6f851c69b1e3d2661d96671d1dd1 (diff)
downloadu-boot-WIP/23Jul2020.tar.gz
Merge tag 'efi-2020-10-rc1-5' of https://gitlab.denx.de/u-boot/custodians/u-boot-efiWIP/23Jul2020
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.
-rw-r--r--cmd/bootefi.c42
-rw-r--r--common/bootm_os.c9
-rw-r--r--include/crypto/pkcs7.h9
-rw-r--r--include/crypto/public_key.h2
-rw-r--r--include/mm_communication.h16
-rw-r--r--lib/crypto/Kconfig3
-rw-r--r--lib/crypto/Makefile1
-rw-r--r--lib/crypto/pkcs7_verify.c657
-rw-r--r--lib/crypto/public_key.c70
-rw-r--r--lib/crypto/x509_cert_parser.c2
-rw-r--r--lib/crypto/x509_public_key.c33
-rw-r--r--lib/efi_loader/efi_boottime.c20
-rw-r--r--lib/efi_loader/efi_disk.c23
-rw-r--r--lib/efi_loader/efi_file.c9
-rw-r--r--lib/efi_loader/efi_runtime.c2
-rw-r--r--lib/efi_loader/efi_var_mem.c4
-rw-r--r--lib/efi_loader/efi_variable_tee.c12
-rw-r--r--test/py/tests/test_efi_fit.py9
-rw-r--r--test/py/tests/test_efi_loader.py9
-rw-r--r--test/py/tests/test_efi_secboot/conftest.py24
20 files changed, 863 insertions, 93 deletions
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 <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;
}
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 */
-
-/* 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
+/* Defined in EDK2 ArmPkg/Include/IndustryStandard/ArmMmSvc.h */
+
+/* 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 <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__ */
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 <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.
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 <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.
*/
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 <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;
}
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: