All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support
@ 2021-07-27  9:10 AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
                   ` (9 more replies)
  0 siblings, 10 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

As I proposed and discussed in [1] and [2], I have made a couple of
improvements on the current implementation of capsule update in this
patch set.

* add signing feature to mkeficapsule
* add "--guid" option to mkeficapsule
* add man page of mkeficapsule
* add pytest for capsule authentication (on sandbox)

NOTE:
Due to Ilias's commit[3], we need to have a customized configuration
for sandbox to properly set up and run capsule authentication test.
See patch#5,#6 and #7.

[1] https://lists.denx.de/pipermail/u-boot/2021-April/447918.html
[2] https://lists.denx.de/pipermail/u-boot/2021-July/455292.html
[3] commit ddf67daac39d ("efi_capsule: Move signature from DTB to
    .rodata")

Prerequisite patches
====================
None

Test
====
* locally passed the pytest which is included in this patch series
  on sandbox built.

Todo
====
* Confirm that the change in .gitlab-ci.yml works.
* Azure support(?)

Changes
=======
v2 (July 28, 2021)
* rebased on v2021.10-rc*
* removed dependency on target's configuration
* removed fdtsig.sh and others
* add man page
* update the UEFI document
* add dedicate defconfig for testing on sandbox
* add gitlab CI support
* add "--guid" option to mkeficapsule
  (yet rather RFC)

Initial release (May 12, 2021)
* based on v2021.07-rc2

AKASHI Takahiro (9):
  tools: mkeficapsule: add firmwware image signing
  tools: mkeficapsule: add man page
  doc: update UEFI document for usage of mkeficapsule
  efi_loader: ease the file path check for public key
  test/py: efi_capsule: add image authentication test
  sandbox: add config for efi capsule authentication test
  GitLab: add a test rule for efi capsule authentication test
  tools: mkeficapsule: allow for specifying GUID explicitly
  test/py: efi_capsule: align with the syntax change of mkeficapsule

 .gitlab-ci.yml                                |   6 +
 MAINTAINERS                                   |   1 +
 configs/sandbox_capsule_auth_defconfig        | 307 +++++++++++++++
 doc/develop/uefi/uefi.rst                     |  31 +-
 doc/mkeficapsule.1                            |  98 +++++
 lib/efi_loader/Makefile                       |   5 +-
 test/py/tests/test_efi_capsule/SIGNER.crt     |  19 +
 test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
 test/py/tests/test_efi_capsule/SIGNER.key     |  28 ++
 test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 +
 test/py/tests/test_efi_capsule/SIGNER2.key    |  28 ++
 .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
 test/py/tests/test_efi_capsule/conftest.py    |  39 +-
 .../test_capsule_firmware_signed.py           | 228 +++++++++++
 tools/Kconfig                                 |   7 +
 tools/Makefile                                |   8 +-
 tools/mkeficapsule.c                          | 368 ++++++++++++++++--
 17 files changed, 1129 insertions(+), 68 deletions(-)
 create mode 100644 configs/sandbox_capsule_auth_defconfig
 create mode 100644 doc/mkeficapsule.1
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
 create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py

-- 
2.31.0


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

* [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-07-28  8:12   ` Masami Hiramatsu
  2021-08-01  9:21   ` Heinrich Schuchardt
  2021-07-27  9:10 ` [PATCH v2 2/9] tools: mkeficapsule: add man page AKASHI Takahiro
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

With this enhancement, mkeficapsule will be able to sign a capsule
file when it is created. A signature added will be used later
in the verification at FMP's SetImage() call.

To do that, We need specify additional command parameters:
  -monotonic-cout <count> : monotonic count
  -private-key <private key file> : private key file
  -certificate <certificate file> : certificate file
Only when all of those parameters are given, a signature will be added
to a capsule file.

Users are expected to maintain and increment the monotonic count at
every time of the update for each firmware image.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 tools/Kconfig        |   7 +
 tools/Makefile       |   8 +-
 tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
 3 files changed, 316 insertions(+), 31 deletions(-)

diff --git a/tools/Kconfig b/tools/Kconfig
index d6f82cd949b5..9a37ed035311 100644
--- a/tools/Kconfig
+++ b/tools/Kconfig
@@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
 	  This selection does not affect target features, such as runtime FIT
 	  signature verification.
 
+config TOOLS_MKEFICAPSULE
+	bool "Build efimkcapsule command"
+	default y if EFI_CAPSULE_ON_DISK
+	help
+	  This command allows users to create a UEFI capsule file and,
+	  optionally sign that file. If you want to enable UEFI capsule
+	  update feature on your target, you certainly need this.
 endmenu
diff --git a/tools/Makefile b/tools/Makefile
index bae3f95c4995..af8536489652 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
 hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
 HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
 
-mkeficapsule-objs	:= mkeficapsule.o $(LIBFDT_OBJS)
-hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
+HOSTLDLIBS_mkeficapsule += -luuid
+ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
+HOSTLDLIBS_mkeficapsule += \
+	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
+endif
+hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
 
 # We build some files with extra pedantic flags to try to minimize things
 # that won't build on some weird host compiler -- though there are lots of
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 4995ba4e0c2a..798706c7b5f7 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -15,6 +15,16 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
+#include <linux/kconfig.h>
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+#include <openssl/asn1.h>
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+#include <openssl/pkcs7.h>
+#endif
+
 typedef __u8 u8;
 typedef __u16 u16;
 typedef __u32 u32;
@@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
 		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
 efi_guid_t efi_guid_image_type_uboot_raw =
 		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
+efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
+
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
+#else
+static const char *opts_short = "f:r:i:I:v:h";
+#endif
 
 static struct option options[] = {
 	{"fit", required_argument, NULL, 'f'},
 	{"raw", required_argument, NULL, 'r'},
 	{"index", required_argument, NULL, 'i'},
 	{"instance", required_argument, NULL, 'I'},
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+	{"private-key", required_argument, NULL, 'p'},
+	{"certificate", required_argument, NULL, 'c'},
+	{"monotonic-count", required_argument, NULL, 'm'},
+	{"dump-sig", no_argument, NULL, 'd'},
+#endif
 	{"help", no_argument, NULL, 'h'},
 	{NULL, 0, NULL, 0},
 };
@@ -57,16 +80,195 @@ static void print_usage(void)
 	       "\t-r, --raw <raw image>       new raw image file\n"
 	       "\t-i, --index <index>         update image index\n"
 	       "\t-I, --instance <instance>   update hardware instance\n"
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+	       "\t-p, --private-key <privkey file>  private key file\n"
+	       "\t-c, --certificate <cert file>     signer's certificate file\n"
+	       "\t-m, --monotonic-count <count>     monotonic count\n"
+	       "\t-d, --dump_sig              dump signature (*.p7)\n"
+#endif
 	       "\t-h, --help                  print a help message\n",
 	       tool_name);
 }
 
+struct auth_context {
+	char *key_file;
+	char *cert_file;
+	u8 *image_data;
+	size_t image_size;
+	struct efi_firmware_image_authentication auth;
+	u8 *sig_data;
+	size_t sig_size;
+};
+
+static int dump_sig;
+
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+static EVP_PKEY *fileio_read_pkey(const char *filename)
+{
+	EVP_PKEY *key = NULL;
+	BIO *bio;
+
+	bio = BIO_new_file(filename, "r");
+	if (!bio)
+		goto out;
+
+	key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
+
+out:
+	BIO_free_all(bio);
+	if (!key) {
+		printf("Can't load key from file '%s'\n", filename);
+		ERR_print_errors_fp(stderr);
+	}
+
+	return key;
+}
+
+static X509 *fileio_read_cert(const char *filename)
+{
+	X509 *cert = NULL;
+	BIO *bio;
+
+	bio = BIO_new_file(filename, "r");
+	if (!bio)
+		goto out;
+
+	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
+
+out:
+	BIO_free_all(bio);
+	if (!cert) {
+		printf("Can't load certificate from file '%s'\n", filename);
+		ERR_print_errors_fp(stderr);
+	}
+
+	return cert;
+}
+
+static int create_auth_data(struct auth_context *ctx)
+{
+	EVP_PKEY *key = NULL;
+	X509 *cert = NULL;
+	BIO *data_bio = NULL;
+	const EVP_MD *md;
+	PKCS7 *p7;
+	int flags, ret = -1;
+
+	OpenSSL_add_all_digests();
+	OpenSSL_add_all_ciphers();
+	ERR_load_crypto_strings();
+
+	key = fileio_read_pkey(ctx->key_file);
+	if (!key)
+		goto err;
+	cert = fileio_read_cert(ctx->cert_file);
+	if (!cert)
+		goto err;
+
+	/*
+	 * create a BIO, containing:
+	 *  * firmware image
+	 *  * monotonic count
+	 * in this order!
+	 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
+	 */
+	data_bio = BIO_new(BIO_s_mem());
+	BIO_write(data_bio, ctx->image_data, ctx->image_size);
+	BIO_write(data_bio, &ctx->auth.monotonic_count,
+		  sizeof(ctx->auth.monotonic_count));
+
+	md = EVP_get_digestbyname("SHA256");
+	if (!md)
+		goto err;
+
+	/* create signature */
+	/* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
+	flags = PKCS7_BINARY | PKCS7_DETACHED;
+	p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
+	if (!p7)
+		goto err;
+	if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
+		goto err;
+	if (!PKCS7_final(p7, data_bio, flags))
+		goto err;
+
+	/* convert pkcs7 into DER */
+	ctx->sig_data = NULL;
+	ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
+				      ASN1_ITEM_rptr(PKCS7));
+	if (!ctx->sig_size)
+		goto err;
+
+	/* fill auth_info */
+	ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
+						+ ctx->sig_size;
+	ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
+	ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
+	memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
+	       sizeof(efi_guid_cert_type_pkcs7));
+
+	ret = 0;
+err:
+	BIO_free_all(data_bio);
+	EVP_PKEY_free(key);
+	X509_free(cert);
+
+	return ret;
+}
+
+static int dump_signature(const char *path, u8 *signature, size_t sig_size)
+{
+	char *sig_path;
+	FILE *f;
+	size_t size;
+	int ret = -1;
+
+	sig_path = malloc(strlen(path) + 3 + 1);
+	if (!sig_path)
+		return ret;
+
+	sprintf(sig_path, "%s.p7", path);
+	f = fopen(sig_path, "w");
+	if (!f)
+		goto err;
+
+	size = fwrite(signature, 1, sig_size, f);
+	if (size == sig_size)
+		ret = 0;
+
+	fclose(f);
+err:
+	free(sig_path);
+	return ret;
+}
+
+static void free_sig_data(struct auth_context *ctx)
+{
+	if (ctx->sig_size)
+		OPENSSL_free(ctx->sig_data);
+}
+#else
+static int create_auth_data(struct auth_context *ctx)
+{
+	return 0;
+}
+
+static int dump_signature(const char *path, u8 *signature, size_t sig_size)
+{
+	return 0;
+}
+
+static void free_sig_data(struct auth_context *ctx) {}
+#endif
+
 static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
-			unsigned long index, unsigned long instance)
+			unsigned long index, unsigned long instance,
+			uint64_t mcount, char *privkey_file, char *cert_file)
 {
 	struct efi_capsule_header header;
 	struct efi_firmware_management_capsule_header capsule;
 	struct efi_firmware_management_capsule_image_header image;
+	struct auth_context auth_context;
 	FILE *f, *g;
 	struct stat bin_stat;
 	u8 *data;
@@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 	printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
 	printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
 #endif
+	auth_context.sig_size = 0;
 
 	g = fopen(bin, "r");
 	if (!g) {
@@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 		printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
 		goto err_1;
 	}
-	f = fopen(path, "w");
-	if (!f) {
-		printf("cannot open %s\n", path);
+
+	size = fread(data, 1, bin_stat.st_size, g);
+	if (size < bin_stat.st_size) {
+		printf("read failed (%zx)\n", size);
 		goto err_2;
 	}
+
+	/* first, calculate signature to determine its size */
+	if (privkey_file && cert_file) {
+		auth_context.key_file = privkey_file;
+		auth_context.cert_file = cert_file;
+		auth_context.auth.monotonic_count = mcount;
+		auth_context.image_data = data;
+		auth_context.image_size = bin_stat.st_size;
+
+		if (create_auth_data(&auth_context)) {
+			printf("Signing firmware image failed\n");
+			goto err_3;
+		}
+
+		if (dump_sig &&
+		    dump_signature(path, auth_context.sig_data,
+				   auth_context.sig_size)) {
+			printf("Creating signature file failed\n");
+			goto err_3;
+		}
+	}
+
 	header.capsule_guid = efi_guid_fm_capsule;
 	header.header_size = sizeof(header);
 	/* TODO: The current implementation ignores flags */
@@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 					+ sizeof(capsule) + sizeof(u64)
 					+ sizeof(image)
 					+ bin_stat.st_size;
+	if (auth_context.sig_size)
+		header.capsule_image_size += sizeof(auth_context.auth)
+				+ auth_context.sig_size;
+
+	f = fopen(path, "w");
+	if (!f) {
+		printf("cannot open %s\n", path);
+		goto err_3;
+	}
 
 	size = fwrite(&header, 1, sizeof(header), f);
 	if (size < sizeof(header)) {
 		printf("write failed (%zx)\n", size);
-		goto err_3;
+		goto err_4;
 	}
 
 	capsule.version = 0x00000001;
@@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 	size = fwrite(&capsule, 1, sizeof(capsule), f);
 	if (size < (sizeof(capsule))) {
 		printf("write failed (%zx)\n", size);
-		goto err_3;
+		goto err_4;
 	}
 	offset = sizeof(capsule) + sizeof(u64);
 	size = fwrite(&offset, 1, sizeof(offset), f);
 	if (size < sizeof(offset)) {
 		printf("write failed (%zx)\n", size);
-		goto err_3;
+		goto err_4;
 	}
 
 	image.version = 0x00000003;
@@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
 	image.reserved[1] = 0;
 	image.reserved[2] = 0;
 	image.update_image_size = bin_stat.st_size;
+	if (auth_context.sig_size)
+		image.update_image_size += sizeof(auth_context.auth)
+				+ auth_context.sig_size;
 	image.update_vendor_code_size = 0; /* none */
 	image.update_hardware_instance = instance;
 	image.image_capsule_support = 0;
+	if (auth_context.sig_size)
+		image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
 
 	size = fwrite(&image, 1, sizeof(image), f);
 	if (size < sizeof(image)) {
 		printf("write failed (%zx)\n", size);
-		goto err_3;
+		goto err_4;
 	}
-	size = fread(data, 1, bin_stat.st_size, g);
-	if (size < bin_stat.st_size) {
-		printf("read failed (%zx)\n", size);
-		goto err_3;
+
+	if (auth_context.sig_size) {
+		size = fwrite(&auth_context.auth, 1,
+			      sizeof(auth_context.auth), f);
+		if (size < sizeof(auth_context.auth)) {
+			printf("write failed (%zx)\n", size);
+			goto err_4;
+		}
+		size = fwrite(auth_context.sig_data, 1,
+			      auth_context.sig_size, f);
+		if (size < auth_context.sig_size) {
+			printf("write failed (%zx)\n", size);
+			goto err_4;
+		}
 	}
+
 	size = fwrite(data, 1, bin_stat.st_size, f);
 	if (size < bin_stat.st_size) {
 		printf("write failed (%zx)\n", size);
-		goto err_3;
+		goto err_4;
 	}
 
 	fclose(f);
 	fclose(g);
 	free(data);
+	free_sig_data(&auth_context);
 
 	return 0;
 
-err_3:
+err_4:
 	fclose(f);
+err_3:
+	free_sig_data(&auth_context);
 err_2:
 	free(data);
 err_1:
@@ -171,23 +425,25 @@ err_1:
 	return -1;
 }
 
-/*
- * Usage:
- *   $ mkeficapsule -f <firmware binary> <output file>
- */
 int main(int argc, char **argv)
 {
 	char *file;
 	efi_guid_t *guid;
 	unsigned long index, instance;
+	uint64_t mcount;
+	char *privkey_file, *cert_file;
 	int c, idx;
 
 	file = NULL;
 	guid = NULL;
 	index = 0;
 	instance = 0;
+	mcount = 0;
+	privkey_file = NULL;
+	cert_file = NULL;
+	dump_sig = 0;
 	for (;;) {
-		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
+		c = getopt_long(argc, argv, opts_short, options, &idx);
 		if (c == -1)
 			break;
 
@@ -214,26 +470,44 @@ int main(int argc, char **argv)
 		case 'I':
 			instance = strtoul(optarg, NULL, 0);
 			break;
+#ifdef CONFIG_TOOLS_LIBCRYPTO
+		case 'p':
+			if (privkey_file) {
+				printf("Private Key already specified\n");
+				return -1;
+			}
+			privkey_file = optarg;
+			break;
+		case 'c':
+			if (cert_file) {
+				printf("Certificate file already specified\n");
+				return -1;
+			}
+			cert_file = optarg;
+			break;
+		case 'm':
+			mcount = strtoul(optarg, NULL, 0);
+			break;
+		case 'd':
+			dump_sig = 1;
+			break;
+#endif /* CONFIG_TOOLS_LIBCRYPTO */
 		case 'h':
 			print_usage();
 			return 0;
 		}
 	}
 
-	/* need an output file */
-	if (argc != optind + 1) {
+	/* check necessary parameters */
+	if ((argc != optind + 1) || !file ||
+	    ((privkey_file && !cert_file) ||
+	     (!privkey_file && cert_file))) {
 		print_usage();
 		exit(EXIT_FAILURE);
 	}
 
-	/* need a fit image file or raw image file */
-	if (!file) {
-		print_usage();
-		exit(EXIT_SUCCESS);
-	}
-
-	if (create_fwbin(argv[optind], file, guid, index, instance)
-			< 0) {
+	if (create_fwbin(argv[optind], file, guid, index, instance,
+			 mcount, privkey_file, cert_file) < 0) {
 		printf("Creating firmware capsule failed\n");
 		exit(EXIT_FAILURE);
 	}
-- 
2.31.0


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

* [PATCH v2 2/9] tools: mkeficapsule: add man page
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-08-01  9:28   ` Heinrich Schuchardt
  2021-07-27  9:10 ` [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule AKASHI Takahiro
                   ` (7 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

Add a man page for mkeficapsule command.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 MAINTAINERS        |  1 +
 doc/mkeficapsule.1 | 91 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 92 insertions(+)
 create mode 100644 doc/mkeficapsule.1

diff --git a/MAINTAINERS b/MAINTAINERS
index ae6c70860d3a..24f52f837066 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -696,6 +696,7 @@ S:	Maintained
 T:	git https://source.denx.de/u-boot/custodians/u-boot-efi.git
 F:	doc/api/efi.rst
 F:	doc/develop/uefi/*
+F:	doc/mkeficapsule.1
 F:	doc/usage/bootefi.rst
 F:	drivers/rtc/emul_rtc.c
 F:	include/capitalization.h
diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
new file mode 100644
index 000000000000..7c2341160ea4
--- /dev/null
+++ b/doc/mkeficapsule.1
@@ -0,0 +1,91 @@
+.TH MAEFICAPSULE 1 "May 2021"
+
+.SH NAME
+mkeficapsule \- Generate EFI capsule file for U-Boot
+
+.SH SYNOPSIS
+.B mkeficapsule
+.RB [\fIoptions\fP] " \fIcapsule-file\fP"
+
+.SH "DESCRIPTION"
+The
+\fBmkeficapsule\fP
+command is used to create an EFI capsule file for use with the U-Boot
+EFI capsule update.
+A capsule file may contain various type of firmware blobs which
+are to be applied to the system and must be placed in the specific
+directory on the UEFI system partition. An update will be automatically
+executed at next reboot.
+
+Optionally, a capsule file can be signed with a given private key.
+In this case, the update will be authenticated by verifying the signature
+before applying.
+
+\fBmkeficapsule\fP supports two different format of image files:
+.TP
+.I raw image
+format is a single binary blob of any type of firmware.
+
+.TP
+.I FIT (Flattened Image Tree) image
+format
+is the same as used in the new \fIuImage\fP format and allows for
+multiple binary blobs in a single capsule file.
+This type of image file can be generated by \fBmkimage\fP.
+
+.SH "OPTIONS"
+
+.TP
+.BI "-f, --fit \fIfit-image-file\fP"
+Specify a FIT image file
+
+.TP
+.BI "-r, --raw \fIraw-image-file\fP"
+Specify a raw image file
+
+.TP
+.BI "-i, --index \fIindex\fP"
+Specify an image index
+
+.TP
+.BI "-I, --instance \fIinstance\fP"
+Specify a hardware instance
+
+.TP
+.BI "-h, --help"
+Print a help message
+
+.TP 0
+.B With signing:
+
+.TP
+.BI "-p, --private-key \fIprivate-key-file\fP"
+Specify signer's private key file in PEM
+
+.TP
+.BI "-c, --certificate \fIcertificate-file\fP"
+Specify signer's certificate file in EFI certificate list format
+
+.TP
+.BI "-m, --monotonic-count \fIcount\fP"
+Specify a monotonic count which is set to be monotonically incremented
+at every firmware update.
+
+.TP
+.BI "-d, --dump_sig"
+Dump signature data into *.p7 file
+
+.PP
+.SH FILES
+.TP
+.BI "\fI/EFI/UpdateCapsule\fP"
+The directory in which all capsule files be placed
+
+.SH SEE ALSO
+.B mkimage
+
+.SH AUTHORS
+Written by AKASHI Takahiro <takahiro.akashi@linaro.org>
+
+.SH HOMEPAGE
+http://www.denx.de/wiki/U-Boot/WebHome
-- 
2.31.0


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

* [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 2/9] tools: mkeficapsule: add man page AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-08-01  9:31   ` Heinrich Schuchardt
  2021-07-27  9:10 ` [PATCH v2 4/9] efi_loader: ease the file path check for public key AKASHI Takahiro
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

Now we can use mkeficapsule command instead of EDK-II's script
to create a signed capsule file. So update the instruction for
capsule authentication.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 doc/develop/uefi/uefi.rst | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
index 64fe9346c7f2..5ccb455da984 100644
--- a/doc/develop/uefi/uefi.rst
+++ b/doc/develop/uefi/uefi.rst
@@ -347,23 +347,20 @@ and used by the steps highlighted below::
             -keyout CRT.key -out CRT.crt -nodes -days 365
         $ cert-to-efi-sig-list CRT.crt CRT.esl
 
-        $ openssl x509 -in CRT.crt -out CRT.cer -outform DER
-        $ openssl x509 -inform DER -in CRT.cer -outform PEM -out CRT.pub.pem
-
-        $ openssl pkcs12 -export -out CRT.pfx -inkey CRT.key -in CRT.crt
-        $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem
-
-The capsule file can be generated by using the GenerateCapsule.py
-script in EDKII::
-
-    $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \
-      <capsule_file_name> --monotonic-count <val> --fw-version \
-      <val> --lsv <val> --guid \
-      e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \
-      --update-image-index <val> --signer-private-cert \
-      /path/to/CRT.pem --trusted-public-cert \
-      /path/to/CRT.pub.pem --other-public-cert /path/to/CRT.pub.pem \
-      <u-boot.bin>
+The signed capsule file can be generated by using tools/mkeficapsule.
+To build this tool, enable::
+
+    CONFIG_TOOLS_MKEFICAPSULE=y
+    CONFIG_TOOLS_LIBCRYPTO=y
+
+To generate and sign the capsule file::
+
+    $ mkeficapsule --monotonic-count 1 \
+      --private-key CRT.key \
+      --certificate CRT.crt \
+      --index 1 --instance 0 \
+      [--fit <FIT image> | --raw <raw image>] \
+      <capsule_file_name>
 
 Place the capsule generated in the above step on the EFI System
 Partition under the EFI/UpdateCapsule directory
-- 
2.31.0


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

* [PATCH v2 4/9] efi_loader: ease the file path check for public key
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (2 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-08-01  9:35   ` Heinrich Schuchardt
  2021-07-27  9:10 ` [PATCH v2 5/9] test/py: efi_capsule: add image authentication test AKASHI Takahiro
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

The check for CONFIG_EFI_CAPSULE_KEY_PATH:
    ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
does not allow users to specify a relative path for including a public
key binary. This is fine for most of all cases, but it will make it
difficult to add pytest test cases as pre-created keys/certificates
are placed in "test" directory.

So just ease the check, still causing an error if the specified file
does not exist at compiling efi_capsule_key.S.

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

diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index 9b369430e258..fca0da4d131e 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -21,8 +21,9 @@ targets += helloworld.o
 endif
 
 ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y)
-EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
-ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
+#EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
+#ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
+ifeq ($(CONFIG_EFI_CAPSULE_KEY_PATH),"")
 $(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_KEY_PATH)
 endif
 endif
-- 
2.31.0


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

* [PATCH v2 5/9] test/py: efi_capsule: add image authentication test
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (3 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 4/9] efi_loader: ease the file path check for public key AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-08-01  9:38   ` Heinrich Schuchardt
  2021-07-27  9:10 ` [PATCH v2 6/9] sandbox: add config for efi capsule " AKASHI Takahiro
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

Add a couple of test cases against capsule image authentication
for capsule-on-disk, where only a signed capsule file with the verified
signature will be applied to the system.

Due to the difficulty of embedding a public key (esl file) in U-Boot
binary during pytest setup time, all the keys/certificates are pre-created.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_capsule/SIGNER.crt     |  19 ++
 test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
 test/py/tests/test_efi_capsule/SIGNER.key     |  28 +++
 test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 ++
 test/py/tests/test_efi_capsule/SIGNER2.key    |  28 +++
 .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
 test/py/tests/test_efi_capsule/conftest.py    |  35 ++-
 .../test_capsule_firmware_signed.py           | 228 ++++++++++++++++++
 8 files changed, 359 insertions(+), 3 deletions(-)
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
 create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
 create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py

diff --git a/test/py/tests/test_efi_capsule/SIGNER.crt b/test/py/tests/test_efi_capsule/SIGNER.crt
new file mode 100644
index 000000000000..f63ec01d9996
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/SIGNER.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIUD96z+lSbhDFN76YoIY2LnDBt1yQwDQYJKoZIhvcNAQEL
+BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
+NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAMBuazX28i0y4L0loJYJOtlvF5eWb4tbx7zwei5c
+KoSzQYixinS10OrVy7y8mELyXOlGOOsM509vzvoia0nffwEPsvTBeS3le2JBz9iN
+/+AIo+gUmzgEPQN+jp+s4fi0yzRvq3BgWu1ego2gExxQ7AePQHoSkX8UeC3Kb7SF
+a8Kt/TopOupZfEuZ+EtoxPA4JUStFgEUEcRJEfpQqECXV+lKqcyqHc2ZUzMisu+i
+5omkneX8sEZdIPFsSGanCyY3F9VjWzIxo60PU2xUBOIcEUg5luR+VXT4090g/yCw
+8PSf9rIKgGIQSQKAlUSc7zuXQIdgIMTS1xUpc/Nx+SqWNZECAwEAAaNTMFEwHQYD
+VR0OBBYEFHndZVpPrAjc3OD3UZ3xkXQqDOlZMB8GA1UdIwQYMBaAFHndZVpPrAjc
+3OD3UZ3xkXQqDOlZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AG88t6w0qTXE50ltps62f6wtuuZsiX1zj+AluO4E8E3Wi0QsNtT24JdY2P4mAg8y
+abYLdgJIldzzsfjWWok9Dfqnx29tqgesKWkgUo16v70i4EVZ9YWGe+CfOK639OxL
+4D0XPcU5CUpDrEcnt59wCxQ7IArZzrDxrqigEw5nReejtgQV/mEzvVOzWjLjmngy
+SpvrydxYpfSvOJ3KGV9xw3Oa/qO3pS0ZNX9QqZdcC94M0SI6OF635oxJkz6JToYq
++qtv9PZtZnEU/cwzL0nTXMj7yRsP5+2Wre26yT62nKRy9P/3UFwmsJ0OuEmnol5I
+141ZGfBYmSQ6EReOwNeK7A0=
+-----END CERTIFICATE-----
diff --git a/test/py/tests/test_efi_capsule/SIGNER.esl b/test/py/tests/test_efi_capsule/SIGNER.esl
new file mode 100644
index 0000000000000000000000000000000000000000..a54536e243d274b74985abbecfe234d14013ef33
GIT binary patch
literal 829
zcmZ1&d0^?2Da*aux2_hA(f&|m%gg`<iclKDgOCPI%)ACoj9(WpGchtTiSXas{3~R3
zi=prPWg3dT-E$0bud5jFvT<s)d9;1!Wn|=LWiSvk6fqEDV-96u=HU);4GxJ9_H_4i
z4Kk1u=QT1kFgG$YurM_?G>rmsjgYuF^))dnAzQ)7%D~*j$j<<D6&F(zBO}9sylm5N
zpLC5L>{VSbjnnF8zWDTM`Q6dS_k5_*i_vP??AWoft7PkiS65H(*)zlGQ_M>@i`P8Q
z{qxWLQp)zcU(d+D>C3@N-KW(_j^}Um{(r!+_=U)93l>}Ey1w~q9{$*J+9ZE<K|<8q
zxTf9(!ZHDG*!vx-geKODROp_{-_n|WXzgDsO{-UtHQqCScxN2>V4>==R*X?Z@QA12
zuYeT})5BkStvs_z_Uz1HW2H^+7d`7-GWY494Q{atA9Fm?mUF9_i(gHSHZokimOnTr
zgyoTppoitOCv~AEKQ7-@_^+_x!<YHrHgPp133xI!Om&&_-g>%2dxFA|OV>p;i$53s
z)S6~Gk%^g+fpKxLL7;&wFw|xFSj1RFD(|L7`LE%)bLYYLz_}kMmT2+3j5Lr3Nh`BR
z7>G4sSHKTaAk4`4pM}+c8Au@qJ1}N}!OqB#Z?k=k$x72B&pmUOo!eHwMt9e<oX*<f
z{s*c%-m!e}z1HobV|L}+gXs}B{;4tX8)a_eE@SeTdgt@TAJ?KfZFzq!Kc1hvihYe{
zrb19})&9Lo4_qU^wzgG2m~XLe`<FM~4{XJ4k6LniIj?b7-#)*9Tf|y{>*l!)AJ?r|
zAk3HU`h4*=7SVr+#(RS|M;SeyRbk{c`}N5?5lg?Ux0riMGQRL|@vMJ~w=dO|G_4O<
zIX#B^9?wN3D~q`8&w4y3+jaW2Y5iKA|K(e5TA|3_GsgO!mt#)+J}J%r{Oz>0Z+D%v
r+csxO(U<?<17g%R%;nqRxqMNa$MxPw$qx}TRjdTX`wm?1dcz9<2x(B#

literal 0
HcmV?d00001

diff --git a/test/py/tests/test_efi_capsule/SIGNER.key b/test/py/tests/test_efi_capsule/SIGNER.key
new file mode 100644
index 000000000000..9952647ed74a
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/SIGNER.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDAbms19vItMuC9
+JaCWCTrZbxeXlm+LW8e88HouXCqEs0GIsYp0tdDq1cu8vJhC8lzpRjjrDOdPb876
+ImtJ338BD7L0wXkt5XtiQc/Yjf/gCKPoFJs4BD0Dfo6frOH4tMs0b6twYFrtXoKN
+oBMcUOwHj0B6EpF/FHgtym+0hWvCrf06KTrqWXxLmfhLaMTwOCVErRYBFBHESRH6
+UKhAl1fpSqnMqh3NmVMzIrLvouaJpJ3l/LBGXSDxbEhmpwsmNxfVY1syMaOtD1Ns
+VATiHBFIOZbkflV0+NPdIP8gsPD0n/ayCoBiEEkCgJVEnO87l0CHYCDE0tcVKXPz
+cfkqljWRAgMBAAECggEAItLYrAdohC105kXs7bn14GtuRYx/2yRc3SBXvBQJzcHy
+1h3rBHvytszB9gHbPCJIFh8TJdZL9eAyAKpB6Dh9718773cjyt6AmaN3TaVE7PIj
+V1iDTnvV3tAEV3kd27g8Hd0nlUqaqeI0lhSl4LX0QNn3vR+nHOxDY2YDGRQcEDrD
+4hlCIGzAfbCW9gINdadQnC6p9NEBbfJ18doCagdn1Q1UYs8YlWwhBK98wXKGsG6T
+TUywOWIe6+VJqzSwZn5YkDVD3qD4tToar7T0jrCvZjbTbOsjtinD70c3uBcrK/XN
+gpwJfTiDLo1d0tNoWCRUH0myMs1fq3H3SkdfqB1GwQKBgQDrw8FwUc3Q+j8YhR7i
+73H/osk3VOZhCPsqbrQThUo5ZV4EXqp9E3PLN5E3suWgfaXVCEI3lHARUyR+J+E/
+evIrUUnkIryLdVOwwEWRonW4cLANjLSzT0eA85CFLXKUaij7Jfon2YNs9CmUARnC
+M96T3a89XOezX/SbRVz6X8KslQKBgQDQ8onkHcscHMANIjgxycIgYF+MvxwHRICA
+nt3ZSQiGSXJbWK7/sM5yd16ulvsXL7aF9G+q5osOzDWJ0w4SOhqNDfItrFH34Px6
+qEPjq/sAigqqrQls7uu7MHfkE+eEy181CoT9argxo8ifAQDn4YtXBW6L7p6AgaAx
+83FAbBcqDQKBgQClHk185534zTqhZqIyF7bEbfL0sJ5EuXCG0E+IGGLafdbxwocu
+4A/J9Jnc44sU8srQv1745Bn02EEHpdCIkAfJNL5Ga9mW5k39zTsr+xbtXObAJppr
+touCkZLW4vSLYypecsOXYyw7g2kXQgoTTBaHgsv3cvjHVN3QXSz4IVcLXQJ/LBL9
+AyFFtqhZ2mtdbyMfz7SEcyvcvau1b2wTX8IICktz09DhGQ4yffKwBiPS0xE9bwQg
+iewXaQeqQ2hBj5ayAw7uBrRSlfbfSwAzUdL1Hyf/GAFn+5JqJxISOAn6zAgaDRYq
+90mLkOz7ZI7RohfxTGnY56ttw62UHPU87lneiQKBgHcVituUDJgmbaHXx2IVzKsm
+5uDyXUf4S+tY5CZj6WTsb70+q4PYfh1D02nZgxuLNwpwNI0uhLIkLYHcL3poOapC
+LCXS8tsexNosmrTmjHFh/uNdKb7bKbMxyzYrr+ADKMclF3CJzKDzLfiIe9Na+bWa
+q5/HYNIw5zJyapPksgr4
+-----END PRIVATE KEY-----
diff --git a/test/py/tests/test_efi_capsule/SIGNER2.crt b/test/py/tests/test_efi_capsule/SIGNER2.crt
new file mode 100644
index 000000000000..8889a3ed930a
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/SIGNER2.crt
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDTCCAfWgAwIBAgIUfmZcui7VkJEe9jx25Epo6jJ6l+owDQYJKoZIhvcNAQEL
+BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
+NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBANozXTFKGVx0121MIBoSgxfI8IHcfY32T/LQusse
+PaXsm0GaJNwOgEP34u1k0cz466swfBCqTcZRjKuDpcH1sgrF1XaKjxuwYuiJrbsf
+ykVesN1z1bIamkFdVR/CBJEwN/epsyCBQCSbcxUwEX+ayq2zp+kSweew1B4i3u8f
+nbqFB15Rt+KAzFaBlvOJhmoZP7uYtb8zHa58eteaxQmPFt3v6eEbgOt92oVB8fPQ
+JJBuxUAHdimMDQ9mBGUosXR8PFyma5jOiOyY+0oTfig4bRHbGxCGMYyABJDH+j4e
+7Zl7lVMsq2fTm/lGONRX2QPLfMO298pz/wundJmYhseibvUCAwEAAaNTMFEwHQYD
+VR0OBBYEFDPYxE3oBmU1pWrZpY62JuXgcK5aMB8GA1UdIwQYMBaAFDPYxE3oBmU1
+pWrZpY62JuXgcK5aMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
+AEtY9QnvTvgmXmep7AMv/T6+GpERvsRdi+Lc+16L7uSCQhouDkeu5/sUHax6icX1
+NyDb3u6tyQhMnm7CD+7Mo74wrZ4vK2SzBoZSBLi+Tyz2ScyysdRIo7O42nxVyWm7
+ifZVfQKvanUjDSxPO89yJDYp0znvVpuZOzYXFHdprHoR5Atkth11HFHzWDzqblKS
+sx145wgPZ9bYohuOn1weyORsG9bJcHznPyJ1ceAOFk40bKWWLQtruWIhY4aZIlJN
+cDKv92rtgVApaamu+WRC4pzgQMQYKOcnMz4ZKeOKgEajfo6nOUVrvc0IYO6wixvi
+V+Msrg5o7ag2SN2AHg5/1/4=
+-----END CERTIFICATE-----
diff --git a/test/py/tests/test_efi_capsule/SIGNER2.key b/test/py/tests/test_efi_capsule/SIGNER2.key
new file mode 100644
index 000000000000..ee467fd9f7a6
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/SIGNER2.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDaM10xShlcdNdt
+TCAaEoMXyPCB3H2N9k/y0LrLHj2l7JtBmiTcDoBD9+LtZNHM+OurMHwQqk3GUYyr
+g6XB9bIKxdV2io8bsGLoia27H8pFXrDdc9WyGppBXVUfwgSRMDf3qbMggUAkm3MV
+MBF/msqts6fpEsHnsNQeIt7vH526hQdeUbfigMxWgZbziYZqGT+7mLW/Mx2ufHrX
+msUJjxbd7+nhG4DrfdqFQfHz0CSQbsVAB3YpjA0PZgRlKLF0fDxcpmuYzojsmPtK
+E34oOG0R2xsQhjGMgASQx/o+Hu2Ze5VTLKtn05v5RjjUV9kDy3zDtvfKc/8Lp3SZ
+mIbHom71AgMBAAECggEBAJXskO3bAg364kJg+fWwHo7rLAWuYD54rXojXRVPFAC7
+z/mFVio1dIA/BJcknNr/db5MNBKnUYUgZ005yVy52rl4MTGgBrB5w5wPbWWTdEGx
+zEh83KnhiXe8D08g2k6AGRR8b224IUCF5s76FivdScGMHaURlFYDs9t5DkCzMocC
+ty0ewHv9aeMSzJl4y+DrRw+NkkAntlAkerCI5PInFtxyOQ6lFIRkMKlBA//VL0QF
+B9yGbmfoxlErWCqnj70DTcVO7O2AaijU+FTMRbb/V7r34GPU0Cfeum6gGNOtDkaX
+3UnWGR2esiHViMqz8vvEYtVIxHhLTD7INqDlK/yiNEECgYEA+ua1JcHXI2qS3cV/
+BuVvBrd3MzIpZvddCcTdo/B7WT3EoTupEG1gcajrCuNQDtRoizSbMuhCXYoMsktF
+wXFoTWoGr8yO7uVU5r2nCXZneprV3kuQmR0qYipN2GTCGSE1rKQI+YXeALPF1qIp
+12vUVdzWVDJvlQRMvSTlzpRZQkkCgYEA3qKI1ZsBszKPbnzLX91+ZAZeAwwN/HvS
+nrIveJAci/9U2yV2mw3l/Dulc8EkGABs/cMp47toje8DmsSfdu1yIYqpi3MHvefX
++ijc3ry5v28Hia3WP3WPczqhbkT7cco0t8Vwm9w1B+kkreuRCtyoCOLsRauB0CH1
+QJjMtPAth00CgYAKUUhruA/nxe8qLX/uwaqSJSNCuLJZKJzr1OukXTRFVDPsyW5H
+XagUpHSd6wEUywlNiClFq6VnAVFKV6wTq101qcGCoy/RhR67qlrfGb5hnVJkJMla
+coeWp9SxrFsK+4GgitJPqICbmMju7ZY45JdDvKQXrEdIYnfhY04L86/D+QKBgBxx
+nZPU0vnHCuYt0Xn0/XHgEmDHSH4qf7VAxKndl5gXTgsVlTqoIur/39qTIX5jh4lA
+RvjOd8Qydj5uwoTaP0ujwJeNYb7UgRZ35AgdCoo3sDnZ2NaQuXwaUIebDpjyIZwd
+AI8ZKjlRgxspToWZvWotO8yG5fXmcMQJAZZYXSi9AoGBALfXX/C5ojwms1l+XP+p
+FKzOFZ/uEKPfQid+2Sm1BknXXGVbs3zJ4OdonTvhjq+VQvXTW4IvjgY8TpumQZvE
+8nb7I8E1B6ajkSvgfetN9jlKM5hzIfJ3Vxx6hMGMab1ySKy3rZGPL706CW2BeMI2
+v2k9P0qWItuE4S7I4hEsovwS
+-----END PRIVATE KEY-----
diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py
index 4fd6353c2040..aa9bf5eee3aa 100644
--- a/test/py/tests/test_efi_capsule/capsule_defs.py
+++ b/test/py/tests/test_efi_capsule/capsule_defs.py
@@ -3,3 +3,8 @@
 # Directories
 CAPSULE_DATA_DIR = '/EFI/CapsuleTestData'
 CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule'
+
+# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and
+# you need build a newer version on your own.
+# The path must terminate with '/'.
+EFITOOLS_PATH = ''
diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
index 6ad5608cd71c..35cfa5513703 100644
--- a/test/py/tests/test_efi_capsule/conftest.py
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -10,13 +10,13 @@ import pytest
 from capsule_defs import *
 
 #
-# Fixture for UEFI secure boot test
+# Fixture for UEFI capsule test
 #
 
-
 @pytest.fixture(scope='session')
 def efi_capsule_data(request, u_boot_config):
-    """Set up a file system to be used in UEFI capsule test.
+    """Set up a file system to be used in UEFI capsule and
+       authentication test.
 
     Args:
         request: Pytest request object.
@@ -40,6 +40,22 @@ def efi_capsule_data(request, u_boot_config):
         check_call('mkdir -p %s' % data_dir, shell=True)
         check_call('mkdir -p %s' % install_dir, shell=True)
 
+        capsule_auth_enabled = u_boot_config.buildconfig.get(
+                    'config_efi_capsule_authenticate')
+        # NOTE:
+        # private keys (SIGNER?.key) dn certificates (SIGNER?.crt)
+        # in this pytest directory are created this way:
+        # Create private key (SIGNER.key) and certificate (SIGNER.crt)
+        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER.key -out SIGNER.crt -nodes -days 365'
+        #               % data_dir, shell=True)
+        #    check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl'
+        #               % (data_dir, EFITOOLS_PATH), shell=True)
+
+        # Create *malicious* private key (SIGNER2.key) and certificate
+        # (SIGNER2.crt)
+        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER2.key -out SIGNER2.crt -nodes -days 365'
+        #               % data_dir, shell=True)
+
         # Create capsule files
         # two regions: one for u-boot.bin and the other for u-boot.env
         check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old -> u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
@@ -56,6 +72,19 @@ def efi_capsule_data(request, u_boot_config):
         check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 Test02' %
                    (data_dir, u_boot_config.build_dir),
                    shell=True)
+        if capsule_auth_enabled:
+            # copy keys/certificates
+            check_call('cp %s/test/py/tests/test_efi_capsule/SIGNER*.* %s' %
+                       (u_boot_config.source_dir, data_dir),
+                       shell=True)
+            # firmware signed with proper key
+            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER.key --certificate SIGNER.crt Test03' %
+                       (data_dir, u_boot_config.build_dir),
+                       shell=True)
+            # firmware signed with *mal* key
+            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER2.key --certificate SIGNER2.crt Test04' %
+                       (data_dir, u_boot_config.build_dir),
+                       shell=True)
 
         # Create a disk image with EFI system partition
         check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
new file mode 100644
index 000000000000..8fe93ef424ac
--- /dev/null
+++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
@@ -0,0 +1,228 @@
+# SPDX-License-Identifier:      GPL-2.0+
+# Copyright (c) 2021, Linaro Limited
+# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
+#
+# U-Boot UEFI: Firmware Update (Signed capsule) Test
+
+"""
+This test verifies capsule-on-disk firmware update
+with signed capsule files
+"""
+
+from subprocess import check_call, check_output, CalledProcessError
+import pytest
+from capsule_defs import *
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
+@pytest.mark.buildconfigspec('efi_capsule_authenticate')
+@pytest.mark.buildconfigspec('dfu')
+@pytest.mark.buildconfigspec('dfu_sf')
+@pytest.mark.buildconfigspec('cmd_efidebug')
+@pytest.mark.buildconfigspec('cmd_fat')
+@pytest.mark.buildconfigspec('cmd_memory')
+@pytest.mark.buildconfigspec('cmd_nvedit_efi')
+@pytest.mark.buildconfigspec('cmd_sf')
+@pytest.mark.slow
+class TestEfiCapsuleFirmwareSigned(object):
+    def test_efi_capsule_auth1(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 1 - Update U-Boot on SPI Flash, raw image format
+                      0x100000-0x150000: U-Boot binary (but dummy)
+
+                      If the capsule is properly signed, the authentication
+                      should pass and the firmware be updated.
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 1-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
+                'efidebug boot order 1',
+                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize content
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test03' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test03 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test03' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 1-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test03' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e Capsule0000')
+
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test03' not in ''.join(output)
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:New' in ''.join(output)
+
+    def test_efi_capsule_auth2(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 2 - Update U-Boot on SPI Flash, raw image format
+                      0x100000-0x150000: U-Boot binary (but dummy)
+
+                      If the capsule is signed but with an invalid key,
+                      the authentication should fail and the firmware
+                      not be updated.
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 2-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
+                'efidebug boot order 1',
+                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize content
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test04' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test04 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test04' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 2-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test04' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e Capsule0000')
+
+            # deleted any way
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test04' not in ''.join(output)
+
+            # TODO: check CapsuleStatus in CapsuleXXXX
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:Old' in ''.join(output)
+
+    def test_efi_capsule_auth3(
+            self, u_boot_config, u_boot_console, efi_capsule_data):
+        """
+        Test Case 3 - Update U-Boot on SPI Flash, raw image format
+                      0x100000-0x150000: U-Boot binary (but dummy)
+
+                      If the capsule is not signed, the authentication
+                      should fail and the firmware not be updated.
+        """
+        disk_img = efi_capsule_data
+        with u_boot_console.log.section('Test Case 3-a, before reboot'):
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
+                'efidebug boot order 1',
+                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
+                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                'env save'])
+
+            # initialize content
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
+                'sf write 4000000 100000 10',
+                'sf read 5000000 100000 10',
+                'md.b 5000000 10'])
+            assert 'Old' in ''.join(output)
+
+            # place a capsule file
+            output = u_boot_console.run_command_list([
+                'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
+                'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test02' in ''.join(output)
+
+        # reboot
+        u_boot_console.restart_uboot()
+
+        capsule_early = u_boot_config.buildconfig.get(
+            'config_efi_capsule_on_disk_early')
+        with u_boot_console.log.section('Test Case 3-b, after reboot'):
+            if not capsule_early:
+                # make sure that dfu_alt_info exists even persistent variables
+                # are not available.
+                output = u_boot_console.run_command_list([
+                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
+                    'host bind 0 %s' % disk_img,
+                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+                assert 'Test02' in ''.join(output)
+
+                # need to run uefi command to initiate capsule handling
+                output = u_boot_console.run_command(
+                    'env print -e Capsule0000')
+
+            # deleted any way
+            output = u_boot_console.run_command_list([
+                'host bind 0 %s' % disk_img,
+                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
+            assert 'Test02' not in ''.join(output)
+
+            # TODO: check CapsuleStatus in CapsuleXXXX
+
+            output = u_boot_console.run_command_list([
+                'sf probe 0:0',
+                'sf read 4000000 100000 10',
+                'md.b 4000000 10'])
+            assert 'u-boot:Old' in ''.join(output)
-- 
2.31.0


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

* [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (4 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 5/9] test/py: efi_capsule: add image authentication test AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-07-28 20:21   ` Heinrich Schuchardt
  2021-07-31 16:59   ` Simon Glass
  2021-07-27  9:10 ` [PATCH v2 7/9] GitLab: add a test rule " AKASHI Takahiro
                   ` (3 subsequent siblings)
  9 siblings, 2 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

This new configuration, which was derived from sandbox_defconfig, will be
used solely to run efi capsule authentication test as the test requires
a public key (esl file) to be embedded in U-Boot binary.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
 1 file changed, 307 insertions(+)
 create mode 100644 configs/sandbox_capsule_auth_defconfig

diff --git a/configs/sandbox_capsule_auth_defconfig b/configs/sandbox_capsule_auth_defconfig
new file mode 100644
index 000000000000..8e0ffb1a6995
--- /dev/null
+++ b/configs/sandbox_capsule_auth_defconfig
@@ -0,0 +1,307 @@
+CONFIG_SYS_TEXT_BASE=0
+CONFIG_NR_DRAM_BANKS=1
+CONFIG_SYS_MEMTEST_START=0x00100000
+CONFIG_SYS_MEMTEST_END=0x00101000
+CONFIG_ENV_SIZE=0x2000
+CONFIG_DEFAULT_DEVICE_TREE="sandbox"
+CONFIG_PRE_CON_BUF_ADDR=0xf0000
+CONFIG_BOOTSTAGE_STASH_ADDR=0x0
+CONFIG_DEBUG_UART=y
+CONFIG_DISTRO_DEFAULTS=y
+CONFIG_FIT=y
+CONFIG_FIT_SIGNATURE=y
+CONFIG_FIT_RSASSA_PSS=y
+CONFIG_FIT_CIPHER=y
+CONFIG_FIT_VERBOSE=y
+CONFIG_BOOTSTAGE=y
+CONFIG_BOOTSTAGE_REPORT=y
+CONFIG_BOOTSTAGE_FDT=y
+CONFIG_BOOTSTAGE_STASH=y
+CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
+CONFIG_CONSOLE_RECORD=y
+CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
+CONFIG_PRE_CONSOLE_BUFFER=y
+CONFIG_LOG=y
+CONFIG_DISPLAY_BOARDINFO_LATE=y
+CONFIG_MISC_INIT_F=y
+CONFIG_STACKPROTECTOR=y
+CONFIG_ANDROID_AB=y
+CONFIG_CMD_CPU=y
+CONFIG_CMD_LICENSE=y
+CONFIG_CMD_BOOTZ=y
+CONFIG_CMD_BOOTEFI_HELLO=y
+CONFIG_CMD_ABOOTIMG=y
+# CONFIG_CMD_ELF is not set
+CONFIG_CMD_ASKENV=y
+CONFIG_CMD_GREPENV=y
+CONFIG_CMD_ERASEENV=y
+CONFIG_CMD_ENV_CALLBACK=y
+CONFIG_CMD_ENV_FLAGS=y
+CONFIG_CMD_NVEDIT_EFI=y
+CONFIG_CMD_NVEDIT_INFO=y
+CONFIG_CMD_NVEDIT_LOAD=y
+CONFIG_CMD_NVEDIT_SELECT=y
+CONFIG_LOOPW=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_MEM_SEARCH=y
+CONFIG_CMD_MX_CYCLIC=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_BIND=y
+CONFIG_CMD_DEMO=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_PWM=y
+CONFIG_CMD_GPT=y
+CONFIG_CMD_GPT_RENAME=y
+CONFIG_CMD_IDE=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_LSBLK=y
+CONFIG_CMD_MUX=y
+CONFIG_CMD_OSD=y
+CONFIG_CMD_PCI=y
+CONFIG_CMD_READ=y
+CONFIG_CMD_REMOTEPROC=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
+CONFIG_CMD_AXI=y
+CONFIG_CMD_AB_SELECT=y
+CONFIG_BOOTP_DNS2=y
+CONFIG_CMD_PCAP=y
+CONFIG_CMD_TFTPPUT=y
+CONFIG_CMD_TFTPSRV=y
+CONFIG_CMD_RARP=y
+CONFIG_CMD_CDP=y
+CONFIG_CMD_SNTP=y
+CONFIG_CMD_DNS=y
+CONFIG_CMD_LINK_LOCAL=y
+CONFIG_CMD_ETHSW=y
+CONFIG_CMD_BMP=y
+CONFIG_CMD_BOOTCOUNT=y
+CONFIG_CMD_EFIDEBUG=y
+CONFIG_CMD_RTC=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_TIMER=y
+CONFIG_CMD_SOUND=y
+CONFIG_CMD_QFW=y
+CONFIG_CMD_PSTORE=y
+CONFIG_CMD_PSTORE_MEM_ADDR=0x3000000
+CONFIG_CMD_BOOTSTAGE=y
+CONFIG_CMD_PMIC=y
+CONFIG_CMD_REGULATOR=y
+CONFIG_CMD_AES=y
+CONFIG_CMD_TPM=y
+CONFIG_CMD_TPM_TEST=y
+CONFIG_CMD_BTRFS=y
+CONFIG_CMD_CBFS=y
+CONFIG_CMD_CRAMFS=y
+CONFIG_CMD_EXT4_WRITE=y
+CONFIG_CMD_SQUASHFS=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_CMD_STACKPROTECTOR_TEST=y
+CONFIG_MAC_PARTITION=y
+CONFIG_AMIGA_PARTITION=y
+CONFIG_OF_CONTROL=y
+CONFIG_OF_LIVE=y
+CONFIG_OF_HOSTFILE=y
+CONFIG_ENV_IS_NOWHERE=y
+CONFIG_ENV_IS_IN_EXT4=y
+CONFIG_ENV_EXT4_INTERFACE="host"
+CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
+CONFIG_ENV_IMPORT_FDT=y
+CONFIG_BOOTP_SEND_HOSTNAME=y
+CONFIG_NETCONSOLE=y
+CONFIG_IP_DEFRAG=y
+CONFIG_DM_DMA=y
+CONFIG_REGMAP=y
+CONFIG_SYSCON=y
+CONFIG_DEVRES=y
+CONFIG_DEBUG_DEVRES=y
+CONFIG_SIMPLE_PM_BUS=y
+CONFIG_ADC=y
+CONFIG_ADC_SANDBOX=y
+CONFIG_AXI=y
+CONFIG_AXI_SANDBOX=y
+CONFIG_BOOTCOUNT_LIMIT=y
+CONFIG_DM_BOOTCOUNT=y
+CONFIG_DM_BOOTCOUNT_RTC=y
+CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y
+CONFIG_BUTTON=y
+CONFIG_BUTTON_ADC=y
+CONFIG_BUTTON_GPIO=y
+CONFIG_CLK=y
+CONFIG_CLK_COMPOSITE_CCF=y
+CONFIG_CLK_SCMI=y
+CONFIG_CLK_K210=y
+CONFIG_CLK_K210_SET_RATE=y
+CONFIG_SANDBOX_CLK_CCF=y
+CONFIG_CPU=y
+CONFIG_DM_DEMO=y
+CONFIG_DM_DEMO_SIMPLE=y
+CONFIG_DM_DEMO_SHAPE=y
+CONFIG_DFU_SF=y
+CONFIG_DMA=y
+CONFIG_DMA_CHANNELS=y
+CONFIG_SANDBOX_DMA=y
+CONFIG_FASTBOOT_FLASH=y
+CONFIG_FASTBOOT_FLASH_MMC_DEV=0
+CONFIG_GPIO_HOG=y
+CONFIG_DM_GPIO_LOOKUP_LABEL=y
+CONFIG_PM8916_GPIO=y
+CONFIG_SANDBOX_GPIO=y
+CONFIG_DM_HWSPINLOCK=y
+CONFIG_HWSPINLOCK_SANDBOX=y
+CONFIG_I2C_CROS_EC_TUNNEL=y
+CONFIG_I2C_CROS_EC_LDO=y
+CONFIG_DM_I2C_GPIO=y
+CONFIG_SYS_I2C_SANDBOX=y
+CONFIG_I2C_MUX=y
+CONFIG_SPL_I2C_MUX=y
+CONFIG_I2C_ARB_GPIO_CHALLENGE=y
+CONFIG_CROS_EC_KEYB=y
+CONFIG_I8042_KEYB=y
+CONFIG_LED=y
+CONFIG_LED_BLINK=y
+CONFIG_LED_GPIO=y
+CONFIG_DM_MAILBOX=y
+CONFIG_SANDBOX_MBOX=y
+CONFIG_MISC=y
+CONFIG_CROS_EC=y
+CONFIG_CROS_EC_I2C=y
+CONFIG_CROS_EC_LPC=y
+CONFIG_CROS_EC_SANDBOX=y
+CONFIG_CROS_EC_SPI=y
+CONFIG_P2SB=y
+CONFIG_PWRSEQ=y
+CONFIG_SPL_PWRSEQ=y
+CONFIG_I2C_EEPROM=y
+CONFIG_MMC_PCI=y
+CONFIG_MMC_SANDBOX=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MTD=y
+CONFIG_SPI_FLASH_SANDBOX=y
+CONFIG_SPI_FLASH_ATMEL=y
+CONFIG_SPI_FLASH_EON=y
+CONFIG_SPI_FLASH_GIGADEVICE=y
+CONFIG_SPI_FLASH_MACRONIX=y
+CONFIG_SPI_FLASH_SPANSION=y
+CONFIG_SPI_FLASH_STMICRO=y
+CONFIG_SPI_FLASH_SST=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_MULTIPLEXER=y
+CONFIG_MUX_MMIO=y
+CONFIG_DM_ETH=y
+CONFIG_NVME=y
+CONFIG_PCI=y
+CONFIG_DM_PCI=y
+CONFIG_PCI_REGION_MULTI_ENTRY=y
+CONFIG_PCI_SANDBOX=y
+CONFIG_PHY=y
+CONFIG_PHY_SANDBOX=y
+CONFIG_PINCTRL=y
+CONFIG_PINCONF=y
+CONFIG_PINCTRL_SANDBOX=y
+CONFIG_PINCTRL_SINGLE=y
+CONFIG_POWER_DOMAIN=y
+CONFIG_SANDBOX_POWER_DOMAIN=y
+CONFIG_DM_PMIC=y
+CONFIG_PMIC_ACT8846=y
+CONFIG_DM_PMIC_PFUZE100=y
+CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
+CONFIG_PMIC_PM8916=y
+CONFIG_PMIC_RK8XX=y
+CONFIG_PMIC_S2MPS11=y
+CONFIG_DM_PMIC_SANDBOX=y
+CONFIG_PMIC_S5M8767=y
+CONFIG_PMIC_TPS65090=y
+CONFIG_DM_REGULATOR=y
+CONFIG_REGULATOR_ACT8846=y
+CONFIG_DM_REGULATOR_PFUZE100=y
+CONFIG_DM_REGULATOR_MAX77686=y
+CONFIG_DM_REGULATOR_FIXED=y
+CONFIG_REGULATOR_RK8XX=y
+CONFIG_REGULATOR_S5M8767=y
+CONFIG_DM_REGULATOR_SANDBOX=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_DM_REGULATOR_SCMI=y
+CONFIG_DM_PWM=y
+CONFIG_PWM_CROS_EC=y
+CONFIG_PWM_SANDBOX=y
+CONFIG_RAM=y
+CONFIG_REMOTEPROC_SANDBOX=y
+CONFIG_DM_RESET=y
+CONFIG_SANDBOX_RESET=y
+CONFIG_RESET_SYSCON=y
+CONFIG_RESET_SCMI=y
+CONFIG_DM_RNG=y
+CONFIG_DM_RTC=y
+CONFIG_RTC_RV8803=y
+CONFIG_SANDBOX_SERIAL=y
+CONFIG_SMEM=y
+CONFIG_SANDBOX_SMEM=y
+CONFIG_SOUND=y
+CONFIG_SOUND_DA7219=y
+CONFIG_SOUND_MAX98357A=y
+CONFIG_SOUND_SANDBOX=y
+CONFIG_SOC_DEVICE=y
+CONFIG_SANDBOX_SPI=y
+CONFIG_SPMI=y
+CONFIG_SPMI_SANDBOX=y
+CONFIG_SYSINFO=y
+CONFIG_SYSINFO_SANDBOX=y
+CONFIG_SYSINFO_GPIO=y
+CONFIG_SYSRESET=y
+CONFIG_TIMER=y
+CONFIG_TIMER_EARLY=y
+CONFIG_SANDBOX_TIMER=y
+CONFIG_USB=y
+CONFIG_DM_USB=y
+CONFIG_USB_EMUL=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_DM_VIDEO=y
+CONFIG_VIDEO_COPY=y
+CONFIG_CONSOLE_ROTATION=y
+CONFIG_CONSOLE_TRUETYPE=y
+CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
+CONFIG_VIDEO_SANDBOX_SDL=y
+CONFIG_VIDEO_DSI_HOST_SANDBOX=y
+CONFIG_OSD=y
+CONFIG_SANDBOX_OSD=y
+CONFIG_SPLASH_SCREEN_ALIGN=y
+CONFIG_VIDEO_BMP_RLE8=y
+CONFIG_W1=y
+CONFIG_W1_GPIO=y
+CONFIG_W1_EEPROM=y
+CONFIG_W1_EEPROM_SANDBOX=y
+CONFIG_WDT=y
+CONFIG_WDT_SANDBOX=y
+CONFIG_FS_CBFS=y
+CONFIG_FS_CRAMFS=y
+CONFIG_CMD_DHRYSTONE=y
+CONFIG_TPM=y
+CONFIG_LZ4=y
+CONFIG_ERRNO_STR=y
+CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
+CONFIG_EFI_CAPSULE_ON_DISK=y
+CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
+CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
+CONFIG_EFI_CAPSULE_AUTHENTICATE=y
+CONFIG_EFI_CAPSULE_KEY_PATH="../test/py/tests/test_efi_capsule/SIGNER.esl"
+CONFIG_EFI_SECURE_BOOT=y
+CONFIG_TEST_FDTDEC=y
+CONFIG_CRYPT_PW=y
+CONFIG_CRYPT_PW_SHA256=y
+CONFIG_CRYPT_PW_SHA512=y
+CONFIG_AUTOBOOT_KEYED=y
+CONFIG_AUTOBOOT_PROMPT="Enter password \"a\" in %d seconds to stop autoboot\n"
+CONFIG_AUTOBOOT_ENCRYPTION=y
+CONFIG_AUTOBOOT_STOP_STR_ENABLE=y
+CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9"
+CONFIG_AUTOBOOT_NEVER_TIMEOUT=y
+CONFIG_AUTOBOOT_SHA256_FALLBACK=y
+CONFIG_UNIT_TEST=y
+CONFIG_UT_TIME=y
+CONFIG_UT_DM=y
+CONFIG_DM_REBOOT_MODE=y
+CONFIG_DM_REBOOT_MODE_GPIO=y
+CONFIG_DM_REBOOT_MODE_RTC=y
-- 
2.31.0


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

* [PATCH v2 7/9] GitLab: add a test rule for efi capsule authentication test
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (5 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 6/9] sandbox: add config for efi capsule " AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 8/9] tools: mkeficapsule: allow for specifying GUID explicitly AKASHI Takahiro
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

To run efi capsule authentication test in CI loop, U-Boot binary must be
compiled with an appropriate public key (esl file).
Add a rule to build this binary with sandbox_capsule_auth_defconfig
and run the test.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 .gitlab-ci.yml | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 86026a15f9da..ed67314fa4ca 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -193,6 +193,12 @@ sandbox_noinst_test.py:
     TEST_PY_TEST_SPEC: "test_ofplatdata or test_handoff or test_spl"
   <<: *buildman_and_testpy_dfn
 
+sandbox_capsule_auth test.py:
+  variables:
+    TEST_PY_BD: "sandbox_capsule_auth"
+    TEST_PY_TEST_SPEC: "test_efi_capsule_signed"
+  <<: *buildman_and_testpy_dfn
+
 evb-ast2500 test.py:
   variables:
     TEST_PY_BD: "evb-ast2500"
-- 
2.31.0


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

* [PATCH v2 8/9] tools: mkeficapsule: allow for specifying GUID explicitly
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (6 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 7/9] GitLab: add a test rule " AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-07-27  9:10 ` [PATCH v2 9/9] test/py: efi_capsule: align with the syntax change of mkeficapsule AKASHI Takahiro
  2021-08-01  9:40 ` [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support Heinrich Schuchardt
  9 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

The existing options, "--fit" and "--raw," are only used to put a proper
GUID in a capsule header, where GUID identifies a particular FMP (Firmware
Management Protocol) driver which then would handle the firmware binary in
a capsule. In fact, mkeficapsule does the exact same job in creating
a capsule file whatever the firmware binary type is.

To prepare for the future extension, the command syntax will be a bit
modified to allow users to specify arbitrary GUID for their own FMP driver.
OLD:
   [--fit <image> | --raw <image>] <capsule file>
NEW:
   [--fit | --raw | --guid <guid-string>] <image> <capsule file>

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 doc/mkeficapsule.1   | 19 ++++++++++++------
 tools/mkeficapsule.c | 46 +++++++++++++++++++++++++++-----------------
 2 files changed, 41 insertions(+), 24 deletions(-)

diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
index 7c2341160ea4..ab2aa3719744 100644
--- a/doc/mkeficapsule.1
+++ b/doc/mkeficapsule.1
@@ -5,7 +5,7 @@ mkeficapsule \- Generate EFI capsule file for U-Boot
 
 .SH SYNOPSIS
 .B mkeficapsule
-.RB [\fIoptions\fP] " \fIcapsule-file\fP"
+.RB [\fIoptions\fP] " \fIimage-blob\fP \fIcapsule-file\fP"
 
 .SH "DESCRIPTION"
 The
@@ -21,7 +21,7 @@ Optionally, a capsule file can be signed with a given private key.
 In this case, the update will be authenticated by verifying the signature
 before applying.
 
-\fBmkeficapsule\fP supports two different format of image files:
+\fBmkeficapsule\fP takes any type of image files, including:
 .TP
 .I raw image
 format is a single binary blob of any type of firmware.
@@ -33,15 +33,22 @@ is the same as used in the new \fIuImage\fP format and allows for
 multiple binary blobs in a single capsule file.
 This type of image file can be generated by \fBmkimage\fP.
 
+If you want to use other types than above two, you should explicitly
+specify a guid for the FMP driver.
+
 .SH "OPTIONS"
 
 .TP
-.BI "-f, --fit \fIfit-image-file\fP"
-Specify a FIT image file
+.BI "-f, --fit
+Indicate that the blob is a FIT image file
+
+.TP
+.BI "-r, --raw
+Indicate that the blob is a raw image file
 
 .TP
-.BI "-r, --raw \fIraw-image-file\fP"
-Specify a raw image file
+.BI "-g, --guid \fIguid-string\fP"
+Specify guid for image blob type
 
 .TP
 .BI "-i, --index \fIindex\fP"
diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 798706c7b5f7..8ac1811c68bd 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -14,7 +14,7 @@
 
 #include <sys/stat.h>
 #include <sys/types.h>
-
+#include <uuid/uuid.h>
 #include <linux/kconfig.h>
 #ifdef CONFIG_TOOLS_LIBCRYPTO
 #include <openssl/asn1.h>
@@ -51,14 +51,15 @@ efi_guid_t efi_guid_image_type_uboot_raw =
 efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
 
 #ifdef CONFIG_TOOLS_LIBCRYPTO
-static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
+static const char *opts_short = "frg:i:I:v:p:c:m:dh";
 #else
-static const char *opts_short = "f:r:i:I:v:h";
+static const char *opts_short = "frg:i:I:v:h";
 #endif
 
 static struct option options[] = {
-	{"fit", required_argument, NULL, 'f'},
-	{"raw", required_argument, NULL, 'r'},
+	{"fit", no_argument, NULL, 'f'},
+	{"raw", no_argument, NULL, 'r'},
+	{"guid", required_argument, NULL, 'g'},
 	{"index", required_argument, NULL, 'i'},
 	{"instance", required_argument, NULL, 'I'},
 #ifdef CONFIG_TOOLS_LIBCRYPTO
@@ -73,11 +74,12 @@ static struct option options[] = {
 
 static void print_usage(void)
 {
-	printf("Usage: %s [options] <output file>\n"
+	printf("Usage: %s [options] <image blob> <output file>\n"
 	       "Options:\n"
 
-	       "\t-f, --fit <fit image>       new FIT image file\n"
-	       "\t-r, --raw <raw image>       new raw image file\n"
+	       "\t-f, --fit                   FIT image type\n"
+	       "\t-r, --raw                   raw image type\n"
+	       "\t-g, --guid <guid string>    guid for image blob type\n"
 	       "\t-i, --index <index>         update image index\n"
 	       "\t-I, --instance <instance>   update hardware instance\n"
 #ifdef CONFIG_TOOLS_LIBCRYPTO
@@ -427,14 +429,13 @@ err_1:
 
 int main(int argc, char **argv)
 {
-	char *file;
 	efi_guid_t *guid;
+	unsigned char uuid_buf[16];
 	unsigned long index, instance;
 	uint64_t mcount;
 	char *privkey_file, *cert_file;
 	int c, idx;
 
-	file = NULL;
 	guid = NULL;
 	index = 0;
 	instance = 0;
@@ -449,21 +450,30 @@ int main(int argc, char **argv)
 
 		switch (c) {
 		case 'f':
-			if (file) {
-				printf("Image already specified\n");
+			if (guid) {
+				printf("Image type already specified\n");
 				return -1;
 			}
-			file = optarg;
 			guid = &efi_guid_image_type_uboot_fit;
 			break;
 		case 'r':
-			if (file) {
-				printf("Image already specified\n");
+			if (guid) {
+				printf("Image type already specified\n");
 				return -1;
 			}
-			file = optarg;
 			guid = &efi_guid_image_type_uboot_raw;
 			break;
+		case 'g':
+			if (guid) {
+				printf("Image type already specified\n");
+				return -1;
+			}
+			if (uuid_parse(optarg, uuid_buf)) {
+				printf("Wrong guid format\n");
+				return -1;
+			}
+			guid = (efi_guid_t *)uuid_buf;
+			break;
 		case 'i':
 			index = strtoul(optarg, NULL, 0);
 			break;
@@ -499,14 +509,14 @@ int main(int argc, char **argv)
 	}
 
 	/* check necessary parameters */
-	if ((argc != optind + 1) || !file ||
+	if ((argc != optind + 2) || !guid ||
 	    ((privkey_file && !cert_file) ||
 	     (!privkey_file && cert_file))) {
 		print_usage();
 		exit(EXIT_FAILURE);
 	}
 
-	if (create_fwbin(argv[optind], file, guid, index, instance,
+	if (create_fwbin(argv[argc - 1], argv[argc - 2], guid, index, instance,
 			 mcount, privkey_file, cert_file) < 0) {
 		printf("Creating firmware capsule failed\n");
 		exit(EXIT_FAILURE);
-- 
2.31.0


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

* [PATCH v2 9/9] test/py: efi_capsule: align with the syntax change of mkeficapsule
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (7 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 8/9] tools: mkeficapsule: allow for specifying GUID explicitly AKASHI Takahiro
@ 2021-07-27  9:10 ` AKASHI Takahiro
  2021-08-01  9:40 ` [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support Heinrich Schuchardt
  9 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-27  9:10 UTC (permalink / raw)
  To: xypron.glpk, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot,
	AKASHI Takahiro

Modify command line arguments at mkeficapsule as the syntax was
a bit modified in the previous commit.

Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
---
 test/py/tests/test_efi_capsule/conftest.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
index 35cfa5513703..86ace308b3cb 100644
--- a/test/py/tests/test_efi_capsule/conftest.py
+++ b/test/py/tests/test_efi_capsule/conftest.py
@@ -66,10 +66,10 @@ def efi_capsule_data(request, u_boot_config):
         check_call('cd %s; %s/tools/mkimage -f uboot_bin_env.its uboot_bin_env.itb' %
                    (data_dir, u_boot_config.build_dir),
                    shell=True)
-        check_call('cd %s; %s/tools/mkeficapsule --fit uboot_bin_env.itb --index 1 Test01' %
+        check_call('cd %s; %s/tools/mkeficapsule --index 1 --fit uboot_bin_env.itb Test01' %
                    (data_dir, u_boot_config.build_dir),
                    shell=True)
-        check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 Test02' %
+        check_call('cd %s; %s/tools/mkeficapsule --index 1 --raw u-boot.bin.new Test02' %
                    (data_dir, u_boot_config.build_dir),
                    shell=True)
         if capsule_auth_enabled:
@@ -78,11 +78,11 @@ def efi_capsule_data(request, u_boot_config):
                        (u_boot_config.source_dir, data_dir),
                        shell=True)
             # firmware signed with proper key
-            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER.key --certificate SIGNER.crt Test03' %
+            check_call('cd %s; %s/tools/mkeficapsule --index 1 --monotonic-count 1 --private-key SIGNER.key --certificate SIGNER.crt --raw u-boot.bin.new Test03' %
                        (data_dir, u_boot_config.build_dir),
                        shell=True)
             # firmware signed with *mal* key
-            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER2.key --certificate SIGNER2.crt Test04' %
+            check_call('cd %s; %s/tools/mkeficapsule --index 1 --monotonic-count 1 --private-key SIGNER2.key --certificate SIGNER2.crt --raw u-boot.bin.new Test04' %
                        (data_dir, u_boot_config.build_dir),
                        shell=True)
 
-- 
2.31.0


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

* Re: [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
@ 2021-07-28  8:12   ` Masami Hiramatsu
  2021-08-01  9:21   ` Heinrich Schuchardt
  1 sibling, 0 replies; 30+ messages in thread
From: Masami Hiramatsu @ 2021-07-28  8:12 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Heinrich Schuchardt, Alexander Graf, Tom Rini, Simon Glass,
	Ilias Apalodimas, Sughosh Ganu, U-Boot Mailing List

Hi,

I've tested this update on the DeveloperBox platform.

Tested-by: Masami Hiramatsu <masami.hiramatsu@linaro.org>

Thank you,

2021年7月27日(火) 18:12 AKASHI Takahiro <takahiro.akashi@linaro.org>:
>
> With this enhancement, mkeficapsule will be able to sign a capsule
> file when it is created. A signature added will be used later
> in the verification at FMP's SetImage() call.
>
> To do that, We need specify additional command parameters:
>   -monotonic-cout <count> : monotonic count
>   -private-key <private key file> : private key file
>   -certificate <certificate file> : certificate file
> Only when all of those parameters are given, a signature will be added
> to a capsule file.
>
> Users are expected to maintain and increment the monotonic count at
> every time of the update for each firmware image.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  tools/Kconfig        |   7 +
>  tools/Makefile       |   8 +-
>  tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
>  3 files changed, 316 insertions(+), 31 deletions(-)
>
> diff --git a/tools/Kconfig b/tools/Kconfig
> index d6f82cd949b5..9a37ed035311 100644
> --- a/tools/Kconfig
> +++ b/tools/Kconfig
> @@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
>           This selection does not affect target features, such as runtime FIT
>           signature verification.
>
> +config TOOLS_MKEFICAPSULE
> +       bool "Build efimkcapsule command"
> +       default y if EFI_CAPSULE_ON_DISK
> +       help
> +         This command allows users to create a UEFI capsule file and,
> +         optionally sign that file. If you want to enable UEFI capsule
> +         update feature on your target, you certainly need this.
>  endmenu
> diff --git a/tools/Makefile b/tools/Makefile
> index bae3f95c4995..af8536489652 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
>  hostprogs-$(CONFIG_ASN1_COMPILER)      += asn1_compiler
>  HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
>
> -mkeficapsule-objs      := mkeficapsule.o $(LIBFDT_OBJS)
> -hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
> +HOSTLDLIBS_mkeficapsule += -luuid
> +ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
> +HOSTLDLIBS_mkeficapsule += \
> +       $(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
> +endif
> +hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
>
>  # We build some files with extra pedantic flags to try to minimize things
>  # that won't build on some weird host compiler -- though there are lots of
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index 4995ba4e0c2a..798706c7b5f7 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -15,6 +15,16 @@
>  #include <sys/stat.h>
>  #include <sys/types.h>
>
> +#include <linux/kconfig.h>
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +#include <openssl/asn1.h>
> +#include <openssl/bio.h>
> +#include <openssl/evp.h>
> +#include <openssl/err.h>
> +#include <openssl/pem.h>
> +#include <openssl/pkcs7.h>
> +#endif
> +
>  typedef __u8 u8;
>  typedef __u16 u16;
>  typedef __u32 u32;
> @@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
>                 EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
>  efi_guid_t efi_guid_image_type_uboot_raw =
>                 EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
> +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> +
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
> +#else
> +static const char *opts_short = "f:r:i:I:v:h";
> +#endif
>
>  static struct option options[] = {
>         {"fit", required_argument, NULL, 'f'},
>         {"raw", required_argument, NULL, 'r'},
>         {"index", required_argument, NULL, 'i'},
>         {"instance", required_argument, NULL, 'I'},
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +       {"private-key", required_argument, NULL, 'p'},
> +       {"certificate", required_argument, NULL, 'c'},
> +       {"monotonic-count", required_argument, NULL, 'm'},
> +       {"dump-sig", no_argument, NULL, 'd'},
> +#endif
>         {"help", no_argument, NULL, 'h'},
>         {NULL, 0, NULL, 0},
>  };
> @@ -57,16 +80,195 @@ static void print_usage(void)
>                "\t-r, --raw <raw image>       new raw image file\n"
>                "\t-i, --index <index>         update image index\n"
>                "\t-I, --instance <instance>   update hardware instance\n"
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +              "\t-p, --private-key <privkey file>  private key file\n"
> +              "\t-c, --certificate <cert file>     signer's certificate file\n"
> +              "\t-m, --monotonic-count <count>     monotonic count\n"
> +              "\t-d, --dump_sig              dump signature (*.p7)\n"
> +#endif
>                "\t-h, --help                  print a help message\n",
>                tool_name);
>  }
>
> +struct auth_context {
> +       char *key_file;
> +       char *cert_file;
> +       u8 *image_data;
> +       size_t image_size;
> +       struct efi_firmware_image_authentication auth;
> +       u8 *sig_data;
> +       size_t sig_size;
> +};
> +
> +static int dump_sig;
> +
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +static EVP_PKEY *fileio_read_pkey(const char *filename)
> +{
> +       EVP_PKEY *key = NULL;
> +       BIO *bio;
> +
> +       bio = BIO_new_file(filename, "r");
> +       if (!bio)
> +               goto out;
> +
> +       key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
> +
> +out:
> +       BIO_free_all(bio);
> +       if (!key) {
> +               printf("Can't load key from file '%s'\n", filename);
> +               ERR_print_errors_fp(stderr);
> +       }
> +
> +       return key;
> +}
> +
> +static X509 *fileio_read_cert(const char *filename)
> +{
> +       X509 *cert = NULL;
> +       BIO *bio;
> +
> +       bio = BIO_new_file(filename, "r");
> +       if (!bio)
> +               goto out;
> +
> +       cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
> +
> +out:
> +       BIO_free_all(bio);
> +       if (!cert) {
> +               printf("Can't load certificate from file '%s'\n", filename);
> +               ERR_print_errors_fp(stderr);
> +       }
> +
> +       return cert;
> +}
> +
> +static int create_auth_data(struct auth_context *ctx)
> +{
> +       EVP_PKEY *key = NULL;
> +       X509 *cert = NULL;
> +       BIO *data_bio = NULL;
> +       const EVP_MD *md;
> +       PKCS7 *p7;
> +       int flags, ret = -1;
> +
> +       OpenSSL_add_all_digests();
> +       OpenSSL_add_all_ciphers();
> +       ERR_load_crypto_strings();
> +
> +       key = fileio_read_pkey(ctx->key_file);
> +       if (!key)
> +               goto err;
> +       cert = fileio_read_cert(ctx->cert_file);
> +       if (!cert)
> +               goto err;
> +
> +       /*
> +        * create a BIO, containing:
> +        *  * firmware image
> +        *  * monotonic count
> +        * in this order!
> +        * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
> +        */
> +       data_bio = BIO_new(BIO_s_mem());
> +       BIO_write(data_bio, ctx->image_data, ctx->image_size);
> +       BIO_write(data_bio, &ctx->auth.monotonic_count,
> +                 sizeof(ctx->auth.monotonic_count));
> +
> +       md = EVP_get_digestbyname("SHA256");
> +       if (!md)
> +               goto err;
> +
> +       /* create signature */
> +       /* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
> +       flags = PKCS7_BINARY | PKCS7_DETACHED;
> +       p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
> +       if (!p7)
> +               goto err;
> +       if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
> +               goto err;
> +       if (!PKCS7_final(p7, data_bio, flags))
> +               goto err;
> +
> +       /* convert pkcs7 into DER */
> +       ctx->sig_data = NULL;
> +       ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
> +                                     ASN1_ITEM_rptr(PKCS7));
> +       if (!ctx->sig_size)
> +               goto err;
> +
> +       /* fill auth_info */
> +       ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
> +                                               + ctx->sig_size;
> +       ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> +       ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> +       memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
> +              sizeof(efi_guid_cert_type_pkcs7));
> +
> +       ret = 0;
> +err:
> +       BIO_free_all(data_bio);
> +       EVP_PKEY_free(key);
> +       X509_free(cert);
> +
> +       return ret;
> +}
> +
> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> +{
> +       char *sig_path;
> +       FILE *f;
> +       size_t size;
> +       int ret = -1;
> +
> +       sig_path = malloc(strlen(path) + 3 + 1);
> +       if (!sig_path)
> +               return ret;
> +
> +       sprintf(sig_path, "%s.p7", path);
> +       f = fopen(sig_path, "w");
> +       if (!f)
> +               goto err;
> +
> +       size = fwrite(signature, 1, sig_size, f);
> +       if (size == sig_size)
> +               ret = 0;
> +
> +       fclose(f);
> +err:
> +       free(sig_path);
> +       return ret;
> +}
> +
> +static void free_sig_data(struct auth_context *ctx)
> +{
> +       if (ctx->sig_size)
> +               OPENSSL_free(ctx->sig_data);
> +}
> +#else
> +static int create_auth_data(struct auth_context *ctx)
> +{
> +       return 0;
> +}
> +
> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> +{
> +       return 0;
> +}
> +
> +static void free_sig_data(struct auth_context *ctx) {}
> +#endif
> +
>  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> -                       unsigned long index, unsigned long instance)
> +                       unsigned long index, unsigned long instance,
> +                       uint64_t mcount, char *privkey_file, char *cert_file)
>  {
>         struct efi_capsule_header header;
>         struct efi_firmware_management_capsule_header capsule;
>         struct efi_firmware_management_capsule_image_header image;
> +       struct auth_context auth_context;
>         FILE *f, *g;
>         struct stat bin_stat;
>         u8 *data;
> @@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>         printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
>         printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
>  #endif
> +       auth_context.sig_size = 0;
>
>         g = fopen(bin, "r");
>         if (!g) {
> @@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>                 printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
>                 goto err_1;
>         }
> -       f = fopen(path, "w");
> -       if (!f) {
> -               printf("cannot open %s\n", path);
> +
> +       size = fread(data, 1, bin_stat.st_size, g);
> +       if (size < bin_stat.st_size) {
> +               printf("read failed (%zx)\n", size);
>                 goto err_2;
>         }
> +
> +       /* first, calculate signature to determine its size */
> +       if (privkey_file && cert_file) {
> +               auth_context.key_file = privkey_file;
> +               auth_context.cert_file = cert_file;
> +               auth_context.auth.monotonic_count = mcount;
> +               auth_context.image_data = data;
> +               auth_context.image_size = bin_stat.st_size;
> +
> +               if (create_auth_data(&auth_context)) {
> +                       printf("Signing firmware image failed\n");
> +                       goto err_3;
> +               }
> +
> +               if (dump_sig &&
> +                   dump_signature(path, auth_context.sig_data,
> +                                  auth_context.sig_size)) {
> +                       printf("Creating signature file failed\n");
> +                       goto err_3;
> +               }
> +       }
> +
>         header.capsule_guid = efi_guid_fm_capsule;
>         header.header_size = sizeof(header);
>         /* TODO: The current implementation ignores flags */
> @@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>                                         + sizeof(capsule) + sizeof(u64)
>                                         + sizeof(image)
>                                         + bin_stat.st_size;
> +       if (auth_context.sig_size)
> +               header.capsule_image_size += sizeof(auth_context.auth)
> +                               + auth_context.sig_size;
> +
> +       f = fopen(path, "w");
> +       if (!f) {
> +               printf("cannot open %s\n", path);
> +               goto err_3;
> +       }
>
>         size = fwrite(&header, 1, sizeof(header), f);
>         if (size < sizeof(header)) {
>                 printf("write failed (%zx)\n", size);
> -               goto err_3;
> +               goto err_4;
>         }
>
>         capsule.version = 0x00000001;
> @@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>         size = fwrite(&capsule, 1, sizeof(capsule), f);
>         if (size < (sizeof(capsule))) {
>                 printf("write failed (%zx)\n", size);
> -               goto err_3;
> +               goto err_4;
>         }
>         offset = sizeof(capsule) + sizeof(u64);
>         size = fwrite(&offset, 1, sizeof(offset), f);
>         if (size < sizeof(offset)) {
>                 printf("write failed (%zx)\n", size);
> -               goto err_3;
> +               goto err_4;
>         }
>
>         image.version = 0x00000003;
> @@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>         image.reserved[1] = 0;
>         image.reserved[2] = 0;
>         image.update_image_size = bin_stat.st_size;
> +       if (auth_context.sig_size)
> +               image.update_image_size += sizeof(auth_context.auth)
> +                               + auth_context.sig_size;
>         image.update_vendor_code_size = 0; /* none */
>         image.update_hardware_instance = instance;
>         image.image_capsule_support = 0;
> +       if (auth_context.sig_size)
> +               image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
>
>         size = fwrite(&image, 1, sizeof(image), f);
>         if (size < sizeof(image)) {
>                 printf("write failed (%zx)\n", size);
> -               goto err_3;
> +               goto err_4;
>         }
> -       size = fread(data, 1, bin_stat.st_size, g);
> -       if (size < bin_stat.st_size) {
> -               printf("read failed (%zx)\n", size);
> -               goto err_3;
> +
> +       if (auth_context.sig_size) {
> +               size = fwrite(&auth_context.auth, 1,
> +                             sizeof(auth_context.auth), f);
> +               if (size < sizeof(auth_context.auth)) {
> +                       printf("write failed (%zx)\n", size);
> +                       goto err_4;
> +               }
> +               size = fwrite(auth_context.sig_data, 1,
> +                             auth_context.sig_size, f);
> +               if (size < auth_context.sig_size) {
> +                       printf("write failed (%zx)\n", size);
> +                       goto err_4;
> +               }
>         }
> +
>         size = fwrite(data, 1, bin_stat.st_size, f);
>         if (size < bin_stat.st_size) {
>                 printf("write failed (%zx)\n", size);
> -               goto err_3;
> +               goto err_4;
>         }
>
>         fclose(f);
>         fclose(g);
>         free(data);
> +       free_sig_data(&auth_context);
>
>         return 0;
>
> -err_3:
> +err_4:
>         fclose(f);
> +err_3:
> +       free_sig_data(&auth_context);
>  err_2:
>         free(data);
>  err_1:
> @@ -171,23 +425,25 @@ err_1:
>         return -1;
>  }
>
> -/*
> - * Usage:
> - *   $ mkeficapsule -f <firmware binary> <output file>
> - */
>  int main(int argc, char **argv)
>  {
>         char *file;
>         efi_guid_t *guid;
>         unsigned long index, instance;
> +       uint64_t mcount;
> +       char *privkey_file, *cert_file;
>         int c, idx;
>
>         file = NULL;
>         guid = NULL;
>         index = 0;
>         instance = 0;
> +       mcount = 0;
> +       privkey_file = NULL;
> +       cert_file = NULL;
> +       dump_sig = 0;
>         for (;;) {
> -               c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
> +               c = getopt_long(argc, argv, opts_short, options, &idx);
>                 if (c == -1)
>                         break;
>
> @@ -214,26 +470,44 @@ int main(int argc, char **argv)
>                 case 'I':
>                         instance = strtoul(optarg, NULL, 0);
>                         break;
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +               case 'p':
> +                       if (privkey_file) {
> +                               printf("Private Key already specified\n");
> +                               return -1;
> +                       }
> +                       privkey_file = optarg;
> +                       break;
> +               case 'c':
> +                       if (cert_file) {
> +                               printf("Certificate file already specified\n");
> +                               return -1;
> +                       }
> +                       cert_file = optarg;
> +                       break;
> +               case 'm':
> +                       mcount = strtoul(optarg, NULL, 0);
> +                       break;
> +               case 'd':
> +                       dump_sig = 1;
> +                       break;
> +#endif /* CONFIG_TOOLS_LIBCRYPTO */
>                 case 'h':
>                         print_usage();
>                         return 0;
>                 }
>         }
>
> -       /* need an output file */
> -       if (argc != optind + 1) {
> +       /* check necessary parameters */
> +       if ((argc != optind + 1) || !file ||
> +           ((privkey_file && !cert_file) ||
> +            (!privkey_file && cert_file))) {
>                 print_usage();
>                 exit(EXIT_FAILURE);
>         }
>
> -       /* need a fit image file or raw image file */
> -       if (!file) {
> -               print_usage();
> -               exit(EXIT_SUCCESS);
> -       }
> -
> -       if (create_fwbin(argv[optind], file, guid, index, instance)
> -                       < 0) {
> +       if (create_fwbin(argv[optind], file, guid, index, instance,
> +                        mcount, privkey_file, cert_file) < 0) {
>                 printf("Creating firmware capsule failed\n");
>                 exit(EXIT_FAILURE);
>         }
> --
> 2.31.0
>


-- 
Masami Hiramatsu

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-07-27  9:10 ` [PATCH v2 6/9] sandbox: add config for efi capsule " AKASHI Takahiro
@ 2021-07-28 20:21   ` Heinrich Schuchardt
  2021-07-29  0:39     ` AKASHI Takahiro
  2021-07-31 16:59   ` Simon Glass
  1 sibling, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-07-28 20:21 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot



On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> This new configuration, which was derived from sandbox_defconfig, will be
> used solely to run efi capsule authentication test as the test requires
> a public key (esl file) to be embedded in U-Boot binary.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
>   1 file changed, 307 insertions(+)
>   create mode 100644 configs/sandbox_capsule_auth_defconfig
>
> diff --git a/configs/sandbox_capsule_auth_defconfig b/configs/sandbox_capsule_auth_defconfig
> new file mode 100644
> index 000000000000..8e0ffb1a6995
> --- /dev/null
> +++ b/configs/sandbox_capsule_auth_defconfig
> @@ -0,0 +1,307 @@
> +CONFIG_SYS_TEXT_BASE=0
> +CONFIG_NR_DRAM_BANKS=1
> +CONFIG_SYS_MEMTEST_START=0x00100000
> +CONFIG_SYS_MEMTEST_END=0x00101000
> +CONFIG_ENV_SIZE=0x2000
> +CONFIG_DEFAULT_DEVICE_TREE="sandbox"
> +CONFIG_PRE_CON_BUF_ADDR=0xf0000
> +CONFIG_BOOTSTAGE_STASH_ADDR=0x0
> +CONFIG_DEBUG_UART=y
> +CONFIG_DISTRO_DEFAULTS=y
> +CONFIG_FIT=y
> +CONFIG_FIT_SIGNATURE=y
> +CONFIG_FIT_RSASSA_PSS=y
> +CONFIG_FIT_CIPHER=y
> +CONFIG_FIT_VERBOSE=y
> +CONFIG_BOOTSTAGE=y
> +CONFIG_BOOTSTAGE_REPORT=y
> +CONFIG_BOOTSTAGE_FDT=y
> +CONFIG_BOOTSTAGE_STASH=y
> +CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
> +CONFIG_CONSOLE_RECORD=y
> +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
> +CONFIG_PRE_CONSOLE_BUFFER=y
> +CONFIG_LOG=y
> +CONFIG_DISPLAY_BOARDINFO_LATE=y
> +CONFIG_MISC_INIT_F=y
> +CONFIG_STACKPROTECTOR=y
> +CONFIG_ANDROID_AB=y
> +CONFIG_CMD_CPU=y
> +CONFIG_CMD_LICENSE=y
> +CONFIG_CMD_BOOTZ=y
> +CONFIG_CMD_BOOTEFI_HELLO=y
> +CONFIG_CMD_ABOOTIMG=y
> +# CONFIG_CMD_ELF is not set
> +CONFIG_CMD_ASKENV=y
> +CONFIG_CMD_GREPENV=y
> +CONFIG_CMD_ERASEENV=y
> +CONFIG_CMD_ENV_CALLBACK=y
> +CONFIG_CMD_ENV_FLAGS=y
> +CONFIG_CMD_NVEDIT_EFI=y
> +CONFIG_CMD_NVEDIT_INFO=y
> +CONFIG_CMD_NVEDIT_LOAD=y
> +CONFIG_CMD_NVEDIT_SELECT=y
> +CONFIG_LOOPW=y
> +CONFIG_CMD_MD5SUM=y
> +CONFIG_CMD_MEMINFO=y
> +CONFIG_CMD_MEM_SEARCH=y
> +CONFIG_CMD_MX_CYCLIC=y
> +CONFIG_CMD_MEMTEST=y
> +CONFIG_CMD_BIND=y
> +CONFIG_CMD_DEMO=y
> +CONFIG_CMD_GPIO=y
> +CONFIG_CMD_PWM=y
> +CONFIG_CMD_GPT=y
> +CONFIG_CMD_GPT_RENAME=y
> +CONFIG_CMD_IDE=y
> +CONFIG_CMD_I2C=y
> +CONFIG_CMD_LSBLK=y
> +CONFIG_CMD_MUX=y
> +CONFIG_CMD_OSD=y
> +CONFIG_CMD_PCI=y
> +CONFIG_CMD_READ=y
> +CONFIG_CMD_REMOTEPROC=y
> +CONFIG_CMD_SPI=y
> +CONFIG_CMD_USB=y
> +CONFIG_CMD_AXI=y
> +CONFIG_CMD_AB_SELECT=y
> +CONFIG_BOOTP_DNS2=y
> +CONFIG_CMD_PCAP=y
> +CONFIG_CMD_TFTPPUT=y
> +CONFIG_CMD_TFTPSRV=y
> +CONFIG_CMD_RARP=y
> +CONFIG_CMD_CDP=y
> +CONFIG_CMD_SNTP=y
> +CONFIG_CMD_DNS=y
> +CONFIG_CMD_LINK_LOCAL=y
> +CONFIG_CMD_ETHSW=y
> +CONFIG_CMD_BMP=y
> +CONFIG_CMD_BOOTCOUNT=y
> +CONFIG_CMD_EFIDEBUG=y
> +CONFIG_CMD_RTC=y
> +CONFIG_CMD_TIME=y
> +CONFIG_CMD_TIMER=y
> +CONFIG_CMD_SOUND=y
> +CONFIG_CMD_QFW=y
> +CONFIG_CMD_PSTORE=y
> +CONFIG_CMD_PSTORE_MEM_ADDR=0x3000000
> +CONFIG_CMD_BOOTSTAGE=y
> +CONFIG_CMD_PMIC=y
> +CONFIG_CMD_REGULATOR=y
> +CONFIG_CMD_AES=y
> +CONFIG_CMD_TPM=y
> +CONFIG_CMD_TPM_TEST=y
> +CONFIG_CMD_BTRFS=y
> +CONFIG_CMD_CBFS=y
> +CONFIG_CMD_CRAMFS=y
> +CONFIG_CMD_EXT4_WRITE=y
> +CONFIG_CMD_SQUASHFS=y
> +CONFIG_CMD_MTDPARTS=y
> +CONFIG_CMD_STACKPROTECTOR_TEST=y
> +CONFIG_MAC_PARTITION=y
> +CONFIG_AMIGA_PARTITION=y
> +CONFIG_OF_CONTROL=y
> +CONFIG_OF_LIVE=y
> +CONFIG_OF_HOSTFILE=y
> +CONFIG_ENV_IS_NOWHERE=y
> +CONFIG_ENV_IS_IN_EXT4=y
> +CONFIG_ENV_EXT4_INTERFACE="host"
> +CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
> +CONFIG_ENV_IMPORT_FDT=y
> +CONFIG_BOOTP_SEND_HOSTNAME=y
> +CONFIG_NETCONSOLE=y
> +CONFIG_IP_DEFRAG=y
> +CONFIG_DM_DMA=y
> +CONFIG_REGMAP=y
> +CONFIG_SYSCON=y
> +CONFIG_DEVRES=y
> +CONFIG_DEBUG_DEVRES=y
> +CONFIG_SIMPLE_PM_BUS=y
> +CONFIG_ADC=y
> +CONFIG_ADC_SANDBOX=y
> +CONFIG_AXI=y
> +CONFIG_AXI_SANDBOX=y
> +CONFIG_BOOTCOUNT_LIMIT=y
> +CONFIG_DM_BOOTCOUNT=y
> +CONFIG_DM_BOOTCOUNT_RTC=y
> +CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y
> +CONFIG_BUTTON=y
> +CONFIG_BUTTON_ADC=y
> +CONFIG_BUTTON_GPIO=y
> +CONFIG_CLK=y
> +CONFIG_CLK_COMPOSITE_CCF=y
> +CONFIG_CLK_SCMI=y
> +CONFIG_CLK_K210=y
> +CONFIG_CLK_K210_SET_RATE=y
> +CONFIG_SANDBOX_CLK_CCF=y
> +CONFIG_CPU=y
> +CONFIG_DM_DEMO=y
> +CONFIG_DM_DEMO_SIMPLE=y
> +CONFIG_DM_DEMO_SHAPE=y
> +CONFIG_DFU_SF=y
> +CONFIG_DMA=y
> +CONFIG_DMA_CHANNELS=y
> +CONFIG_SANDBOX_DMA=y
> +CONFIG_FASTBOOT_FLASH=y
> +CONFIG_FASTBOOT_FLASH_MMC_DEV=0
> +CONFIG_GPIO_HOG=y
> +CONFIG_DM_GPIO_LOOKUP_LABEL=y
> +CONFIG_PM8916_GPIO=y
> +CONFIG_SANDBOX_GPIO=y
> +CONFIG_DM_HWSPINLOCK=y
> +CONFIG_HWSPINLOCK_SANDBOX=y
> +CONFIG_I2C_CROS_EC_TUNNEL=y
> +CONFIG_I2C_CROS_EC_LDO=y
> +CONFIG_DM_I2C_GPIO=y
> +CONFIG_SYS_I2C_SANDBOX=y
> +CONFIG_I2C_MUX=y
> +CONFIG_SPL_I2C_MUX=y
> +CONFIG_I2C_ARB_GPIO_CHALLENGE=y
> +CONFIG_CROS_EC_KEYB=y
> +CONFIG_I8042_KEYB=y
> +CONFIG_LED=y
> +CONFIG_LED_BLINK=y
> +CONFIG_LED_GPIO=y
> +CONFIG_DM_MAILBOX=y
> +CONFIG_SANDBOX_MBOX=y
> +CONFIG_MISC=y
> +CONFIG_CROS_EC=y
> +CONFIG_CROS_EC_I2C=y
> +CONFIG_CROS_EC_LPC=y
> +CONFIG_CROS_EC_SANDBOX=y
> +CONFIG_CROS_EC_SPI=y
> +CONFIG_P2SB=y
> +CONFIG_PWRSEQ=y
> +CONFIG_SPL_PWRSEQ=y
> +CONFIG_I2C_EEPROM=y
> +CONFIG_MMC_PCI=y
> +CONFIG_MMC_SANDBOX=y
> +CONFIG_MMC_SDHCI=y
> +CONFIG_MTD=y
> +CONFIG_SPI_FLASH_SANDBOX=y
> +CONFIG_SPI_FLASH_ATMEL=y
> +CONFIG_SPI_FLASH_EON=y
> +CONFIG_SPI_FLASH_GIGADEVICE=y
> +CONFIG_SPI_FLASH_MACRONIX=y
> +CONFIG_SPI_FLASH_SPANSION=y
> +CONFIG_SPI_FLASH_STMICRO=y
> +CONFIG_SPI_FLASH_SST=y
> +CONFIG_SPI_FLASH_WINBOND=y
> +CONFIG_MULTIPLEXER=y
> +CONFIG_MUX_MMIO=y
> +CONFIG_DM_ETH=y
> +CONFIG_NVME=y
> +CONFIG_PCI=y
> +CONFIG_DM_PCI=y
> +CONFIG_PCI_REGION_MULTI_ENTRY=y
> +CONFIG_PCI_SANDBOX=y
> +CONFIG_PHY=y
> +CONFIG_PHY_SANDBOX=y
> +CONFIG_PINCTRL=y
> +CONFIG_PINCONF=y
> +CONFIG_PINCTRL_SANDBOX=y
> +CONFIG_PINCTRL_SINGLE=y
> +CONFIG_POWER_DOMAIN=y
> +CONFIG_SANDBOX_POWER_DOMAIN=y
> +CONFIG_DM_PMIC=y
> +CONFIG_PMIC_ACT8846=y
> +CONFIG_DM_PMIC_PFUZE100=y
> +CONFIG_DM_PMIC_MAX77686=y
> +CONFIG_DM_PMIC_MC34708=y
> +CONFIG_PMIC_PM8916=y
> +CONFIG_PMIC_RK8XX=y
> +CONFIG_PMIC_S2MPS11=y
> +CONFIG_DM_PMIC_SANDBOX=y
> +CONFIG_PMIC_S5M8767=y
> +CONFIG_PMIC_TPS65090=y
> +CONFIG_DM_REGULATOR=y
> +CONFIG_REGULATOR_ACT8846=y
> +CONFIG_DM_REGULATOR_PFUZE100=y
> +CONFIG_DM_REGULATOR_MAX77686=y
> +CONFIG_DM_REGULATOR_FIXED=y
> +CONFIG_REGULATOR_RK8XX=y
> +CONFIG_REGULATOR_S5M8767=y
> +CONFIG_DM_REGULATOR_SANDBOX=y
> +CONFIG_REGULATOR_TPS65090=y
> +CONFIG_DM_REGULATOR_SCMI=y
> +CONFIG_DM_PWM=y
> +CONFIG_PWM_CROS_EC=y
> +CONFIG_PWM_SANDBOX=y
> +CONFIG_RAM=y
> +CONFIG_REMOTEPROC_SANDBOX=y
> +CONFIG_DM_RESET=y
> +CONFIG_SANDBOX_RESET=y
> +CONFIG_RESET_SYSCON=y
> +CONFIG_RESET_SCMI=y
> +CONFIG_DM_RNG=y
> +CONFIG_DM_RTC=y
> +CONFIG_RTC_RV8803=y
> +CONFIG_SANDBOX_SERIAL=y
> +CONFIG_SMEM=y
> +CONFIG_SANDBOX_SMEM=y
> +CONFIG_SOUND=y
> +CONFIG_SOUND_DA7219=y
> +CONFIG_SOUND_MAX98357A=y
> +CONFIG_SOUND_SANDBOX=y
> +CONFIG_SOC_DEVICE=y
> +CONFIG_SANDBOX_SPI=y
> +CONFIG_SPMI=y
> +CONFIG_SPMI_SANDBOX=y
> +CONFIG_SYSINFO=y
> +CONFIG_SYSINFO_SANDBOX=y
> +CONFIG_SYSINFO_GPIO=y
> +CONFIG_SYSRESET=y
> +CONFIG_TIMER=y
> +CONFIG_TIMER_EARLY=y
> +CONFIG_SANDBOX_TIMER=y
> +CONFIG_USB=y
> +CONFIG_DM_USB=y
> +CONFIG_USB_EMUL=y
> +CONFIG_USB_KEYBOARD=y
> +CONFIG_DM_VIDEO=y
> +CONFIG_VIDEO_COPY=y
> +CONFIG_CONSOLE_ROTATION=y
> +CONFIG_CONSOLE_TRUETYPE=y
> +CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
> +CONFIG_VIDEO_SANDBOX_SDL=y
> +CONFIG_VIDEO_DSI_HOST_SANDBOX=y
> +CONFIG_OSD=y
> +CONFIG_SANDBOX_OSD=y
> +CONFIG_SPLASH_SCREEN_ALIGN=y
> +CONFIG_VIDEO_BMP_RLE8=y
> +CONFIG_W1=y
> +CONFIG_W1_GPIO=y
> +CONFIG_W1_EEPROM=y
> +CONFIG_W1_EEPROM_SANDBOX=y
> +CONFIG_WDT=y
> +CONFIG_WDT_SANDBOX=y
> +CONFIG_FS_CBFS=y
> +CONFIG_FS_CRAMFS=y
> +CONFIG_CMD_DHRYSTONE=y
> +CONFIG_TPM=y
> +CONFIG_LZ4=y
> +CONFIG_ERRNO_STR=y
> +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
> +CONFIG_EFI_CAPSULE_ON_DISK=y
> +CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
> +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> +CONFIG_EFI_CAPSULE_AUTHENTICATE=y
> +CONFIG_EFI_CAPSULE_KEY_PATH="../test/py/tests/test_efi_capsule/SIGNER.esl"

Is this path relative to the build directory?

Will building fail if the build directory is not a direct subdirectory
of the source directory?

Best regards

Heinrich

> +CONFIG_EFI_SECURE_BOOT=y
> +CONFIG_TEST_FDTDEC=y
> +CONFIG_CRYPT_PW=y
> +CONFIG_CRYPT_PW_SHA256=y
> +CONFIG_CRYPT_PW_SHA512=y
> +CONFIG_AUTOBOOT_KEYED=y
> +CONFIG_AUTOBOOT_PROMPT="Enter password \"a\" in %d seconds to stop autoboot\n"
> +CONFIG_AUTOBOOT_ENCRYPTION=y
> +CONFIG_AUTOBOOT_STOP_STR_ENABLE=y
> +CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9"
> +CONFIG_AUTOBOOT_NEVER_TIMEOUT=y
> +CONFIG_AUTOBOOT_SHA256_FALLBACK=y
> +CONFIG_UNIT_TEST=y
> +CONFIG_UT_TIME=y
> +CONFIG_UT_DM=y
> +CONFIG_DM_REBOOT_MODE=y
> +CONFIG_DM_REBOOT_MODE_GPIO=y
> +CONFIG_DM_REBOOT_MODE_RTC=y
>

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-07-28 20:21   ` Heinrich Schuchardt
@ 2021-07-29  0:39     ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-07-29  0:39 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

On Wed, Jul 28, 2021 at 10:21:56PM +0200, Heinrich Schuchardt wrote:
> 
> 
> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > This new configuration, which was derived from sandbox_defconfig, will be
> > used solely to run efi capsule authentication test as the test requires
> > a public key (esl file) to be embedded in U-Boot binary.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >   configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
> >   1 file changed, 307 insertions(+)
> >   create mode 100644 configs/sandbox_capsule_auth_defconfig
> > 
> > diff --git a/configs/sandbox_capsule_auth_defconfig b/configs/sandbox_capsule_auth_defconfig
> > new file mode 100644
> > index 000000000000..8e0ffb1a6995
> > --- /dev/null
> > +++ b/configs/sandbox_capsule_auth_defconfig
> > @@ -0,0 +1,307 @@
> > +CONFIG_SYS_TEXT_BASE=0
> > +CONFIG_NR_DRAM_BANKS=1
> > +CONFIG_SYS_MEMTEST_START=0x00100000
> > +CONFIG_SYS_MEMTEST_END=0x00101000
> > +CONFIG_ENV_SIZE=0x2000
> > +CONFIG_DEFAULT_DEVICE_TREE="sandbox"
> > +CONFIG_PRE_CON_BUF_ADDR=0xf0000
> > +CONFIG_BOOTSTAGE_STASH_ADDR=0x0
> > +CONFIG_DEBUG_UART=y
> > +CONFIG_DISTRO_DEFAULTS=y
> > +CONFIG_FIT=y
> > +CONFIG_FIT_SIGNATURE=y
> > +CONFIG_FIT_RSASSA_PSS=y
> > +CONFIG_FIT_CIPHER=y
> > +CONFIG_FIT_VERBOSE=y
> > +CONFIG_BOOTSTAGE=y
> > +CONFIG_BOOTSTAGE_REPORT=y
> > +CONFIG_BOOTSTAGE_FDT=y
> > +CONFIG_BOOTSTAGE_STASH=y
> > +CONFIG_BOOTSTAGE_STASH_SIZE=0x4096
> > +CONFIG_CONSOLE_RECORD=y
> > +CONFIG_CONSOLE_RECORD_OUT_SIZE=0x1000
> > +CONFIG_PRE_CONSOLE_BUFFER=y
> > +CONFIG_LOG=y
> > +CONFIG_DISPLAY_BOARDINFO_LATE=y
> > +CONFIG_MISC_INIT_F=y
> > +CONFIG_STACKPROTECTOR=y
> > +CONFIG_ANDROID_AB=y
> > +CONFIG_CMD_CPU=y
> > +CONFIG_CMD_LICENSE=y
> > +CONFIG_CMD_BOOTZ=y
> > +CONFIG_CMD_BOOTEFI_HELLO=y
> > +CONFIG_CMD_ABOOTIMG=y
> > +# CONFIG_CMD_ELF is not set
> > +CONFIG_CMD_ASKENV=y
> > +CONFIG_CMD_GREPENV=y
> > +CONFIG_CMD_ERASEENV=y
> > +CONFIG_CMD_ENV_CALLBACK=y
> > +CONFIG_CMD_ENV_FLAGS=y
> > +CONFIG_CMD_NVEDIT_EFI=y
> > +CONFIG_CMD_NVEDIT_INFO=y
> > +CONFIG_CMD_NVEDIT_LOAD=y
> > +CONFIG_CMD_NVEDIT_SELECT=y
> > +CONFIG_LOOPW=y
> > +CONFIG_CMD_MD5SUM=y
> > +CONFIG_CMD_MEMINFO=y
> > +CONFIG_CMD_MEM_SEARCH=y
> > +CONFIG_CMD_MX_CYCLIC=y
> > +CONFIG_CMD_MEMTEST=y
> > +CONFIG_CMD_BIND=y
> > +CONFIG_CMD_DEMO=y
> > +CONFIG_CMD_GPIO=y
> > +CONFIG_CMD_PWM=y
> > +CONFIG_CMD_GPT=y
> > +CONFIG_CMD_GPT_RENAME=y
> > +CONFIG_CMD_IDE=y
> > +CONFIG_CMD_I2C=y
> > +CONFIG_CMD_LSBLK=y
> > +CONFIG_CMD_MUX=y
> > +CONFIG_CMD_OSD=y
> > +CONFIG_CMD_PCI=y
> > +CONFIG_CMD_READ=y
> > +CONFIG_CMD_REMOTEPROC=y
> > +CONFIG_CMD_SPI=y
> > +CONFIG_CMD_USB=y
> > +CONFIG_CMD_AXI=y
> > +CONFIG_CMD_AB_SELECT=y
> > +CONFIG_BOOTP_DNS2=y
> > +CONFIG_CMD_PCAP=y
> > +CONFIG_CMD_TFTPPUT=y
> > +CONFIG_CMD_TFTPSRV=y
> > +CONFIG_CMD_RARP=y
> > +CONFIG_CMD_CDP=y
> > +CONFIG_CMD_SNTP=y
> > +CONFIG_CMD_DNS=y
> > +CONFIG_CMD_LINK_LOCAL=y
> > +CONFIG_CMD_ETHSW=y
> > +CONFIG_CMD_BMP=y
> > +CONFIG_CMD_BOOTCOUNT=y
> > +CONFIG_CMD_EFIDEBUG=y
> > +CONFIG_CMD_RTC=y
> > +CONFIG_CMD_TIME=y
> > +CONFIG_CMD_TIMER=y
> > +CONFIG_CMD_SOUND=y
> > +CONFIG_CMD_QFW=y
> > +CONFIG_CMD_PSTORE=y
> > +CONFIG_CMD_PSTORE_MEM_ADDR=0x3000000
> > +CONFIG_CMD_BOOTSTAGE=y
> > +CONFIG_CMD_PMIC=y
> > +CONFIG_CMD_REGULATOR=y
> > +CONFIG_CMD_AES=y
> > +CONFIG_CMD_TPM=y
> > +CONFIG_CMD_TPM_TEST=y
> > +CONFIG_CMD_BTRFS=y
> > +CONFIG_CMD_CBFS=y
> > +CONFIG_CMD_CRAMFS=y
> > +CONFIG_CMD_EXT4_WRITE=y
> > +CONFIG_CMD_SQUASHFS=y
> > +CONFIG_CMD_MTDPARTS=y
> > +CONFIG_CMD_STACKPROTECTOR_TEST=y
> > +CONFIG_MAC_PARTITION=y
> > +CONFIG_AMIGA_PARTITION=y
> > +CONFIG_OF_CONTROL=y
> > +CONFIG_OF_LIVE=y
> > +CONFIG_OF_HOSTFILE=y
> > +CONFIG_ENV_IS_NOWHERE=y
> > +CONFIG_ENV_IS_IN_EXT4=y
> > +CONFIG_ENV_EXT4_INTERFACE="host"
> > +CONFIG_ENV_EXT4_DEVICE_AND_PART="0:0"
> > +CONFIG_ENV_IMPORT_FDT=y
> > +CONFIG_BOOTP_SEND_HOSTNAME=y
> > +CONFIG_NETCONSOLE=y
> > +CONFIG_IP_DEFRAG=y
> > +CONFIG_DM_DMA=y
> > +CONFIG_REGMAP=y
> > +CONFIG_SYSCON=y
> > +CONFIG_DEVRES=y
> > +CONFIG_DEBUG_DEVRES=y
> > +CONFIG_SIMPLE_PM_BUS=y
> > +CONFIG_ADC=y
> > +CONFIG_ADC_SANDBOX=y
> > +CONFIG_AXI=y
> > +CONFIG_AXI_SANDBOX=y
> > +CONFIG_BOOTCOUNT_LIMIT=y
> > +CONFIG_DM_BOOTCOUNT=y
> > +CONFIG_DM_BOOTCOUNT_RTC=y
> > +CONFIG_DM_BOOTCOUNT_I2C_EEPROM=y
> > +CONFIG_BUTTON=y
> > +CONFIG_BUTTON_ADC=y
> > +CONFIG_BUTTON_GPIO=y
> > +CONFIG_CLK=y
> > +CONFIG_CLK_COMPOSITE_CCF=y
> > +CONFIG_CLK_SCMI=y
> > +CONFIG_CLK_K210=y
> > +CONFIG_CLK_K210_SET_RATE=y
> > +CONFIG_SANDBOX_CLK_CCF=y
> > +CONFIG_CPU=y
> > +CONFIG_DM_DEMO=y
> > +CONFIG_DM_DEMO_SIMPLE=y
> > +CONFIG_DM_DEMO_SHAPE=y
> > +CONFIG_DFU_SF=y
> > +CONFIG_DMA=y
> > +CONFIG_DMA_CHANNELS=y
> > +CONFIG_SANDBOX_DMA=y
> > +CONFIG_FASTBOOT_FLASH=y
> > +CONFIG_FASTBOOT_FLASH_MMC_DEV=0
> > +CONFIG_GPIO_HOG=y
> > +CONFIG_DM_GPIO_LOOKUP_LABEL=y
> > +CONFIG_PM8916_GPIO=y
> > +CONFIG_SANDBOX_GPIO=y
> > +CONFIG_DM_HWSPINLOCK=y
> > +CONFIG_HWSPINLOCK_SANDBOX=y
> > +CONFIG_I2C_CROS_EC_TUNNEL=y
> > +CONFIG_I2C_CROS_EC_LDO=y
> > +CONFIG_DM_I2C_GPIO=y
> > +CONFIG_SYS_I2C_SANDBOX=y
> > +CONFIG_I2C_MUX=y
> > +CONFIG_SPL_I2C_MUX=y
> > +CONFIG_I2C_ARB_GPIO_CHALLENGE=y
> > +CONFIG_CROS_EC_KEYB=y
> > +CONFIG_I8042_KEYB=y
> > +CONFIG_LED=y
> > +CONFIG_LED_BLINK=y
> > +CONFIG_LED_GPIO=y
> > +CONFIG_DM_MAILBOX=y
> > +CONFIG_SANDBOX_MBOX=y
> > +CONFIG_MISC=y
> > +CONFIG_CROS_EC=y
> > +CONFIG_CROS_EC_I2C=y
> > +CONFIG_CROS_EC_LPC=y
> > +CONFIG_CROS_EC_SANDBOX=y
> > +CONFIG_CROS_EC_SPI=y
> > +CONFIG_P2SB=y
> > +CONFIG_PWRSEQ=y
> > +CONFIG_SPL_PWRSEQ=y
> > +CONFIG_I2C_EEPROM=y
> > +CONFIG_MMC_PCI=y
> > +CONFIG_MMC_SANDBOX=y
> > +CONFIG_MMC_SDHCI=y
> > +CONFIG_MTD=y
> > +CONFIG_SPI_FLASH_SANDBOX=y
> > +CONFIG_SPI_FLASH_ATMEL=y
> > +CONFIG_SPI_FLASH_EON=y
> > +CONFIG_SPI_FLASH_GIGADEVICE=y
> > +CONFIG_SPI_FLASH_MACRONIX=y
> > +CONFIG_SPI_FLASH_SPANSION=y
> > +CONFIG_SPI_FLASH_STMICRO=y
> > +CONFIG_SPI_FLASH_SST=y
> > +CONFIG_SPI_FLASH_WINBOND=y
> > +CONFIG_MULTIPLEXER=y
> > +CONFIG_MUX_MMIO=y
> > +CONFIG_DM_ETH=y
> > +CONFIG_NVME=y
> > +CONFIG_PCI=y
> > +CONFIG_DM_PCI=y
> > +CONFIG_PCI_REGION_MULTI_ENTRY=y
> > +CONFIG_PCI_SANDBOX=y
> > +CONFIG_PHY=y
> > +CONFIG_PHY_SANDBOX=y
> > +CONFIG_PINCTRL=y
> > +CONFIG_PINCONF=y
> > +CONFIG_PINCTRL_SANDBOX=y
> > +CONFIG_PINCTRL_SINGLE=y
> > +CONFIG_POWER_DOMAIN=y
> > +CONFIG_SANDBOX_POWER_DOMAIN=y
> > +CONFIG_DM_PMIC=y
> > +CONFIG_PMIC_ACT8846=y
> > +CONFIG_DM_PMIC_PFUZE100=y
> > +CONFIG_DM_PMIC_MAX77686=y
> > +CONFIG_DM_PMIC_MC34708=y
> > +CONFIG_PMIC_PM8916=y
> > +CONFIG_PMIC_RK8XX=y
> > +CONFIG_PMIC_S2MPS11=y
> > +CONFIG_DM_PMIC_SANDBOX=y
> > +CONFIG_PMIC_S5M8767=y
> > +CONFIG_PMIC_TPS65090=y
> > +CONFIG_DM_REGULATOR=y
> > +CONFIG_REGULATOR_ACT8846=y
> > +CONFIG_DM_REGULATOR_PFUZE100=y
> > +CONFIG_DM_REGULATOR_MAX77686=y
> > +CONFIG_DM_REGULATOR_FIXED=y
> > +CONFIG_REGULATOR_RK8XX=y
> > +CONFIG_REGULATOR_S5M8767=y
> > +CONFIG_DM_REGULATOR_SANDBOX=y
> > +CONFIG_REGULATOR_TPS65090=y
> > +CONFIG_DM_REGULATOR_SCMI=y
> > +CONFIG_DM_PWM=y
> > +CONFIG_PWM_CROS_EC=y
> > +CONFIG_PWM_SANDBOX=y
> > +CONFIG_RAM=y
> > +CONFIG_REMOTEPROC_SANDBOX=y
> > +CONFIG_DM_RESET=y
> > +CONFIG_SANDBOX_RESET=y
> > +CONFIG_RESET_SYSCON=y
> > +CONFIG_RESET_SCMI=y
> > +CONFIG_DM_RNG=y
> > +CONFIG_DM_RTC=y
> > +CONFIG_RTC_RV8803=y
> > +CONFIG_SANDBOX_SERIAL=y
> > +CONFIG_SMEM=y
> > +CONFIG_SANDBOX_SMEM=y
> > +CONFIG_SOUND=y
> > +CONFIG_SOUND_DA7219=y
> > +CONFIG_SOUND_MAX98357A=y
> > +CONFIG_SOUND_SANDBOX=y
> > +CONFIG_SOC_DEVICE=y
> > +CONFIG_SANDBOX_SPI=y
> > +CONFIG_SPMI=y
> > +CONFIG_SPMI_SANDBOX=y
> > +CONFIG_SYSINFO=y
> > +CONFIG_SYSINFO_SANDBOX=y
> > +CONFIG_SYSINFO_GPIO=y
> > +CONFIG_SYSRESET=y
> > +CONFIG_TIMER=y
> > +CONFIG_TIMER_EARLY=y
> > +CONFIG_SANDBOX_TIMER=y
> > +CONFIG_USB=y
> > +CONFIG_DM_USB=y
> > +CONFIG_USB_EMUL=y
> > +CONFIG_USB_KEYBOARD=y
> > +CONFIG_DM_VIDEO=y
> > +CONFIG_VIDEO_COPY=y
> > +CONFIG_CONSOLE_ROTATION=y
> > +CONFIG_CONSOLE_TRUETYPE=y
> > +CONFIG_CONSOLE_TRUETYPE_CANTORAONE=y
> > +CONFIG_VIDEO_SANDBOX_SDL=y
> > +CONFIG_VIDEO_DSI_HOST_SANDBOX=y
> > +CONFIG_OSD=y
> > +CONFIG_SANDBOX_OSD=y
> > +CONFIG_SPLASH_SCREEN_ALIGN=y
> > +CONFIG_VIDEO_BMP_RLE8=y
> > +CONFIG_W1=y
> > +CONFIG_W1_GPIO=y
> > +CONFIG_W1_EEPROM=y
> > +CONFIG_W1_EEPROM_SANDBOX=y
> > +CONFIG_WDT=y
> > +CONFIG_WDT_SANDBOX=y
> > +CONFIG_FS_CBFS=y
> > +CONFIG_FS_CRAMFS=y
> > +CONFIG_CMD_DHRYSTONE=y
> > +CONFIG_TPM=y
> > +CONFIG_LZ4=y
> > +CONFIG_ERRNO_STR=y
> > +CONFIG_EFI_RUNTIME_UPDATE_CAPSULE=y
> > +CONFIG_EFI_CAPSULE_ON_DISK=y
> > +CONFIG_EFI_CAPSULE_FIRMWARE_FIT=y
> > +CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y
> > +CONFIG_EFI_CAPSULE_AUTHENTICATE=y
> > +CONFIG_EFI_CAPSULE_KEY_PATH="../test/py/tests/test_efi_capsule/SIGNER.esl"
> 
> Is this path relative to the build directory?

No.

> Will building fail if the build directory is not a direct subdirectory
> of the source directory?

No.
"incbin" directive in assembly code works with "include directory" paths.
As "-Iinclude" is passed on to the assembler, "../" will eventually be
able to point to the source directory whatever the build directory is.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> > +CONFIG_EFI_SECURE_BOOT=y
> > +CONFIG_TEST_FDTDEC=y
> > +CONFIG_CRYPT_PW=y
> > +CONFIG_CRYPT_PW_SHA256=y
> > +CONFIG_CRYPT_PW_SHA512=y
> > +CONFIG_AUTOBOOT_KEYED=y
> > +CONFIG_AUTOBOOT_PROMPT="Enter password \"a\" in %d seconds to stop autoboot\n"
> > +CONFIG_AUTOBOOT_ENCRYPTION=y
> > +CONFIG_AUTOBOOT_STOP_STR_ENABLE=y
> > +CONFIG_AUTOBOOT_STOP_STR_CRYPT="$5$rounds=640000$HrpE65IkB8CM5nCL$BKT3QdF98Bo8fJpTr9tjZLZQyzqPASBY20xuK5Rent9"
> > +CONFIG_AUTOBOOT_NEVER_TIMEOUT=y
> > +CONFIG_AUTOBOOT_SHA256_FALLBACK=y
> > +CONFIG_UNIT_TEST=y
> > +CONFIG_UT_TIME=y
> > +CONFIG_UT_DM=y
> > +CONFIG_DM_REBOOT_MODE=y
> > +CONFIG_DM_REBOOT_MODE_GPIO=y
> > +CONFIG_DM_REBOOT_MODE_RTC=y
> > 

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-07-27  9:10 ` [PATCH v2 6/9] sandbox: add config for efi capsule " AKASHI Takahiro
  2021-07-28 20:21   ` Heinrich Schuchardt
@ 2021-07-31 16:59   ` Simon Glass
  2021-08-01  4:29     ` AKASHI Takahiro
  1 sibling, 1 reply; 30+ messages in thread
From: Simon Glass @ 2021-07-31 16:59 UTC (permalink / raw)
  To: AKASHI Takahiro
  Cc: Heinrich Schuchardt, Alex Graf, Tom Rini, Ilias Apalodimas,
	Sughosh Ganu, Masami Hiramatsu, U-Boot Mailing List

Hi Takahiro,

On Tue, 27 Jul 2021 at 03:12, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> This new configuration, which was derived from sandbox_defconfig, will be
> used solely to run efi capsule authentication test as the test requires
> a public key (esl file) to be embedded in U-Boot binary.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>  configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
>  1 file changed, 307 insertions(+)
>  create mode 100644 configs/sandbox_capsule_auth_defconfig

NAK.

Please just add it to sandbox_defconfig. We sometimes have to create
new variants when dealing with actual build variations (e.g. SPL,
building without OF_LIVE), but here we should just enable the feature
in sandbox_defconfig.

We already covered embedding key in the binary on another thread.
Please don't do that. After that debacle I sent a patch explaining
this:

http://patchwork.ozlabs.org/project/uboot/patch/20210725164400.468319-3-sjg@chromium.org/

Regards,
Simon

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-07-31 16:59   ` Simon Glass
@ 2021-08-01  4:29     ` AKASHI Takahiro
  2021-08-01 19:00       ` Simon Glass
  0 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-01  4:29 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, Alex Graf, Tom Rini, Ilias Apalodimas,
	Sughosh Ganu, Masami Hiramatsu, U-Boot Mailing List

Simon,

On Sat, Jul 31, 2021 at 10:59:32AM -0600, Simon Glass wrote:
> Hi Takahiro,
> 
> On Tue, 27 Jul 2021 at 03:12, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > This new configuration, which was derived from sandbox_defconfig, will be
> > used solely to run efi capsule authentication test as the test requires
> > a public key (esl file) to be embedded in U-Boot binary.
> >
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >  configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
> >  1 file changed, 307 insertions(+)
> >  create mode 100644 configs/sandbox_capsule_auth_defconfig
> 
> NAK.
> 
> Please just add it to sandbox_defconfig. We sometimes have to create

Unfortunately, I can't.
Look, we now have two tests, test_capsule_firmware.py and
test_capsule_firmware_signed.py, and we need U-Boot binaries,
respectively, without a key and with a key.
A single configuration cannot satisfy both.

> new variants when dealing with actual build variations (e.g. SPL,
> building without OF_LIVE), but here we should just enable the feature
> in sandbox_defconfig.
> 
> We already covered embedding key in the binary on another thread.
> Please don't do that. After that debacle I sent a patch explaining
> this:
> 
> http://patchwork.ozlabs.org/project/uboot/patch/20210725164400.468319-3-sjg@chromium.org/

Please discuss and make an agreement with Heinrich.
The patch for embedding a key has already been merged in -rc1.

In my personal opinion, neither approaches won't apply to production
any way.

-Takahiro Akashi

> Regards,
> Simon

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

* Re: [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
  2021-07-28  8:12   ` Masami Hiramatsu
@ 2021-08-01  9:21   ` Heinrich Schuchardt
  2021-08-02  3:30     ` AKASHI Takahiro
  1 sibling, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:21 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> With this enhancement, mkeficapsule will be able to sign a capsule
> file when it is created. A signature added will be used later
> in the verification at FMP's SetImage() call.
>
> To do that, We need specify additional command parameters:
>    -monotonic-cout <count> : monotonic count
>    -private-key <private key file> : private key file
>    -certificate <certificate file> : certificate file
> Only when all of those parameters are given, a signature will be added
> to a capsule file.
>
> Users are expected to maintain and increment the monotonic count at
> every time of the update for each firmware image.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   tools/Kconfig        |   7 +
>   tools/Makefile       |   8 +-
>   tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
>   3 files changed, 316 insertions(+), 31 deletions(-)
>
> diff --git a/tools/Kconfig b/tools/Kconfig
> index d6f82cd949b5..9a37ed035311 100644
> --- a/tools/Kconfig
> +++ b/tools/Kconfig
> @@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
>   	  This selection does not affect target features, such as runtime FIT
>   	  signature verification.
>
> +config TOOLS_MKEFICAPSULE
> +	bool "Build efimkcapsule command"
> +	default y if EFI_CAPSULE_ON_DISK
> +	help
> +	  This command allows users to create a UEFI capsule file and,
> +	  optionally sign that file. If you want to enable UEFI capsule
> +	  update feature on your target, you certainly need this.
>   endmenu
> diff --git a/tools/Makefile b/tools/Makefile
> index bae3f95c4995..af8536489652 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
>   hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
>   HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
>
> -mkeficapsule-objs	:= mkeficapsule.o $(LIBFDT_OBJS)
> -hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
> +HOSTLDLIBS_mkeficapsule += -luuid
> +ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
> +HOSTLDLIBS_mkeficapsule += \
> +	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")

Please, add package pkg-config to the build dependencies enumerated in
doc/build/gcc.rst.

> +endif
> +hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
>
>   # We build some files with extra pedantic flags to try to minimize things
>   # that won't build on some weird host compiler -- though there are lots of
> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> index 4995ba4e0c2a..798706c7b5f7 100644
> --- a/tools/mkeficapsule.c
> +++ b/tools/mkeficapsule.c
> @@ -15,6 +15,16 @@
>   #include <sys/stat.h>
>   #include <sys/types.h>
>
> +#include <linux/kconfig.h>
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +#include <openssl/asn1.h>
> +#include <openssl/bio.h>
> +#include <openssl/evp.h>
> +#include <openssl/err.h>
> +#include <openssl/pem.h>
> +#include <openssl/pkcs7.h>
> +#endif
> +
>   typedef __u8 u8;
>   typedef __u16 u16;
>   typedef __u32 u32;
> @@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
>   		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
>   efi_guid_t efi_guid_image_type_uboot_raw =
>   		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
> +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> +
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
> +#else
> +static const char *opts_short = "f:r:i:I:v:h";
> +#endif
>
>   static struct option options[] = {
>   	{"fit", required_argument, NULL, 'f'},
>   	{"raw", required_argument, NULL, 'r'},
>   	{"index", required_argument, NULL, 'i'},
>   	{"instance", required_argument, NULL, 'I'},
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +	{"private-key", required_argument, NULL, 'p'},
> +	{"certificate", required_argument, NULL, 'c'},
> +	{"monotonic-count", required_argument, NULL, 'm'},
> +	{"dump-sig", no_argument, NULL, 'd'},
> +#endif
>   	{"help", no_argument, NULL, 'h'},
>   	{NULL, 0, NULL, 0},
>   };
> @@ -57,16 +80,195 @@ static void print_usage(void)
>   	       "\t-r, --raw <raw image>       new raw image file\n"
>   	       "\t-i, --index <index>         update image index\n"
>   	       "\t-I, --instance <instance>   update hardware instance\n"
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +	       "\t-p, --private-key <privkey file>  private key file\n"
> +	       "\t-c, --certificate <cert file>     signer's certificate file\n"
> +	       "\t-m, --monotonic-count <count>     monotonic count\n"
> +	       "\t-d, --dump_sig              dump signature (*.p7)\n"
> +#endif
>   	       "\t-h, --help                  print a help message\n",
>   	       tool_name);
>   }
>

Please, add Sphinx documentation.

> +struct auth_context {
> +	char *key_file;
> +	char *cert_file;
> +	u8 *image_data;
> +	size_t image_size;
> +	struct efi_firmware_image_authentication auth;
> +	u8 *sig_data;
> +	size_t sig_size;
> +};
> +
> +static int dump_sig;
> +
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +static EVP_PKEY *fileio_read_pkey(const char *filename)
> +{
> +	EVP_PKEY *key = NULL;
> +	BIO *bio;
> +
> +	bio = BIO_new_file(filename, "r");
> +	if (!bio)
> +		goto out;
> +
> +	key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
> +
> +out:
> +	BIO_free_all(bio);
> +	if (!key) {
> +		printf("Can't load key from file '%s'\n", filename);
> +		ERR_print_errors_fp(stderr);
> +	}
> +
> +	return key;
> +}
> +

Please, add Sphinx documentation for all functions.

> +static X509 *fileio_read_cert(const char *filename)
> +{
> +	X509 *cert = NULL;
> +	BIO *bio;
> +
> +	bio = BIO_new_file(filename, "r");
> +	if (!bio)
> +		goto out;
> +
> +	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
> +
> +out:
> +	BIO_free_all(bio);
> +	if (!cert) {
> +		printf("Can't load certificate from file '%s'\n", filename);
> +		ERR_print_errors_fp(stderr);
> +	}
> +
> +	return cert;
> +}
> +
> +static int create_auth_data(struct auth_context *ctx)
> +{
> +	EVP_PKEY *key = NULL;
> +	X509 *cert = NULL;
> +	BIO *data_bio = NULL;
> +	const EVP_MD *md;
> +	PKCS7 *p7;
> +	int flags, ret = -1;
> +
> +	OpenSSL_add_all_digests();
> +	OpenSSL_add_all_ciphers();
> +	ERR_load_crypto_strings();
> +
> +	key = fileio_read_pkey(ctx->key_file);
> +	if (!key)
> +		goto err;
> +	cert = fileio_read_cert(ctx->cert_file);
> +	if (!cert)
> +		goto err;
> +
> +	/*
> +	 * create a BIO, containing:
> +	 *  * firmware image
> +	 *  * monotonic count
> +	 * in this order!
> +	 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
> +	 */
> +	data_bio = BIO_new(BIO_s_mem());
> +	BIO_write(data_bio, ctx->image_data, ctx->image_size);
> +	BIO_write(data_bio, &ctx->auth.monotonic_count,
> +		  sizeof(ctx->auth.monotonic_count));
> +
> +	md = EVP_get_digestbyname("SHA256");
> +	if (!md)
> +		goto err;
> +
> +	/* create signature */
> +	/* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
> +	flags = PKCS7_BINARY | PKCS7_DETACHED;
> +	p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
> +	if (!p7)
> +		goto err;
> +	if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
> +		goto err;
> +	if (!PKCS7_final(p7, data_bio, flags))
> +		goto err;
> +
> +	/* convert pkcs7 into DER */
> +	ctx->sig_data = NULL;
> +	ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
> +				      ASN1_ITEM_rptr(PKCS7));
> +	if (!ctx->sig_size)
> +		goto err;
> +
> +	/* fill auth_info */
> +	ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
> +						+ ctx->sig_size;
> +	ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> +	ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> +	memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
> +	       sizeof(efi_guid_cert_type_pkcs7));
> +
> +	ret = 0;
> +err:
> +	BIO_free_all(data_bio);
> +	EVP_PKEY_free(key);
> +	X509_free(cert);
> +
> +	return ret;
> +}
> +
> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> +{
> +	char *sig_path;
> +	FILE *f;
> +	size_t size;
> +	int ret = -1;
> +
> +	sig_path = malloc(strlen(path) + 3 + 1);
> +	if (!sig_path)
> +		return ret;
> +
> +	sprintf(sig_path, "%s.p7", path);
> +	f = fopen(sig_path, "w");
> +	if (!f)
> +		goto err;
> +
> +	size = fwrite(signature, 1, sig_size, f);
> +	if (size == sig_size)
> +		ret = 0;
> +
> +	fclose(f);
> +err:
> +	free(sig_path);
> +	return ret;
> +}
> +
> +static void free_sig_data(struct auth_context *ctx)
> +{
> +	if (ctx->sig_size)
> +		OPENSSL_free(ctx->sig_data);
> +}
> +#else
> +static int create_auth_data(struct auth_context *ctx)
> +{
> +	return 0;
> +}
> +
> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> +{
> +	return 0;
> +}
> +
> +static void free_sig_data(struct auth_context *ctx) {}
> +#endif
> +
>   static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> -			unsigned long index, unsigned long instance)
> +			unsigned long index, unsigned long instance,
> +			uint64_t mcount, char *privkey_file, char *cert_file)
>   {
>   	struct efi_capsule_header header;
>   	struct efi_firmware_management_capsule_header capsule;
>   	struct efi_firmware_management_capsule_image_header image;
> +	struct auth_context auth_context;
>   	FILE *f, *g;
>   	struct stat bin_stat;
>   	u8 *data;
> @@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>   	printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
>   	printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);

[tools/mkeficapsule.c:281] (warning) %ld in format string (no. 1)
requires 'long' but the argument type is 'unsigned long'.

Best regards

Heinrich

>   #endif
> +	auth_context.sig_size = 0;
>
>   	g = fopen(bin, "r");
>   	if (!g) {
> @@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>   		printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
>   		goto err_1;
>   	}
> -	f = fopen(path, "w");
> -	if (!f) {
> -		printf("cannot open %s\n", path);
> +
> +	size = fread(data, 1, bin_stat.st_size, g);
> +	if (size < bin_stat.st_size) {
> +		printf("read failed (%zx)\n", size);
>   		goto err_2;
>   	}
> +
> +	/* first, calculate signature to determine its size */
> +	if (privkey_file && cert_file) {
> +		auth_context.key_file = privkey_file;
> +		auth_context.cert_file = cert_file;
> +		auth_context.auth.monotonic_count = mcount;
> +		auth_context.image_data = data;
> +		auth_context.image_size = bin_stat.st_size;
> +
> +		if (create_auth_data(&auth_context)) {
> +			printf("Signing firmware image failed\n");
> +			goto err_3;
> +		}
> +
> +		if (dump_sig &&
> +		    dump_signature(path, auth_context.sig_data,
> +				   auth_context.sig_size)) {
> +			printf("Creating signature file failed\n");
> +			goto err_3;
> +		}
> +	}
> +
>   	header.capsule_guid = efi_guid_fm_capsule;
>   	header.header_size = sizeof(header);
>   	/* TODO: The current implementation ignores flags */
> @@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>   					+ sizeof(capsule) + sizeof(u64)
>   					+ sizeof(image)
>   					+ bin_stat.st_size;
> +	if (auth_context.sig_size)
> +		header.capsule_image_size += sizeof(auth_context.auth)
> +				+ auth_context.sig_size;
> +
> +	f = fopen(path, "w");
> +	if (!f) {
> +		printf("cannot open %s\n", path);
> +		goto err_3;
> +	}
>
>   	size = fwrite(&header, 1, sizeof(header), f);
>   	if (size < sizeof(header)) {
>   		printf("write failed (%zx)\n", size);
> -		goto err_3;
> +		goto err_4;
>   	}
>
>   	capsule.version = 0x00000001;
> @@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>   	size = fwrite(&capsule, 1, sizeof(capsule), f);
>   	if (size < (sizeof(capsule))) {
>   		printf("write failed (%zx)\n", size);
> -		goto err_3;
> +		goto err_4;
>   	}
>   	offset = sizeof(capsule) + sizeof(u64);
>   	size = fwrite(&offset, 1, sizeof(offset), f);
>   	if (size < sizeof(offset)) {
>   		printf("write failed (%zx)\n", size);
> -		goto err_3;
> +		goto err_4;
>   	}
>
>   	image.version = 0x00000003;
> @@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>   	image.reserved[1] = 0;
>   	image.reserved[2] = 0;
>   	image.update_image_size = bin_stat.st_size;
> +	if (auth_context.sig_size)
> +		image.update_image_size += sizeof(auth_context.auth)
> +				+ auth_context.sig_size;
>   	image.update_vendor_code_size = 0; /* none */
>   	image.update_hardware_instance = instance;
>   	image.image_capsule_support = 0;
> +	if (auth_context.sig_size)
> +		image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
>
>   	size = fwrite(&image, 1, sizeof(image), f);
>   	if (size < sizeof(image)) {
>   		printf("write failed (%zx)\n", size);
> -		goto err_3;
> +		goto err_4;
>   	}
> -	size = fread(data, 1, bin_stat.st_size, g);
> -	if (size < bin_stat.st_size) {
> -		printf("read failed (%zx)\n", size);
> -		goto err_3;
> +
> +	if (auth_context.sig_size) {
> +		size = fwrite(&auth_context.auth, 1,
> +			      sizeof(auth_context.auth), f);
> +		if (size < sizeof(auth_context.auth)) {
> +			printf("write failed (%zx)\n", size);
> +			goto err_4;
> +		}
> +		size = fwrite(auth_context.sig_data, 1,
> +			      auth_context.sig_size, f);
> +		if (size < auth_context.sig_size) {
> +			printf("write failed (%zx)\n", size);
> +			goto err_4;
> +		}
>   	}
> +
>   	size = fwrite(data, 1, bin_stat.st_size, f);
>   	if (size < bin_stat.st_size) {
>   		printf("write failed (%zx)\n", size);
> -		goto err_3;
> +		goto err_4;
>   	}
>
>   	fclose(f);
>   	fclose(g);
>   	free(data);
> +	free_sig_data(&auth_context);
>
>   	return 0;
>
> -err_3:
> +err_4:
>   	fclose(f);
> +err_3:
> +	free_sig_data(&auth_context);
>   err_2:
>   	free(data);
>   err_1:
> @@ -171,23 +425,25 @@ err_1:
>   	return -1;
>   }
>
> -/*
> - * Usage:
> - *   $ mkeficapsule -f <firmware binary> <output file>
> - */
>   int main(int argc, char **argv)
>   {
>   	char *file;
>   	efi_guid_t *guid;
>   	unsigned long index, instance;
> +	uint64_t mcount;
> +	char *privkey_file, *cert_file;
>   	int c, idx;
>
>   	file = NULL;
>   	guid = NULL;
>   	index = 0;
>   	instance = 0;
> +	mcount = 0;
> +	privkey_file = NULL;
> +	cert_file = NULL;
> +	dump_sig = 0;
>   	for (;;) {
> -		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
> +		c = getopt_long(argc, argv, opts_short, options, &idx);
>   		if (c == -1)
>   			break;
>
> @@ -214,26 +470,44 @@ int main(int argc, char **argv)
>   		case 'I':
>   			instance = strtoul(optarg, NULL, 0);
>   			break;
> +#ifdef CONFIG_TOOLS_LIBCRYPTO
> +		case 'p':
> +			if (privkey_file) {
> +				printf("Private Key already specified\n");
> +				return -1;
> +			}
> +			privkey_file = optarg;
> +			break;
> +		case 'c':
> +			if (cert_file) {
> +				printf("Certificate file already specified\n");
> +				return -1;
> +			}
> +			cert_file = optarg;
> +			break;
> +		case 'm':
> +			mcount = strtoul(optarg, NULL, 0);
> +			break;
> +		case 'd':
> +			dump_sig = 1;
> +			break;
> +#endif /* CONFIG_TOOLS_LIBCRYPTO */
>   		case 'h':
>   			print_usage();
>   			return 0;
>   		}
>   	}
>
> -	/* need an output file */
> -	if (argc != optind + 1) {
> +	/* check necessary parameters */
> +	if ((argc != optind + 1) || !file ||
> +	    ((privkey_file && !cert_file) ||
> +	     (!privkey_file && cert_file))) {
>   		print_usage();
>   		exit(EXIT_FAILURE);
>   	}
>
> -	/* need a fit image file or raw image file */
> -	if (!file) {
> -		print_usage();
> -		exit(EXIT_SUCCESS);
> -	}
> -
> -	if (create_fwbin(argv[optind], file, guid, index, instance)
> -			< 0) {
> +	if (create_fwbin(argv[optind], file, guid, index, instance,
> +			 mcount, privkey_file, cert_file) < 0) {
>   		printf("Creating firmware capsule failed\n");
>   		exit(EXIT_FAILURE);
>   	}
>


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

* Re: [PATCH v2 2/9] tools: mkeficapsule: add man page
  2021-07-27  9:10 ` [PATCH v2 2/9] tools: mkeficapsule: add man page AKASHI Takahiro
@ 2021-08-01  9:28   ` Heinrich Schuchardt
  0 siblings, 0 replies; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:28 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> Add a man page for mkeficapsule command.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

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

> ---
>   MAINTAINERS        |  1 +
>   doc/mkeficapsule.1 | 91 ++++++++++++++++++++++++++++++++++++++++++++++
>   2 files changed, 92 insertions(+)
>   create mode 100644 doc/mkeficapsule.1
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index ae6c70860d3a..24f52f837066 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -696,6 +696,7 @@ S:	Maintained
>   T:	git https://source.denx.de/u-boot/custodians/u-boot-efi.git
>   F:	doc/api/efi.rst
>   F:	doc/develop/uefi/*
> +F:	doc/mkeficapsule.1
>   F:	doc/usage/bootefi.rst
>   F:	drivers/rtc/emul_rtc.c
>   F:	include/capitalization.h
> diff --git a/doc/mkeficapsule.1 b/doc/mkeficapsule.1
> new file mode 100644
> index 000000000000..7c2341160ea4
> --- /dev/null
> +++ b/doc/mkeficapsule.1
> @@ -0,0 +1,91 @@
> +.TH MAEFICAPSULE 1 "May 2021"
> +
> +.SH NAME
> +mkeficapsule \- Generate EFI capsule file for U-Boot
> +
> +.SH SYNOPSIS
> +.B mkeficapsule
> +.RB [\fIoptions\fP] " \fIcapsule-file\fP"
> +
> +.SH "DESCRIPTION"
> +The
> +\fBmkeficapsule\fP
> +command is used to create an EFI capsule file for use with the U-Boot
> +EFI capsule update.
> +A capsule file may contain various type of firmware blobs which
> +are to be applied to the system and must be placed in the specific
> +directory on the UEFI system partition. An update will be automatically
> +executed at next reboot.
> +
> +Optionally, a capsule file can be signed with a given private key.
> +In this case, the update will be authenticated by verifying the signature
> +before applying.
> +
> +\fBmkeficapsule\fP supports two different format of image files:
> +.TP
> +.I raw image
> +format is a single binary blob of any type of firmware.
> +
> +.TP
> +.I FIT (Flattened Image Tree) image
> +format
> +is the same as used in the new \fIuImage\fP format and allows for
> +multiple binary blobs in a single capsule file.
> +This type of image file can be generated by \fBmkimage\fP.
> +
> +.SH "OPTIONS"
> +
> +.TP
> +.BI "-f, --fit \fIfit-image-file\fP"
> +Specify a FIT image file
> +
> +.TP
> +.BI "-r, --raw \fIraw-image-file\fP"
> +Specify a raw image file
> +
> +.TP
> +.BI "-i, --index \fIindex\fP"
> +Specify an image index
> +
> +.TP
> +.BI "-I, --instance \fIinstance\fP"
> +Specify a hardware instance
> +
> +.TP
> +.BI "-h, --help"
> +Print a help message
> +
> +.TP 0
> +.B With signing:
> +
> +.TP
> +.BI "-p, --private-key \fIprivate-key-file\fP"
> +Specify signer's private key file in PEM
> +
> +.TP
> +.BI "-c, --certificate \fIcertificate-file\fP"
> +Specify signer's certificate file in EFI certificate list format
> +
> +.TP
> +.BI "-m, --monotonic-count \fIcount\fP"
> +Specify a monotonic count which is set to be monotonically incremented
> +at every firmware update.
> +
> +.TP
> +.BI "-d, --dump_sig"
> +Dump signature data into *.p7 file
> +
> +.PP
> +.SH FILES
> +.TP
> +.BI "\fI/EFI/UpdateCapsule\fP"
> +The directory in which all capsule files be placed
> +
> +.SH SEE ALSO
> +.B mkimage
> +
> +.SH AUTHORS
> +Written by AKASHI Takahiro <takahiro.akashi@linaro.org>
> +
> +.SH HOMEPAGE
> +http://www.denx.de/wiki/U-Boot/WebHome
>


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

* Re: [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule
  2021-07-27  9:10 ` [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule AKASHI Takahiro
@ 2021-08-01  9:31   ` Heinrich Schuchardt
  0 siblings, 0 replies; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:31 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> Now we can use mkeficapsule command instead of EDK-II's script
> to create a signed capsule file. So update the instruction for
> capsule authentication.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

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

> ---
>   doc/develop/uefi/uefi.rst | 31 ++++++++++++++-----------------
>   1 file changed, 14 insertions(+), 17 deletions(-)
>
> diff --git a/doc/develop/uefi/uefi.rst b/doc/develop/uefi/uefi.rst
> index 64fe9346c7f2..5ccb455da984 100644
> --- a/doc/develop/uefi/uefi.rst
> +++ b/doc/develop/uefi/uefi.rst
> @@ -347,23 +347,20 @@ and used by the steps highlighted below::
>               -keyout CRT.key -out CRT.crt -nodes -days 365
>           $ cert-to-efi-sig-list CRT.crt CRT.esl
>
> -        $ openssl x509 -in CRT.crt -out CRT.cer -outform DER
> -        $ openssl x509 -inform DER -in CRT.cer -outform PEM -out CRT.pub.pem
> -
> -        $ openssl pkcs12 -export -out CRT.pfx -inkey CRT.key -in CRT.crt
> -        $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem
> -
> -The capsule file can be generated by using the GenerateCapsule.py
> -script in EDKII::
> -
> -    $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \
> -      <capsule_file_name> --monotonic-count <val> --fw-version \
> -      <val> --lsv <val> --guid \
> -      e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \
> -      --update-image-index <val> --signer-private-cert \
> -      /path/to/CRT.pem --trusted-public-cert \
> -      /path/to/CRT.pub.pem --other-public-cert /path/to/CRT.pub.pem \
> -      <u-boot.bin>
> +The signed capsule file can be generated by using tools/mkeficapsule.
> +To build this tool, enable::
> +
> +    CONFIG_TOOLS_MKEFICAPSULE=y
> +    CONFIG_TOOLS_LIBCRYPTO=y
> +
> +To generate and sign the capsule file::
> +
> +    $ mkeficapsule --monotonic-count 1 \
> +      --private-key CRT.key \
> +      --certificate CRT.crt \
> +      --index 1 --instance 0 \
> +      [--fit <FIT image> | --raw <raw image>] \
> +      <capsule_file_name>
>
>   Place the capsule generated in the above step on the EFI System
>   Partition under the EFI/UpdateCapsule directory
>


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

* Re: [PATCH v2 4/9] efi_loader: ease the file path check for public key
  2021-07-27  9:10 ` [PATCH v2 4/9] efi_loader: ease the file path check for public key AKASHI Takahiro
@ 2021-08-01  9:35   ` Heinrich Schuchardt
  2021-08-02  4:50     ` AKASHI Takahiro
  0 siblings, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:35 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> The check for CONFIG_EFI_CAPSULE_KEY_PATH:
>      ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
> does not allow users to specify a relative path for including a public
> key binary. This is fine for most of all cases, but it will make it
> difficult to add pytest test cases as pre-created keys/certificates
> are placed in "test" directory.
>
> So just ease the check, still causing an error if the specified file
> does not exist at compiling efi_capsule_key.S.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> ---
>   lib/efi_loader/Makefile | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> index 9b369430e258..fca0da4d131e 100644
> --- a/lib/efi_loader/Makefile
> +++ b/lib/efi_loader/Makefile
> @@ -21,8 +21,9 @@ targets += helloworld.o
>   endif
>
>   ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y)
> -EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
> -ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
> +#EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
> +#ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")

Please, remove these two comment lines.

> +ifeq ($(CONFIG_EFI_CAPSULE_KEY_PATH),"")
>   $(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_KEY_PATH)

%s/cerificate/certificate/

Best regards

Heinrich

>   endif
>   endif
>


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

* Re: [PATCH v2 5/9] test/py: efi_capsule: add image authentication test
  2021-07-27  9:10 ` [PATCH v2 5/9] test/py: efi_capsule: add image authentication test AKASHI Takahiro
@ 2021-08-01  9:38   ` Heinrich Schuchardt
  2021-08-02  4:02     ` AKASHI Takahiro
  0 siblings, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:38 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> Add a couple of test cases against capsule image authentication
> for capsule-on-disk, where only a signed capsule file with the verified
> signature will be applied to the system.
>
> Due to the difficulty of embedding a public key (esl file) in U-Boot
> binary during pytest setup time, all the keys/certificates are pre-created.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>

Please, check the pylint warnings:

$ pylint test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
************* Module test_capsule_firmware_signed
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:44:0:
C0301: Line too long (113/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:73:0:
C0301: Line too long (117/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:110:0:
C0301: Line too long (113/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:139:0:
C0301: Line too long (117/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:178:0:
C0301: Line too long (113/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:207:0:
C0301: Line too long (117/100) (line-too-long)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:154:2:
W0511: TODO: check CapsuleStatus in CapsuleXXXX (fixme)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:222:2:
W0511: TODO: check CapsuleStatus in CapsuleXXXX (fixme)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:14:0:
W0401: Wildcard import capsule_defs (wildcard-import)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:27:0:
C0115: Missing class docstring (missing-class-docstring)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:27:0:
R0205: Class 'TestEfiCapsuleFirmwareSigned' inherits from object, can be
safely removed from bases in python3 (useless-object-inheritance)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:28:4:
R0201: Method could be a function (no-self-use)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:93:4:
R0201: Method could be a function (no-self-use)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:162:4:
R0201: Method could be a function (no-self-use)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
W0611: Unused check_call imported from subprocess (unused-import)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
W0611: Unused check_output imported from subprocess (unused-import)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
W0611: Unused CalledProcessError imported from subprocess (unused-import)
test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:14:0:
W0614: Unused import EFITOOLS_PATH from wildcard import
(unused-wildcard-import)

Best regards

Heinrich

> ---
>   test/py/tests/test_efi_capsule/SIGNER.crt     |  19 ++
>   test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
>   test/py/tests/test_efi_capsule/SIGNER.key     |  28 +++
>   test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 ++
>   test/py/tests/test_efi_capsule/SIGNER2.key    |  28 +++
>   .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
>   test/py/tests/test_efi_capsule/conftest.py    |  35 ++-
>   .../test_capsule_firmware_signed.py           | 228 ++++++++++++++++++
>   8 files changed, 359 insertions(+), 3 deletions(-)
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
>   create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
>
> diff --git a/test/py/tests/test_efi_capsule/SIGNER.crt b/test/py/tests/test_efi_capsule/SIGNER.crt
> new file mode 100644
> index 000000000000..f63ec01d9996
> --- /dev/null
> +++ b/test/py/tests/test_efi_capsule/SIGNER.crt
> @@ -0,0 +1,19 @@
> +-----BEGIN CERTIFICATE-----
> +MIIDDTCCAfWgAwIBAgIUD96z+lSbhDFN76YoIY2LnDBt1yQwDQYJKoZIhvcNAQEL
> +BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
> +NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
> +AQEBBQADggEPADCCAQoCggEBAMBuazX28i0y4L0loJYJOtlvF5eWb4tbx7zwei5c
> +KoSzQYixinS10OrVy7y8mELyXOlGOOsM509vzvoia0nffwEPsvTBeS3le2JBz9iN
> +/+AIo+gUmzgEPQN+jp+s4fi0yzRvq3BgWu1ego2gExxQ7AePQHoSkX8UeC3Kb7SF
> +a8Kt/TopOupZfEuZ+EtoxPA4JUStFgEUEcRJEfpQqECXV+lKqcyqHc2ZUzMisu+i
> +5omkneX8sEZdIPFsSGanCyY3F9VjWzIxo60PU2xUBOIcEUg5luR+VXT4090g/yCw
> +8PSf9rIKgGIQSQKAlUSc7zuXQIdgIMTS1xUpc/Nx+SqWNZECAwEAAaNTMFEwHQYD
> +VR0OBBYEFHndZVpPrAjc3OD3UZ3xkXQqDOlZMB8GA1UdIwQYMBaAFHndZVpPrAjc
> +3OD3UZ3xkXQqDOlZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
> +AG88t6w0qTXE50ltps62f6wtuuZsiX1zj+AluO4E8E3Wi0QsNtT24JdY2P4mAg8y
> +abYLdgJIldzzsfjWWok9Dfqnx29tqgesKWkgUo16v70i4EVZ9YWGe+CfOK639OxL
> +4D0XPcU5CUpDrEcnt59wCxQ7IArZzrDxrqigEw5nReejtgQV/mEzvVOzWjLjmngy
> +SpvrydxYpfSvOJ3KGV9xw3Oa/qO3pS0ZNX9QqZdcC94M0SI6OF635oxJkz6JToYq
> ++qtv9PZtZnEU/cwzL0nTXMj7yRsP5+2Wre26yT62nKRy9P/3UFwmsJ0OuEmnol5I
> +141ZGfBYmSQ6EReOwNeK7A0=
> +-----END CERTIFICATE-----
> diff --git a/test/py/tests/test_efi_capsule/SIGNER.esl b/test/py/tests/test_efi_capsule/SIGNER.esl
> new file mode 100644
> index 0000000000000000000000000000000000000000..a54536e243d274b74985abbecfe234d14013ef33
> GIT binary patch
> literal 829
> zcmZ1&d0^?2Da*aux2_hA(f&|m%gg`<iclKDgOCPI%)ACoj9(WpGchtTiSXas{3~R3
> zi=prPWg3dT-E$0bud5jFvT<s)d9;1!Wn|=LWiSvk6fqEDV-96u=HU);4GxJ9_H_4i
> z4Kk1u=QT1kFgG$YurM_?G>rmsjgYuF^))dnAzQ)7%D~*j$j<<D6&F(zBO}9sylm5N
> zpLC5L>{VSbjnnF8zWDTM`Q6dS_k5_*i_vP??AWoft7PkiS65H(*)zlGQ_M>@i`P8Q
> z{qxWLQp)zcU(d+D>C3@N-KW(_j^}Um{(r!+_=U)93l>}Ey1w~q9{$*J+9ZE<K|<8q
> zxTf9(!ZHDG*!vx-geKODROp_{-_n|WXzgDsO{-UtHQqCScxN2>V4>==R*X?Z@QA12
> zuYeT})5BkStvs_z_Uz1HW2H^+7d`7-GWY494Q{atA9Fm?mUF9_i(gHSHZokimOnTr
> zgyoTppoitOCv~AEKQ7-@_^+_x!<YHrHgPp133xI!Om&&_-g>%2dxFA|OV>p;i$53s
> z)S6~Gk%^g+fpKxLL7;&wFw|xFSj1RFD(|L7`LE%)bLYYLz_}kMmT2+3j5Lr3Nh`BR
> z7>G4sSHKTaAk4`4pM}+c8Au@qJ1}N}!OqB#Z?k=k$x72B&pmUOo!eHwMt9e<oX*<f
> z{s*c%-m!e}z1HobV|L}+gXs}B{;4tX8)a_eE@SeTdgt@TAJ?KfZFzq!Kc1hvihYe{
> zrb19})&9Lo4_qU^wzgG2m~XLe`<FM~4{XJ4k6LniIj?b7-#)*9Tf|y{>*l!)AJ?r|
> zAk3HU`h4*=7SVr+#(RS|M;SeyRbk{c`}N5?5lg?Ux0riMGQRL|@vMJ~w=dO|G_4O<
> zIX#B^9?wN3D~q`8&w4y3+jaW2Y5iKA|K(e5TA|3_GsgO!mt#)+J}J%r{Oz>0Z+D%v
> r+csxO(U<?<17g%R%;nqRxqMNa$MxPw$qx}TRjdTX`wm?1dcz9<2x(B#
>
> literal 0
> HcmV?d00001
>
> diff --git a/test/py/tests/test_efi_capsule/SIGNER.key b/test/py/tests/test_efi_capsule/SIGNER.key
> new file mode 100644
> index 000000000000..9952647ed74a
> --- /dev/null
> +++ b/test/py/tests/test_efi_capsule/SIGNER.key
> @@ -0,0 +1,28 @@
> +-----BEGIN PRIVATE KEY-----
> +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDAbms19vItMuC9
> +JaCWCTrZbxeXlm+LW8e88HouXCqEs0GIsYp0tdDq1cu8vJhC8lzpRjjrDOdPb876
> +ImtJ338BD7L0wXkt5XtiQc/Yjf/gCKPoFJs4BD0Dfo6frOH4tMs0b6twYFrtXoKN
> +oBMcUOwHj0B6EpF/FHgtym+0hWvCrf06KTrqWXxLmfhLaMTwOCVErRYBFBHESRH6
> +UKhAl1fpSqnMqh3NmVMzIrLvouaJpJ3l/LBGXSDxbEhmpwsmNxfVY1syMaOtD1Ns
> +VATiHBFIOZbkflV0+NPdIP8gsPD0n/ayCoBiEEkCgJVEnO87l0CHYCDE0tcVKXPz
> +cfkqljWRAgMBAAECggEAItLYrAdohC105kXs7bn14GtuRYx/2yRc3SBXvBQJzcHy
> +1h3rBHvytszB9gHbPCJIFh8TJdZL9eAyAKpB6Dh9718773cjyt6AmaN3TaVE7PIj
> +V1iDTnvV3tAEV3kd27g8Hd0nlUqaqeI0lhSl4LX0QNn3vR+nHOxDY2YDGRQcEDrD
> +4hlCIGzAfbCW9gINdadQnC6p9NEBbfJ18doCagdn1Q1UYs8YlWwhBK98wXKGsG6T
> +TUywOWIe6+VJqzSwZn5YkDVD3qD4tToar7T0jrCvZjbTbOsjtinD70c3uBcrK/XN
> +gpwJfTiDLo1d0tNoWCRUH0myMs1fq3H3SkdfqB1GwQKBgQDrw8FwUc3Q+j8YhR7i
> +73H/osk3VOZhCPsqbrQThUo5ZV4EXqp9E3PLN5E3suWgfaXVCEI3lHARUyR+J+E/
> +evIrUUnkIryLdVOwwEWRonW4cLANjLSzT0eA85CFLXKUaij7Jfon2YNs9CmUARnC
> +M96T3a89XOezX/SbRVz6X8KslQKBgQDQ8onkHcscHMANIjgxycIgYF+MvxwHRICA
> +nt3ZSQiGSXJbWK7/sM5yd16ulvsXL7aF9G+q5osOzDWJ0w4SOhqNDfItrFH34Px6
> +qEPjq/sAigqqrQls7uu7MHfkE+eEy181CoT9argxo8ifAQDn4YtXBW6L7p6AgaAx
> +83FAbBcqDQKBgQClHk185534zTqhZqIyF7bEbfL0sJ5EuXCG0E+IGGLafdbxwocu
> +4A/J9Jnc44sU8srQv1745Bn02EEHpdCIkAfJNL5Ga9mW5k39zTsr+xbtXObAJppr
> +touCkZLW4vSLYypecsOXYyw7g2kXQgoTTBaHgsv3cvjHVN3QXSz4IVcLXQJ/LBL9
> +AyFFtqhZ2mtdbyMfz7SEcyvcvau1b2wTX8IICktz09DhGQ4yffKwBiPS0xE9bwQg
> +iewXaQeqQ2hBj5ayAw7uBrRSlfbfSwAzUdL1Hyf/GAFn+5JqJxISOAn6zAgaDRYq
> +90mLkOz7ZI7RohfxTGnY56ttw62UHPU87lneiQKBgHcVituUDJgmbaHXx2IVzKsm
> +5uDyXUf4S+tY5CZj6WTsb70+q4PYfh1D02nZgxuLNwpwNI0uhLIkLYHcL3poOapC
> +LCXS8tsexNosmrTmjHFh/uNdKb7bKbMxyzYrr+ADKMclF3CJzKDzLfiIe9Na+bWa
> +q5/HYNIw5zJyapPksgr4
> +-----END PRIVATE KEY-----
> diff --git a/test/py/tests/test_efi_capsule/SIGNER2.crt b/test/py/tests/test_efi_capsule/SIGNER2.crt
> new file mode 100644
> index 000000000000..8889a3ed930a
> --- /dev/null
> +++ b/test/py/tests/test_efi_capsule/SIGNER2.crt
> @@ -0,0 +1,19 @@
> +-----BEGIN CERTIFICATE-----
> +MIIDDTCCAfWgAwIBAgIUfmZcui7VkJEe9jx25Epo6jJ6l+owDQYJKoZIhvcNAQEL
> +BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
> +NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
> +AQEBBQADggEPADCCAQoCggEBANozXTFKGVx0121MIBoSgxfI8IHcfY32T/LQusse
> +PaXsm0GaJNwOgEP34u1k0cz466swfBCqTcZRjKuDpcH1sgrF1XaKjxuwYuiJrbsf
> +ykVesN1z1bIamkFdVR/CBJEwN/epsyCBQCSbcxUwEX+ayq2zp+kSweew1B4i3u8f
> +nbqFB15Rt+KAzFaBlvOJhmoZP7uYtb8zHa58eteaxQmPFt3v6eEbgOt92oVB8fPQ
> +JJBuxUAHdimMDQ9mBGUosXR8PFyma5jOiOyY+0oTfig4bRHbGxCGMYyABJDH+j4e
> +7Zl7lVMsq2fTm/lGONRX2QPLfMO298pz/wundJmYhseibvUCAwEAAaNTMFEwHQYD
> +VR0OBBYEFDPYxE3oBmU1pWrZpY62JuXgcK5aMB8GA1UdIwQYMBaAFDPYxE3oBmU1
> +pWrZpY62JuXgcK5aMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
> +AEtY9QnvTvgmXmep7AMv/T6+GpERvsRdi+Lc+16L7uSCQhouDkeu5/sUHax6icX1
> +NyDb3u6tyQhMnm7CD+7Mo74wrZ4vK2SzBoZSBLi+Tyz2ScyysdRIo7O42nxVyWm7
> +ifZVfQKvanUjDSxPO89yJDYp0znvVpuZOzYXFHdprHoR5Atkth11HFHzWDzqblKS
> +sx145wgPZ9bYohuOn1weyORsG9bJcHznPyJ1ceAOFk40bKWWLQtruWIhY4aZIlJN
> +cDKv92rtgVApaamu+WRC4pzgQMQYKOcnMz4ZKeOKgEajfo6nOUVrvc0IYO6wixvi
> +V+Msrg5o7ag2SN2AHg5/1/4=
> +-----END CERTIFICATE-----
> diff --git a/test/py/tests/test_efi_capsule/SIGNER2.key b/test/py/tests/test_efi_capsule/SIGNER2.key
> new file mode 100644
> index 000000000000..ee467fd9f7a6
> --- /dev/null
> +++ b/test/py/tests/test_efi_capsule/SIGNER2.key
> @@ -0,0 +1,28 @@
> +-----BEGIN PRIVATE KEY-----
> +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDaM10xShlcdNdt
> +TCAaEoMXyPCB3H2N9k/y0LrLHj2l7JtBmiTcDoBD9+LtZNHM+OurMHwQqk3GUYyr
> +g6XB9bIKxdV2io8bsGLoia27H8pFXrDdc9WyGppBXVUfwgSRMDf3qbMggUAkm3MV
> +MBF/msqts6fpEsHnsNQeIt7vH526hQdeUbfigMxWgZbziYZqGT+7mLW/Mx2ufHrX
> +msUJjxbd7+nhG4DrfdqFQfHz0CSQbsVAB3YpjA0PZgRlKLF0fDxcpmuYzojsmPtK
> +E34oOG0R2xsQhjGMgASQx/o+Hu2Ze5VTLKtn05v5RjjUV9kDy3zDtvfKc/8Lp3SZ
> +mIbHom71AgMBAAECggEBAJXskO3bAg364kJg+fWwHo7rLAWuYD54rXojXRVPFAC7
> +z/mFVio1dIA/BJcknNr/db5MNBKnUYUgZ005yVy52rl4MTGgBrB5w5wPbWWTdEGx
> +zEh83KnhiXe8D08g2k6AGRR8b224IUCF5s76FivdScGMHaURlFYDs9t5DkCzMocC
> +ty0ewHv9aeMSzJl4y+DrRw+NkkAntlAkerCI5PInFtxyOQ6lFIRkMKlBA//VL0QF
> +B9yGbmfoxlErWCqnj70DTcVO7O2AaijU+FTMRbb/V7r34GPU0Cfeum6gGNOtDkaX
> +3UnWGR2esiHViMqz8vvEYtVIxHhLTD7INqDlK/yiNEECgYEA+ua1JcHXI2qS3cV/
> +BuVvBrd3MzIpZvddCcTdo/B7WT3EoTupEG1gcajrCuNQDtRoizSbMuhCXYoMsktF
> +wXFoTWoGr8yO7uVU5r2nCXZneprV3kuQmR0qYipN2GTCGSE1rKQI+YXeALPF1qIp
> +12vUVdzWVDJvlQRMvSTlzpRZQkkCgYEA3qKI1ZsBszKPbnzLX91+ZAZeAwwN/HvS
> +nrIveJAci/9U2yV2mw3l/Dulc8EkGABs/cMp47toje8DmsSfdu1yIYqpi3MHvefX
> ++ijc3ry5v28Hia3WP3WPczqhbkT7cco0t8Vwm9w1B+kkreuRCtyoCOLsRauB0CH1
> +QJjMtPAth00CgYAKUUhruA/nxe8qLX/uwaqSJSNCuLJZKJzr1OukXTRFVDPsyW5H
> +XagUpHSd6wEUywlNiClFq6VnAVFKV6wTq101qcGCoy/RhR67qlrfGb5hnVJkJMla
> +coeWp9SxrFsK+4GgitJPqICbmMju7ZY45JdDvKQXrEdIYnfhY04L86/D+QKBgBxx
> +nZPU0vnHCuYt0Xn0/XHgEmDHSH4qf7VAxKndl5gXTgsVlTqoIur/39qTIX5jh4lA
> +RvjOd8Qydj5uwoTaP0ujwJeNYb7UgRZ35AgdCoo3sDnZ2NaQuXwaUIebDpjyIZwd
> +AI8ZKjlRgxspToWZvWotO8yG5fXmcMQJAZZYXSi9AoGBALfXX/C5ojwms1l+XP+p
> +FKzOFZ/uEKPfQid+2Sm1BknXXGVbs3zJ4OdonTvhjq+VQvXTW4IvjgY8TpumQZvE
> +8nb7I8E1B6ajkSvgfetN9jlKM5hzIfJ3Vxx6hMGMab1ySKy3rZGPL706CW2BeMI2
> +v2k9P0qWItuE4S7I4hEsovwS
> +-----END PRIVATE KEY-----
> diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py
> index 4fd6353c2040..aa9bf5eee3aa 100644
> --- a/test/py/tests/test_efi_capsule/capsule_defs.py
> +++ b/test/py/tests/test_efi_capsule/capsule_defs.py
> @@ -3,3 +3,8 @@
>   # Directories
>   CAPSULE_DATA_DIR = '/EFI/CapsuleTestData'
>   CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule'
> +
> +# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and
> +# you need build a newer version on your own.
> +# The path must terminate with '/'.
> +EFITOOLS_PATH = ''
> diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
> index 6ad5608cd71c..35cfa5513703 100644
> --- a/test/py/tests/test_efi_capsule/conftest.py
> +++ b/test/py/tests/test_efi_capsule/conftest.py
> @@ -10,13 +10,13 @@ import pytest
>   from capsule_defs import *
>
>   #
> -# Fixture for UEFI secure boot test
> +# Fixture for UEFI capsule test
>   #
>
> -
>   @pytest.fixture(scope='session')
>   def efi_capsule_data(request, u_boot_config):
> -    """Set up a file system to be used in UEFI capsule test.
> +    """Set up a file system to be used in UEFI capsule and
> +       authentication test.
>
>       Args:
>           request: Pytest request object.
> @@ -40,6 +40,22 @@ def efi_capsule_data(request, u_boot_config):
>           check_call('mkdir -p %s' % data_dir, shell=True)
>           check_call('mkdir -p %s' % install_dir, shell=True)
>
> +        capsule_auth_enabled = u_boot_config.buildconfig.get(
> +                    'config_efi_capsule_authenticate')
> +        # NOTE:
> +        # private keys (SIGNER?.key) dn certificates (SIGNER?.crt)
> +        # in this pytest directory are created this way:
> +        # Create private key (SIGNER.key) and certificate (SIGNER.crt)
> +        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER.key -out SIGNER.crt -nodes -days 365'
> +        #               % data_dir, shell=True)
> +        #    check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl'
> +        #               % (data_dir, EFITOOLS_PATH), shell=True)
> +
> +        # Create *malicious* private key (SIGNER2.key) and certificate
> +        # (SIGNER2.crt)
> +        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER2.key -out SIGNER2.crt -nodes -days 365'
> +        #               % data_dir, shell=True)
> +
>           # Create capsule files
>           # two regions: one for u-boot.bin and the other for u-boot.env
>           check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old -> u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
> @@ -56,6 +72,19 @@ def efi_capsule_data(request, u_boot_config):
>           check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 Test02' %
>                      (data_dir, u_boot_config.build_dir),
>                      shell=True)
> +        if capsule_auth_enabled:
> +            # copy keys/certificates
> +            check_call('cp %s/test/py/tests/test_efi_capsule/SIGNER*.* %s' %
> +                       (u_boot_config.source_dir, data_dir),
> +                       shell=True)
> +            # firmware signed with proper key
> +            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER.key --certificate SIGNER.crt Test03' %
> +                       (data_dir, u_boot_config.build_dir),
> +                       shell=True)
> +            # firmware signed with *mal* key
> +            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER2.key --certificate SIGNER2.crt Test04' %
> +                       (data_dir, u_boot_config.build_dir),
> +                       shell=True)
>
>           # Create a disk image with EFI system partition
>           check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
> diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> new file mode 100644
> index 000000000000..8fe93ef424ac
> --- /dev/null
> +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> @@ -0,0 +1,228 @@
> +# SPDX-License-Identifier:      GPL-2.0+
> +# Copyright (c) 2021, Linaro Limited
> +# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> +#
> +# U-Boot UEFI: Firmware Update (Signed capsule) Test
> +
> +"""
> +This test verifies capsule-on-disk firmware update
> +with signed capsule files
> +"""
> +
> +from subprocess import check_call, check_output, CalledProcessError
> +import pytest
> +from capsule_defs import *
> +
> +@pytest.mark.boardspec('sandbox')
> +@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
> +@pytest.mark.buildconfigspec('efi_capsule_authenticate')
> +@pytest.mark.buildconfigspec('dfu')
> +@pytest.mark.buildconfigspec('dfu_sf')
> +@pytest.mark.buildconfigspec('cmd_efidebug')
> +@pytest.mark.buildconfigspec('cmd_fat')
> +@pytest.mark.buildconfigspec('cmd_memory')
> +@pytest.mark.buildconfigspec('cmd_nvedit_efi')
> +@pytest.mark.buildconfigspec('cmd_sf')
> +@pytest.mark.slow
> +class TestEfiCapsuleFirmwareSigned(object):
> +    def test_efi_capsule_auth1(
> +            self, u_boot_config, u_boot_console, efi_capsule_data):
> +        """
> +        Test Case 1 - Update U-Boot on SPI Flash, raw image format
> +                      0x100000-0x150000: U-Boot binary (but dummy)
> +
> +                      If the capsule is properly signed, the authentication
> +                      should pass and the firmware be updated.
> +        """
> +        disk_img = efi_capsule_data
> +        with u_boot_console.log.section('Test Case 1-a, before reboot'):
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> +                'efidebug boot order 1',
> +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                'env save'])
> +
> +            # initialize content
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> +                'sf write 4000000 100000 10',
> +                'sf read 5000000 100000 10',
> +                'md.b 5000000 10'])
> +            assert 'Old' in ''.join(output)
> +
> +            # place a capsule file
> +            output = u_boot_console.run_command_list([
> +                'fatload host 0:1 4000000 %s/Test03' % CAPSULE_DATA_DIR,
> +                'fatwrite host 0:1 4000000 %s/Test03 $filesize' % CAPSULE_INSTALL_DIR,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test03' in ''.join(output)
> +
> +        # reboot
> +        u_boot_console.restart_uboot()
> +
> +        capsule_early = u_boot_config.buildconfig.get(
> +            'config_efi_capsule_on_disk_early')
> +        with u_boot_console.log.section('Test Case 1-b, after reboot'):
> +            if not capsule_early:
> +                # make sure that dfu_alt_info exists even persistent variables
> +                # are not available.
> +                output = u_boot_console.run_command_list([
> +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                    'host bind 0 %s' % disk_img,
> +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +                assert 'Test03' in ''.join(output)
> +
> +                # need to run uefi command to initiate capsule handling
> +                output = u_boot_console.run_command(
> +                    'env print -e Capsule0000')
> +
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test03' not in ''.join(output)
> +
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'sf read 4000000 100000 10',
> +                'md.b 4000000 10'])
> +            assert 'u-boot:New' in ''.join(output)
> +
> +    def test_efi_capsule_auth2(
> +            self, u_boot_config, u_boot_console, efi_capsule_data):
> +        """
> +        Test Case 2 - Update U-Boot on SPI Flash, raw image format
> +                      0x100000-0x150000: U-Boot binary (but dummy)
> +
> +                      If the capsule is signed but with an invalid key,
> +                      the authentication should fail and the firmware
> +                      not be updated.
> +        """
> +        disk_img = efi_capsule_data
> +        with u_boot_console.log.section('Test Case 2-a, before reboot'):
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> +                'efidebug boot order 1',
> +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                'env save'])
> +
> +            # initialize content
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> +                'sf write 4000000 100000 10',
> +                'sf read 5000000 100000 10',
> +                'md.b 5000000 10'])
> +            assert 'Old' in ''.join(output)
> +
> +            # place a capsule file
> +            output = u_boot_console.run_command_list([
> +                'fatload host 0:1 4000000 %s/Test04' % CAPSULE_DATA_DIR,
> +                'fatwrite host 0:1 4000000 %s/Test04 $filesize' % CAPSULE_INSTALL_DIR,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test04' in ''.join(output)
> +
> +        # reboot
> +        u_boot_console.restart_uboot()
> +
> +        capsule_early = u_boot_config.buildconfig.get(
> +            'config_efi_capsule_on_disk_early')
> +        with u_boot_console.log.section('Test Case 2-b, after reboot'):
> +            if not capsule_early:
> +                # make sure that dfu_alt_info exists even persistent variables
> +                # are not available.
> +                output = u_boot_console.run_command_list([
> +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                    'host bind 0 %s' % disk_img,
> +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +                assert 'Test04' in ''.join(output)
> +
> +                # need to run uefi command to initiate capsule handling
> +                output = u_boot_console.run_command(
> +                    'env print -e Capsule0000')
> +
> +            # deleted any way
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test04' not in ''.join(output)
> +
> +            # TODO: check CapsuleStatus in CapsuleXXXX
> +
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'sf read 4000000 100000 10',
> +                'md.b 4000000 10'])
> +            assert 'u-boot:Old' in ''.join(output)
> +
> +    def test_efi_capsule_auth3(
> +            self, u_boot_config, u_boot_console, efi_capsule_data):
> +        """
> +        Test Case 3 - Update U-Boot on SPI Flash, raw image format
> +                      0x100000-0x150000: U-Boot binary (but dummy)
> +
> +                      If the capsule is not signed, the authentication
> +                      should fail and the firmware not be updated.
> +        """
> +        disk_img = efi_capsule_data
> +        with u_boot_console.log.section('Test Case 3-a, before reboot'):
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> +                'efidebug boot order 1',
> +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                'env save'])
> +
> +            # initialize content
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> +                'sf write 4000000 100000 10',
> +                'sf read 5000000 100000 10',
> +                'md.b 5000000 10'])
> +            assert 'Old' in ''.join(output)
> +
> +            # place a capsule file
> +            output = u_boot_console.run_command_list([
> +                'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
> +                'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test02' in ''.join(output)
> +
> +        # reboot
> +        u_boot_console.restart_uboot()
> +
> +        capsule_early = u_boot_config.buildconfig.get(
> +            'config_efi_capsule_on_disk_early')
> +        with u_boot_console.log.section('Test Case 3-b, after reboot'):
> +            if not capsule_early:
> +                # make sure that dfu_alt_info exists even persistent variables
> +                # are not available.
> +                output = u_boot_console.run_command_list([
> +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> +                    'host bind 0 %s' % disk_img,
> +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +                assert 'Test02' in ''.join(output)
> +
> +                # need to run uefi command to initiate capsule handling
> +                output = u_boot_console.run_command(
> +                    'env print -e Capsule0000')
> +
> +            # deleted any way
> +            output = u_boot_console.run_command_list([
> +                'host bind 0 %s' % disk_img,
> +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> +            assert 'Test02' not in ''.join(output)
> +
> +            # TODO: check CapsuleStatus in CapsuleXXXX
> +
> +            output = u_boot_console.run_command_list([
> +                'sf probe 0:0',
> +                'sf read 4000000 100000 10',
> +                'md.b 4000000 10'])
> +            assert 'u-boot:Old' in ''.join(output)
>


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

* Re: [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support
  2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
                   ` (8 preceding siblings ...)
  2021-07-27  9:10 ` [PATCH v2 9/9] test/py: efi_capsule: align with the syntax change of mkeficapsule AKASHI Takahiro
@ 2021-08-01  9:40 ` Heinrich Schuchardt
  2021-08-02  5:00   ` AKASHI Takahiro
  9 siblings, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-01  9:40 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg
  Cc: ilias.apalodimas, sughosh.ganu, masami.hiramatsu, u-boot

On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> As I proposed and discussed in [1] and [2], I have made a couple of
> improvements on the current implementation of capsule update in this
> patch set.
>
> * add signing feature to mkeficapsule
> * add "--guid" option to mkeficapsule
> * add man page of mkeficapsule
> * add pytest for capsule authentication (on sandbox)
>
> NOTE:
> Due to Ilias's commit[3], we need to have a customized configuration
> for sandbox to properly set up and run capsule authentication test.
> See patch#5,#6 and #7.
>
> [1] https://lists.denx.de/pipermail/u-boot/2021-April/447918.html
> [2] https://lists.denx.de/pipermail/u-boot/2021-July/455292.html
> [3] commit ddf67daac39d ("efi_capsule: Move signature from DTB to
>      .rodata")


Dear Takahiro,

thanks for driving this topic. I have finished with my review and will
be waiting for v2.

Best regards

Heinrich

>
> Prerequisite patches
> ====================
> None
>
> Test
> ====
> * locally passed the pytest which is included in this patch series
>    on sandbox built.
>
> Todo
> ====
> * Confirm that the change in .gitlab-ci.yml works.
> * Azure support(?)
>
> Changes
> =======
> v2 (July 28, 2021)
> * rebased on v2021.10-rc*
> * removed dependency on target's configuration
> * removed fdtsig.sh and others
> * add man page
> * update the UEFI document
> * add dedicate defconfig for testing on sandbox
> * add gitlab CI support
> * add "--guid" option to mkeficapsule
>    (yet rather RFC)
>
> Initial release (May 12, 2021)
> * based on v2021.07-rc2
>
> AKASHI Takahiro (9):
>    tools: mkeficapsule: add firmwware image signing
>    tools: mkeficapsule: add man page
>    doc: update UEFI document for usage of mkeficapsule
>    efi_loader: ease the file path check for public key
>    test/py: efi_capsule: add image authentication test
>    sandbox: add config for efi capsule authentication test
>    GitLab: add a test rule for efi capsule authentication test
>    tools: mkeficapsule: allow for specifying GUID explicitly
>    test/py: efi_capsule: align with the syntax change of mkeficapsule
>
>   .gitlab-ci.yml                                |   6 +
>   MAINTAINERS                                   |   1 +
>   configs/sandbox_capsule_auth_defconfig        | 307 +++++++++++++++
>   doc/develop/uefi/uefi.rst                     |  31 +-
>   doc/mkeficapsule.1                            |  98 +++++
>   lib/efi_loader/Makefile                       |   5 +-
>   test/py/tests/test_efi_capsule/SIGNER.crt     |  19 +
>   test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
>   test/py/tests/test_efi_capsule/SIGNER.key     |  28 ++
>   test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 +
>   test/py/tests/test_efi_capsule/SIGNER2.key    |  28 ++
>   .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
>   test/py/tests/test_efi_capsule/conftest.py    |  39 +-
>   .../test_capsule_firmware_signed.py           | 228 +++++++++++
>   tools/Kconfig                                 |   7 +
>   tools/Makefile                                |   8 +-
>   tools/mkeficapsule.c                          | 368 ++++++++++++++++--
>   17 files changed, 1129 insertions(+), 68 deletions(-)
>   create mode 100644 configs/sandbox_capsule_auth_defconfig
>   create mode 100644 doc/mkeficapsule.1
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
>   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
>   create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
>


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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-08-01  4:29     ` AKASHI Takahiro
@ 2021-08-01 19:00       ` Simon Glass
  2021-08-01 22:57         ` AKASHI Takahiro
  0 siblings, 1 reply; 30+ messages in thread
From: Simon Glass @ 2021-08-01 19:00 UTC (permalink / raw)
  To: AKASHI Takahiro, Simon Glass, Heinrich Schuchardt, Alex Graf,
	Tom Rini, Ilias Apalodimas, Sughosh Ganu, Masami Hiramatsu,
	U-Boot Mailing List

Hi Takahiro,

On Sat, 31 Jul 2021 at 22:29, AKASHI Takahiro
<takahiro.akashi@linaro.org> wrote:
>
> Simon,
>
> On Sat, Jul 31, 2021 at 10:59:32AM -0600, Simon Glass wrote:
> > Hi Takahiro,
> >
> > On Tue, 27 Jul 2021 at 03:12, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > This new configuration, which was derived from sandbox_defconfig, will be
> > > used solely to run efi capsule authentication test as the test requires
> > > a public key (esl file) to be embedded in U-Boot binary.
> > >
> > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > ---
> > >  configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
> > >  1 file changed, 307 insertions(+)
> > >  create mode 100644 configs/sandbox_capsule_auth_defconfig
> >
> > NAK.
> >
> > Please just add it to sandbox_defconfig. We sometimes have to create
>
> Unfortunately, I can't.
> Look, we now have two tests, test_capsule_firmware.py and
> test_capsule_firmware_signed.py, and we need U-Boot binaries,
> respectively, without a key and with a key.
> A single configuration cannot satisfy both.
>
> > new variants when dealing with actual build variations (e.g. SPL,
> > building without OF_LIVE), but here we should just enable the feature
> > in sandbox_defconfig.
> >
> > We already covered embedding key in the binary on another thread.
> > Please don't do that. After that debacle I sent a patch explaining
> > this:
> >
> > http://patchwork.ozlabs.org/project/uboot/patch/20210725164400.468319-3-sjg@chromium.org/
>
> Please discuss and make an agreement with Heinrich.
> The patch for embedding a key has already been merged in -rc1.

Which patch was that? I thought I pushed back on the one that did that.

> In my personal opinion, neither approaches won't apply to production
> any way.

Regards,
Simon

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-08-01 19:00       ` Simon Glass
@ 2021-08-01 22:57         ` AKASHI Takahiro
  2021-08-02 19:19           ` Simon Glass
  0 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-01 22:57 UTC (permalink / raw)
  To: Simon Glass
  Cc: Heinrich Schuchardt, Alex Graf, Tom Rini, Ilias Apalodimas,
	Sughosh Ganu, Masami Hiramatsu, U-Boot Mailing List

Simon,

On Sun, Aug 01, 2021 at 01:00:20PM -0600, Simon Glass wrote:
> Hi Takahiro,
> 
> On Sat, 31 Jul 2021 at 22:29, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
> >
> > Simon,
> >
> > On Sat, Jul 31, 2021 at 10:59:32AM -0600, Simon Glass wrote:
> > > Hi Takahiro,
> > >
> > > On Tue, 27 Jul 2021 at 03:12, AKASHI Takahiro
> > > <takahiro.akashi@linaro.org> wrote:
> > > >
> > > > This new configuration, which was derived from sandbox_defconfig, will be
> > > > used solely to run efi capsule authentication test as the test requires
> > > > a public key (esl file) to be embedded in U-Boot binary.
> > > >
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > ---
> > > >  configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
> > > >  1 file changed, 307 insertions(+)
> > > >  create mode 100644 configs/sandbox_capsule_auth_defconfig
> > >
> > > NAK.
> > >
> > > Please just add it to sandbox_defconfig. We sometimes have to create
> >
> > Unfortunately, I can't.
> > Look, we now have two tests, test_capsule_firmware.py and
> > test_capsule_firmware_signed.py, and we need U-Boot binaries,
> > respectively, without a key and with a key.
> > A single configuration cannot satisfy both.
> >
> > > new variants when dealing with actual build variations (e.g. SPL,
> > > building without OF_LIVE), but here we should just enable the feature
> > > in sandbox_defconfig.
> > >
> > > We already covered embedding key in the binary on another thread.
> > > Please don't do that. After that debacle I sent a patch explaining
> > > this:
> > >
> > > http://patchwork.ozlabs.org/project/uboot/patch/20210725164400.468319-3-sjg@chromium.org/
> >
> > Please discuss and make an agreement with Heinrich.
> > The patch for embedding a key has already been merged in -rc1.
> 
> Which patch was that? I thought I pushed back on the one that did that.

The commit ddf67daac39d
  Author: Ilias Apalodimas <ilias.apalodimas@linaro.org>
  Date:   Sat Jul 17 17:26:44 2021 +0300

    efi_capsule: Move signature from DTB to .rodata

-Takahiro Akashi


> > In my personal opinion, neither approaches won't apply to production
> > any way.
> 
> Regards,
> Simon

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

* Re: [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-08-01  9:21   ` Heinrich Schuchardt
@ 2021-08-02  3:30     ` AKASHI Takahiro
  2021-08-02  6:18       ` Heinrich Schuchardt
  0 siblings, 1 reply; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-02  3:30 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

Heinrich,

On Sun, Aug 01, 2021 at 11:21:55AM +0200, Heinrich Schuchardt wrote:
> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > With this enhancement, mkeficapsule will be able to sign a capsule
> > file when it is created. A signature added will be used later
> > in the verification at FMP's SetImage() call.
> > 
> > To do that, We need specify additional command parameters:
> >    -monotonic-cout <count> : monotonic count
> >    -private-key <private key file> : private key file
> >    -certificate <certificate file> : certificate file
> > Only when all of those parameters are given, a signature will be added
> > to a capsule file.
> > 
> > Users are expected to maintain and increment the monotonic count at
> > every time of the update for each firmware image.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >   tools/Kconfig        |   7 +
> >   tools/Makefile       |   8 +-
> >   tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
> >   3 files changed, 316 insertions(+), 31 deletions(-)
> > 
> > diff --git a/tools/Kconfig b/tools/Kconfig
> > index d6f82cd949b5..9a37ed035311 100644
> > --- a/tools/Kconfig
> > +++ b/tools/Kconfig
> > @@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
> >   	  This selection does not affect target features, such as runtime FIT
> >   	  signature verification.
> > 
> > +config TOOLS_MKEFICAPSULE
> > +	bool "Build efimkcapsule command"
> > +	default y if EFI_CAPSULE_ON_DISK
> > +	help
> > +	  This command allows users to create a UEFI capsule file and,
> > +	  optionally sign that file. If you want to enable UEFI capsule
> > +	  update feature on your target, you certainly need this.
> >   endmenu
> > diff --git a/tools/Makefile b/tools/Makefile
> > index bae3f95c4995..af8536489652 100644
> > --- a/tools/Makefile
> > +++ b/tools/Makefile
> > @@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
> >   hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
> >   HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
> > 
> > -mkeficapsule-objs	:= mkeficapsule.o $(LIBFDT_OBJS)
> > -hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
> > +HOSTLDLIBS_mkeficapsule += -luuid
> > +ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
> > +HOSTLDLIBS_mkeficapsule += \
> > +	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
> 
> Please, add package pkg-config to the build dependencies enumerated in
> doc/build/gcc.rst.

Already there: libssl-dev

> > +endif
> > +hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
> > 
> >   # We build some files with extra pedantic flags to try to minimize things
> >   # that won't build on some weird host compiler -- though there are lots of
> > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> > index 4995ba4e0c2a..798706c7b5f7 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -15,6 +15,16 @@
> >   #include <sys/stat.h>
> >   #include <sys/types.h>
> > 
> > +#include <linux/kconfig.h>
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +#include <openssl/asn1.h>
> > +#include <openssl/bio.h>
> > +#include <openssl/evp.h>
> > +#include <openssl/err.h>
> > +#include <openssl/pem.h>
> > +#include <openssl/pkcs7.h>
> > +#endif
> > +
> >   typedef __u8 u8;
> >   typedef __u16 u16;
> >   typedef __u32 u32;
> > @@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
> >   		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
> >   efi_guid_t efi_guid_image_type_uboot_raw =
> >   		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
> > +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> > +
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
> > +#else
> > +static const char *opts_short = "f:r:i:I:v:h";
> > +#endif
> > 
> >   static struct option options[] = {
> >   	{"fit", required_argument, NULL, 'f'},
> >   	{"raw", required_argument, NULL, 'r'},
> >   	{"index", required_argument, NULL, 'i'},
> >   	{"instance", required_argument, NULL, 'I'},
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +	{"private-key", required_argument, NULL, 'p'},
> > +	{"certificate", required_argument, NULL, 'c'},
> > +	{"monotonic-count", required_argument, NULL, 'm'},
> > +	{"dump-sig", no_argument, NULL, 'd'},
> > +#endif
> >   	{"help", no_argument, NULL, 'h'},
> >   	{NULL, 0, NULL, 0},
> >   };
> > @@ -57,16 +80,195 @@ static void print_usage(void)
> >   	       "\t-r, --raw <raw image>       new raw image file\n"
> >   	       "\t-i, --index <index>         update image index\n"
> >   	       "\t-I, --instance <instance>   update hardware instance\n"
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +	       "\t-p, --private-key <privkey file>  private key file\n"
> > +	       "\t-c, --certificate <cert file>     signer's certificate file\n"
> > +	       "\t-m, --monotonic-count <count>     monotonic count\n"
> > +	       "\t-d, --dump_sig              dump signature (*.p7)\n"
> > +#endif
> >   	       "\t-h, --help                  print a help message\n",
> >   	       tool_name);
> >   }
> > 
> 
> Please, add Sphinx documentation.

I added the man page. Why need another different format of doc?
I think that doc/develop/uefi/uefi.rst gives you an enough
introduction to the command.
(Although the doc will have to been updated due to the latest change
of mkeficapsule syntax that I'm also proposing.)

Actually, there is no sphinx doc for any host tools.

> > +struct auth_context {
> > +	char *key_file;
> > +	char *cert_file;
> > +	u8 *image_data;
> > +	size_t image_size;
> > +	struct efi_firmware_image_authentication auth;
> > +	u8 *sig_data;
> > +	size_t sig_size;
> > +};
> > +
> > +static int dump_sig;
> > +
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +static EVP_PKEY *fileio_read_pkey(const char *filename)
> > +{
> > +	EVP_PKEY *key = NULL;
> > +	BIO *bio;
> > +
> > +	bio = BIO_new_file(filename, "r");
> > +	if (!bio)
> > +		goto out;
> > +
> > +	key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
> > +
> > +out:
> > +	BIO_free_all(bio);
> > +	if (!key) {
> > +		printf("Can't load key from file '%s'\n", filename);
> > +		ERR_print_errors_fp(stderr);
> > +	}
> > +
> > +	return key;
> > +}
> > +
> 
> Please, add Sphinx documentation for all functions.

Yeah, but "all" is a too forcible requirement.
There is no source code of host tools to meet the requirement.
Actually, most don't have even one description of a function.

I think that, if it is a really required element in the source,
it should be explicitly described somewhere under "doc". 

> > +static X509 *fileio_read_cert(const char *filename)
> > +{
> > +	X509 *cert = NULL;
> > +	BIO *bio;
> > +
> > +	bio = BIO_new_file(filename, "r");
> > +	if (!bio)
> > +		goto out;
> > +
> > +	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
> > +
> > +out:
> > +	BIO_free_all(bio);
> > +	if (!cert) {
> > +		printf("Can't load certificate from file '%s'\n", filename);
> > +		ERR_print_errors_fp(stderr);
> > +	}
> > +
> > +	return cert;
> > +}
> > +
> > +static int create_auth_data(struct auth_context *ctx)
> > +{
> > +	EVP_PKEY *key = NULL;
> > +	X509 *cert = NULL;
> > +	BIO *data_bio = NULL;
> > +	const EVP_MD *md;
> > +	PKCS7 *p7;
> > +	int flags, ret = -1;
> > +
> > +	OpenSSL_add_all_digests();
> > +	OpenSSL_add_all_ciphers();
> > +	ERR_load_crypto_strings();
> > +
> > +	key = fileio_read_pkey(ctx->key_file);
> > +	if (!key)
> > +		goto err;
> > +	cert = fileio_read_cert(ctx->cert_file);
> > +	if (!cert)
> > +		goto err;
> > +
> > +	/*
> > +	 * create a BIO, containing:
> > +	 *  * firmware image
> > +	 *  * monotonic count
> > +	 * in this order!
> > +	 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
> > +	 */
> > +	data_bio = BIO_new(BIO_s_mem());
> > +	BIO_write(data_bio, ctx->image_data, ctx->image_size);
> > +	BIO_write(data_bio, &ctx->auth.monotonic_count,
> > +		  sizeof(ctx->auth.monotonic_count));
> > +
> > +	md = EVP_get_digestbyname("SHA256");
> > +	if (!md)
> > +		goto err;
> > +
> > +	/* create signature */
> > +	/* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
> > +	flags = PKCS7_BINARY | PKCS7_DETACHED;
> > +	p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
> > +	if (!p7)
> > +		goto err;
> > +	if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
> > +		goto err;
> > +	if (!PKCS7_final(p7, data_bio, flags))
> > +		goto err;
> > +
> > +	/* convert pkcs7 into DER */
> > +	ctx->sig_data = NULL;
> > +	ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
> > +				      ASN1_ITEM_rptr(PKCS7));
> > +	if (!ctx->sig_size)
> > +		goto err;
> > +
> > +	/* fill auth_info */
> > +	ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
> > +						+ ctx->sig_size;
> > +	ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> > +	ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> > +	memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
> > +	       sizeof(efi_guid_cert_type_pkcs7));
> > +
> > +	ret = 0;
> > +err:
> > +	BIO_free_all(data_bio);
> > +	EVP_PKEY_free(key);
> > +	X509_free(cert);
> > +
> > +	return ret;
> > +}
> > +
> > +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> > +{
> > +	char *sig_path;
> > +	FILE *f;
> > +	size_t size;
> > +	int ret = -1;
> > +
> > +	sig_path = malloc(strlen(path) + 3 + 1);
> > +	if (!sig_path)
> > +		return ret;
> > +
> > +	sprintf(sig_path, "%s.p7", path);
> > +	f = fopen(sig_path, "w");
> > +	if (!f)
> > +		goto err;
> > +
> > +	size = fwrite(signature, 1, sig_size, f);
> > +	if (size == sig_size)
> > +		ret = 0;
> > +
> > +	fclose(f);
> > +err:
> > +	free(sig_path);
> > +	return ret;
> > +}
> > +
> > +static void free_sig_data(struct auth_context *ctx)
> > +{
> > +	if (ctx->sig_size)
> > +		OPENSSL_free(ctx->sig_data);
> > +}
> > +#else
> > +static int create_auth_data(struct auth_context *ctx)
> > +{
> > +	return 0;
> > +}
> > +
> > +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> > +{
> > +	return 0;
> > +}
> > +
> > +static void free_sig_data(struct auth_context *ctx) {}
> > +#endif
> > +
> >   static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > -			unsigned long index, unsigned long instance)
> > +			unsigned long index, unsigned long instance,
> > +			uint64_t mcount, char *privkey_file, char *cert_file)
> >   {
> >   	struct efi_capsule_header header;
> >   	struct efi_firmware_management_capsule_header capsule;
> >   	struct efi_firmware_management_capsule_image_header image;
> > +	struct auth_context auth_context;
> >   	FILE *f, *g;
> >   	struct stat bin_stat;
> >   	u8 *data;
> > @@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >   	printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
> >   	printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
> 
> [tools/mkeficapsule.c:281] (warning) %ld in format string (no. 1)
> requires 'long' but the argument type is 'unsigned long'.

Will fix it.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> >   #endif
> > +	auth_context.sig_size = 0;
> > 
> >   	g = fopen(bin, "r");
> >   	if (!g) {
> > @@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >   		printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
> >   		goto err_1;
> >   	}
> > -	f = fopen(path, "w");
> > -	if (!f) {
> > -		printf("cannot open %s\n", path);
> > +
> > +	size = fread(data, 1, bin_stat.st_size, g);
> > +	if (size < bin_stat.st_size) {
> > +		printf("read failed (%zx)\n", size);
> >   		goto err_2;
> >   	}
> > +
> > +	/* first, calculate signature to determine its size */
> > +	if (privkey_file && cert_file) {
> > +		auth_context.key_file = privkey_file;
> > +		auth_context.cert_file = cert_file;
> > +		auth_context.auth.monotonic_count = mcount;
> > +		auth_context.image_data = data;
> > +		auth_context.image_size = bin_stat.st_size;
> > +
> > +		if (create_auth_data(&auth_context)) {
> > +			printf("Signing firmware image failed\n");
> > +			goto err_3;
> > +		}
> > +
> > +		if (dump_sig &&
> > +		    dump_signature(path, auth_context.sig_data,
> > +				   auth_context.sig_size)) {
> > +			printf("Creating signature file failed\n");
> > +			goto err_3;
> > +		}
> > +	}
> > +
> >   	header.capsule_guid = efi_guid_fm_capsule;
> >   	header.header_size = sizeof(header);
> >   	/* TODO: The current implementation ignores flags */
> > @@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >   					+ sizeof(capsule) + sizeof(u64)
> >   					+ sizeof(image)
> >   					+ bin_stat.st_size;
> > +	if (auth_context.sig_size)
> > +		header.capsule_image_size += sizeof(auth_context.auth)
> > +				+ auth_context.sig_size;
> > +
> > +	f = fopen(path, "w");
> > +	if (!f) {
> > +		printf("cannot open %s\n", path);
> > +		goto err_3;
> > +	}
> > 
> >   	size = fwrite(&header, 1, sizeof(header), f);
> >   	if (size < sizeof(header)) {
> >   		printf("write failed (%zx)\n", size);
> > -		goto err_3;
> > +		goto err_4;
> >   	}
> > 
> >   	capsule.version = 0x00000001;
> > @@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >   	size = fwrite(&capsule, 1, sizeof(capsule), f);
> >   	if (size < (sizeof(capsule))) {
> >   		printf("write failed (%zx)\n", size);
> > -		goto err_3;
> > +		goto err_4;
> >   	}
> >   	offset = sizeof(capsule) + sizeof(u64);
> >   	size = fwrite(&offset, 1, sizeof(offset), f);
> >   	if (size < sizeof(offset)) {
> >   		printf("write failed (%zx)\n", size);
> > -		goto err_3;
> > +		goto err_4;
> >   	}
> > 
> >   	image.version = 0x00000003;
> > @@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >   	image.reserved[1] = 0;
> >   	image.reserved[2] = 0;
> >   	image.update_image_size = bin_stat.st_size;
> > +	if (auth_context.sig_size)
> > +		image.update_image_size += sizeof(auth_context.auth)
> > +				+ auth_context.sig_size;
> >   	image.update_vendor_code_size = 0; /* none */
> >   	image.update_hardware_instance = instance;
> >   	image.image_capsule_support = 0;
> > +	if (auth_context.sig_size)
> > +		image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
> > 
> >   	size = fwrite(&image, 1, sizeof(image), f);
> >   	if (size < sizeof(image)) {
> >   		printf("write failed (%zx)\n", size);
> > -		goto err_3;
> > +		goto err_4;
> >   	}
> > -	size = fread(data, 1, bin_stat.st_size, g);
> > -	if (size < bin_stat.st_size) {
> > -		printf("read failed (%zx)\n", size);
> > -		goto err_3;
> > +
> > +	if (auth_context.sig_size) {
> > +		size = fwrite(&auth_context.auth, 1,
> > +			      sizeof(auth_context.auth), f);
> > +		if (size < sizeof(auth_context.auth)) {
> > +			printf("write failed (%zx)\n", size);
> > +			goto err_4;
> > +		}
> > +		size = fwrite(auth_context.sig_data, 1,
> > +			      auth_context.sig_size, f);
> > +		if (size < auth_context.sig_size) {
> > +			printf("write failed (%zx)\n", size);
> > +			goto err_4;
> > +		}
> >   	}
> > +
> >   	size = fwrite(data, 1, bin_stat.st_size, f);
> >   	if (size < bin_stat.st_size) {
> >   		printf("write failed (%zx)\n", size);
> > -		goto err_3;
> > +		goto err_4;
> >   	}
> > 
> >   	fclose(f);
> >   	fclose(g);
> >   	free(data);
> > +	free_sig_data(&auth_context);
> > 
> >   	return 0;
> > 
> > -err_3:
> > +err_4:
> >   	fclose(f);
> > +err_3:
> > +	free_sig_data(&auth_context);
> >   err_2:
> >   	free(data);
> >   err_1:
> > @@ -171,23 +425,25 @@ err_1:
> >   	return -1;
> >   }
> > 
> > -/*
> > - * Usage:
> > - *   $ mkeficapsule -f <firmware binary> <output file>
> > - */
> >   int main(int argc, char **argv)
> >   {
> >   	char *file;
> >   	efi_guid_t *guid;
> >   	unsigned long index, instance;
> > +	uint64_t mcount;
> > +	char *privkey_file, *cert_file;
> >   	int c, idx;
> > 
> >   	file = NULL;
> >   	guid = NULL;
> >   	index = 0;
> >   	instance = 0;
> > +	mcount = 0;
> > +	privkey_file = NULL;
> > +	cert_file = NULL;
> > +	dump_sig = 0;
> >   	for (;;) {
> > -		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
> > +		c = getopt_long(argc, argv, opts_short, options, &idx);
> >   		if (c == -1)
> >   			break;
> > 
> > @@ -214,26 +470,44 @@ int main(int argc, char **argv)
> >   		case 'I':
> >   			instance = strtoul(optarg, NULL, 0);
> >   			break;
> > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > +		case 'p':
> > +			if (privkey_file) {
> > +				printf("Private Key already specified\n");
> > +				return -1;
> > +			}
> > +			privkey_file = optarg;
> > +			break;
> > +		case 'c':
> > +			if (cert_file) {
> > +				printf("Certificate file already specified\n");
> > +				return -1;
> > +			}
> > +			cert_file = optarg;
> > +			break;
> > +		case 'm':
> > +			mcount = strtoul(optarg, NULL, 0);
> > +			break;
> > +		case 'd':
> > +			dump_sig = 1;
> > +			break;
> > +#endif /* CONFIG_TOOLS_LIBCRYPTO */
> >   		case 'h':
> >   			print_usage();
> >   			return 0;
> >   		}
> >   	}
> > 
> > -	/* need an output file */
> > -	if (argc != optind + 1) {
> > +	/* check necessary parameters */
> > +	if ((argc != optind + 1) || !file ||
> > +	    ((privkey_file && !cert_file) ||
> > +	     (!privkey_file && cert_file))) {
> >   		print_usage();
> >   		exit(EXIT_FAILURE);
> >   	}
> > 
> > -	/* need a fit image file or raw image file */
> > -	if (!file) {
> > -		print_usage();
> > -		exit(EXIT_SUCCESS);
> > -	}
> > -
> > -	if (create_fwbin(argv[optind], file, guid, index, instance)
> > -			< 0) {
> > +	if (create_fwbin(argv[optind], file, guid, index, instance,
> > +			 mcount, privkey_file, cert_file) < 0) {
> >   		printf("Creating firmware capsule failed\n");
> >   		exit(EXIT_FAILURE);
> >   	}
> > 
> 

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

* Re: [PATCH v2 5/9] test/py: efi_capsule: add image authentication test
  2021-08-01  9:38   ` Heinrich Schuchardt
@ 2021-08-02  4:02     ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-02  4:02 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

On Sun, Aug 01, 2021 at 11:38:16AM +0200, Heinrich Schuchardt wrote:
> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > Add a couple of test cases against capsule image authentication
> > for capsule-on-disk, where only a signed capsule file with the verified
> > signature will be applied to the system.
> > 
> > Due to the difficulty of embedding a public key (esl file) in U-Boot
> > binary during pytest setup time, all the keys/certificates are pre-created.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> 
> Please, check the pylint warnings:
> 
> $ pylint test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> ************* Module test_capsule_firmware_signed
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:44:0:
> C0301: Line too long (113/100) (line-too-long)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:73:0:
> C0301: Line too long (117/100) (line-too-long)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:110:0:
> C0301: Line too long (113/100) (line-too-long)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:139:0:
> C0301: Line too long (117/100) (line-too-long)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:178:0:
> C0301: Line too long (113/100) (line-too-long)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:207:0:
> C0301: Line too long (117/100) (line-too-long)

As you can see, the line is given as a single "command line" string.
Breaking the line into meaningless pieces of strings won't make sense here. 

> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:154:2:
> W0511: TODO: check CapsuleStatus in CapsuleXXXX (fixme)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:222:2:
> W0511: TODO: check CapsuleStatus in CapsuleXXXX (fixme)

I don't intend to fix those TODOs soon.

> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:14:0:
> W0401: Wildcard import capsule_defs (wildcard-import)

Will fix.

> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:27:0:
> C0115: Missing class docstring (missing-class-docstring)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:27:0:
> R0205: Class 'TestEfiCapsuleFirmwareSigned' inherits from object, can be
> safely removed from bases in python3 (useless-object-inheritance)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:28:4:
> R0201: Method could be a function (no-self-use)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:93:4:
> R0201: Method could be a function (no-self-use)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:162:4:
> R0201: Method could be a function (no-self-use)

I would like to maintain the syntax that I use in this file:
class TestXXX():
   def test_yyy():
     ...
even though pylint suggests that those changes be safely made.

"class/def" combination will allow us to add more tests cases for
different test conditions in the future without modifying
the structure of the file.

> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
> W0611: Unused check_call imported from subprocess (unused-import)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
> W0611: Unused check_output imported from subprocess (unused-import)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:12:0:
> W0611: Unused CalledProcessError imported from subprocess (unused-import)
> test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py:14:0:
> W0614: Unused import EFITOOLS_PATH from wildcard import
> (unused-wildcard-import)

Will fix.

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > ---
> >   test/py/tests/test_efi_capsule/SIGNER.crt     |  19 ++
> >   test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
> >   test/py/tests/test_efi_capsule/SIGNER.key     |  28 +++
> >   test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 ++
> >   test/py/tests/test_efi_capsule/SIGNER2.key    |  28 +++
> >   .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
> >   test/py/tests/test_efi_capsule/conftest.py    |  35 ++-
> >   .../test_capsule_firmware_signed.py           | 228 ++++++++++++++++++
> >   8 files changed, 359 insertions(+), 3 deletions(-)
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
> >   create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > 
> > diff --git a/test/py/tests/test_efi_capsule/SIGNER.crt b/test/py/tests/test_efi_capsule/SIGNER.crt
> > new file mode 100644
> > index 000000000000..f63ec01d9996
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/SIGNER.crt
> > @@ -0,0 +1,19 @@
> > +-----BEGIN CERTIFICATE-----
> > +MIIDDTCCAfWgAwIBAgIUD96z+lSbhDFN76YoIY2LnDBt1yQwDQYJKoZIhvcNAQEL
> > +BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
> > +NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
> > +AQEBBQADggEPADCCAQoCggEBAMBuazX28i0y4L0loJYJOtlvF5eWb4tbx7zwei5c
> > +KoSzQYixinS10OrVy7y8mELyXOlGOOsM509vzvoia0nffwEPsvTBeS3le2JBz9iN
> > +/+AIo+gUmzgEPQN+jp+s4fi0yzRvq3BgWu1ego2gExxQ7AePQHoSkX8UeC3Kb7SF
> > +a8Kt/TopOupZfEuZ+EtoxPA4JUStFgEUEcRJEfpQqECXV+lKqcyqHc2ZUzMisu+i
> > +5omkneX8sEZdIPFsSGanCyY3F9VjWzIxo60PU2xUBOIcEUg5luR+VXT4090g/yCw
> > +8PSf9rIKgGIQSQKAlUSc7zuXQIdgIMTS1xUpc/Nx+SqWNZECAwEAAaNTMFEwHQYD
> > +VR0OBBYEFHndZVpPrAjc3OD3UZ3xkXQqDOlZMB8GA1UdIwQYMBaAFHndZVpPrAjc
> > +3OD3UZ3xkXQqDOlZMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
> > +AG88t6w0qTXE50ltps62f6wtuuZsiX1zj+AluO4E8E3Wi0QsNtT24JdY2P4mAg8y
> > +abYLdgJIldzzsfjWWok9Dfqnx29tqgesKWkgUo16v70i4EVZ9YWGe+CfOK639OxL
> > +4D0XPcU5CUpDrEcnt59wCxQ7IArZzrDxrqigEw5nReejtgQV/mEzvVOzWjLjmngy
> > +SpvrydxYpfSvOJ3KGV9xw3Oa/qO3pS0ZNX9QqZdcC94M0SI6OF635oxJkz6JToYq
> > ++qtv9PZtZnEU/cwzL0nTXMj7yRsP5+2Wre26yT62nKRy9P/3UFwmsJ0OuEmnol5I
> > +141ZGfBYmSQ6EReOwNeK7A0=
> > +-----END CERTIFICATE-----
> > diff --git a/test/py/tests/test_efi_capsule/SIGNER.esl b/test/py/tests/test_efi_capsule/SIGNER.esl
> > new file mode 100644
> > index 0000000000000000000000000000000000000000..a54536e243d274b74985abbecfe234d14013ef33
> > GIT binary patch
> > literal 829
> > zcmZ1&d0^?2Da*aux2_hA(f&|m%gg`<iclKDgOCPI%)ACoj9(WpGchtTiSXas{3~R3
> > zi=prPWg3dT-E$0bud5jFvT<s)d9;1!Wn|=LWiSvk6fqEDV-96u=HU);4GxJ9_H_4i
> > z4Kk1u=QT1kFgG$YurM_?G>rmsjgYuF^))dnAzQ)7%D~*j$j<<D6&F(zBO}9sylm5N
> > zpLC5L>{VSbjnnF8zWDTM`Q6dS_k5_*i_vP??AWoft7PkiS65H(*)zlGQ_M>@i`P8Q
> > z{qxWLQp)zcU(d+D>C3@N-KW(_j^}Um{(r!+_=U)93l>}Ey1w~q9{$*J+9ZE<K|<8q
> > zxTf9(!ZHDG*!vx-geKODROp_{-_n|WXzgDsO{-UtHQqCScxN2>V4>==R*X?Z@QA12
> > zuYeT})5BkStvs_z_Uz1HW2H^+7d`7-GWY494Q{atA9Fm?mUF9_i(gHSHZokimOnTr
> > zgyoTppoitOCv~AEKQ7-@_^+_x!<YHrHgPp133xI!Om&&_-g>%2dxFA|OV>p;i$53s
> > z)S6~Gk%^g+fpKxLL7;&wFw|xFSj1RFD(|L7`LE%)bLYYLz_}kMmT2+3j5Lr3Nh`BR
> > z7>G4sSHKTaAk4`4pM}+c8Au@qJ1}N}!OqB#Z?k=k$x72B&pmUOo!eHwMt9e<oX*<f
> > z{s*c%-m!e}z1HobV|L}+gXs}B{;4tX8)a_eE@SeTdgt@TAJ?KfZFzq!Kc1hvihYe{
> > zrb19})&9Lo4_qU^wzgG2m~XLe`<FM~4{XJ4k6LniIj?b7-#)*9Tf|y{>*l!)AJ?r|
> > zAk3HU`h4*=7SVr+#(RS|M;SeyRbk{c`}N5?5lg?Ux0riMGQRL|@vMJ~w=dO|G_4O<
> > zIX#B^9?wN3D~q`8&w4y3+jaW2Y5iKA|K(e5TA|3_GsgO!mt#)+J}J%r{Oz>0Z+D%v
> > r+csxO(U<?<17g%R%;nqRxqMNa$MxPw$qx}TRjdTX`wm?1dcz9<2x(B#
> > 
> > literal 0
> > HcmV?d00001
> > 
> > diff --git a/test/py/tests/test_efi_capsule/SIGNER.key b/test/py/tests/test_efi_capsule/SIGNER.key
> > new file mode 100644
> > index 000000000000..9952647ed74a
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/SIGNER.key
> > @@ -0,0 +1,28 @@
> > +-----BEGIN PRIVATE KEY-----
> > +MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAQDAbms19vItMuC9
> > +JaCWCTrZbxeXlm+LW8e88HouXCqEs0GIsYp0tdDq1cu8vJhC8lzpRjjrDOdPb876
> > +ImtJ338BD7L0wXkt5XtiQc/Yjf/gCKPoFJs4BD0Dfo6frOH4tMs0b6twYFrtXoKN
> > +oBMcUOwHj0B6EpF/FHgtym+0hWvCrf06KTrqWXxLmfhLaMTwOCVErRYBFBHESRH6
> > +UKhAl1fpSqnMqh3NmVMzIrLvouaJpJ3l/LBGXSDxbEhmpwsmNxfVY1syMaOtD1Ns
> > +VATiHBFIOZbkflV0+NPdIP8gsPD0n/ayCoBiEEkCgJVEnO87l0CHYCDE0tcVKXPz
> > +cfkqljWRAgMBAAECggEAItLYrAdohC105kXs7bn14GtuRYx/2yRc3SBXvBQJzcHy
> > +1h3rBHvytszB9gHbPCJIFh8TJdZL9eAyAKpB6Dh9718773cjyt6AmaN3TaVE7PIj
> > +V1iDTnvV3tAEV3kd27g8Hd0nlUqaqeI0lhSl4LX0QNn3vR+nHOxDY2YDGRQcEDrD
> > +4hlCIGzAfbCW9gINdadQnC6p9NEBbfJ18doCagdn1Q1UYs8YlWwhBK98wXKGsG6T
> > +TUywOWIe6+VJqzSwZn5YkDVD3qD4tToar7T0jrCvZjbTbOsjtinD70c3uBcrK/XN
> > +gpwJfTiDLo1d0tNoWCRUH0myMs1fq3H3SkdfqB1GwQKBgQDrw8FwUc3Q+j8YhR7i
> > +73H/osk3VOZhCPsqbrQThUo5ZV4EXqp9E3PLN5E3suWgfaXVCEI3lHARUyR+J+E/
> > +evIrUUnkIryLdVOwwEWRonW4cLANjLSzT0eA85CFLXKUaij7Jfon2YNs9CmUARnC
> > +M96T3a89XOezX/SbRVz6X8KslQKBgQDQ8onkHcscHMANIjgxycIgYF+MvxwHRICA
> > +nt3ZSQiGSXJbWK7/sM5yd16ulvsXL7aF9G+q5osOzDWJ0w4SOhqNDfItrFH34Px6
> > +qEPjq/sAigqqrQls7uu7MHfkE+eEy181CoT9argxo8ifAQDn4YtXBW6L7p6AgaAx
> > +83FAbBcqDQKBgQClHk185534zTqhZqIyF7bEbfL0sJ5EuXCG0E+IGGLafdbxwocu
> > +4A/J9Jnc44sU8srQv1745Bn02EEHpdCIkAfJNL5Ga9mW5k39zTsr+xbtXObAJppr
> > +touCkZLW4vSLYypecsOXYyw7g2kXQgoTTBaHgsv3cvjHVN3QXSz4IVcLXQJ/LBL9
> > +AyFFtqhZ2mtdbyMfz7SEcyvcvau1b2wTX8IICktz09DhGQ4yffKwBiPS0xE9bwQg
> > +iewXaQeqQ2hBj5ayAw7uBrRSlfbfSwAzUdL1Hyf/GAFn+5JqJxISOAn6zAgaDRYq
> > +90mLkOz7ZI7RohfxTGnY56ttw62UHPU87lneiQKBgHcVituUDJgmbaHXx2IVzKsm
> > +5uDyXUf4S+tY5CZj6WTsb70+q4PYfh1D02nZgxuLNwpwNI0uhLIkLYHcL3poOapC
> > +LCXS8tsexNosmrTmjHFh/uNdKb7bKbMxyzYrr+ADKMclF3CJzKDzLfiIe9Na+bWa
> > +q5/HYNIw5zJyapPksgr4
> > +-----END PRIVATE KEY-----
> > diff --git a/test/py/tests/test_efi_capsule/SIGNER2.crt b/test/py/tests/test_efi_capsule/SIGNER2.crt
> > new file mode 100644
> > index 000000000000..8889a3ed930a
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/SIGNER2.crt
> > @@ -0,0 +1,19 @@
> > +-----BEGIN CERTIFICATE-----
> > +MIIDDTCCAfWgAwIBAgIUfmZcui7VkJEe9jx25Epo6jJ6l+owDQYJKoZIhvcNAQEL
> > +BQAwFjEUMBIGA1UEAwwLVEVTVF9TSUdORVIwHhcNMjEwNzI2MDg1MzE1WhcNMjIw
> > +NzI2MDg1MzE1WjAWMRQwEgYDVQQDDAtURVNUX1NJR05FUjCCASIwDQYJKoZIhvcN
> > +AQEBBQADggEPADCCAQoCggEBANozXTFKGVx0121MIBoSgxfI8IHcfY32T/LQusse
> > +PaXsm0GaJNwOgEP34u1k0cz466swfBCqTcZRjKuDpcH1sgrF1XaKjxuwYuiJrbsf
> > +ykVesN1z1bIamkFdVR/CBJEwN/epsyCBQCSbcxUwEX+ayq2zp+kSweew1B4i3u8f
> > +nbqFB15Rt+KAzFaBlvOJhmoZP7uYtb8zHa58eteaxQmPFt3v6eEbgOt92oVB8fPQ
> > +JJBuxUAHdimMDQ9mBGUosXR8PFyma5jOiOyY+0oTfig4bRHbGxCGMYyABJDH+j4e
> > +7Zl7lVMsq2fTm/lGONRX2QPLfMO298pz/wundJmYhseibvUCAwEAAaNTMFEwHQYD
> > +VR0OBBYEFDPYxE3oBmU1pWrZpY62JuXgcK5aMB8GA1UdIwQYMBaAFDPYxE3oBmU1
> > +pWrZpY62JuXgcK5aMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
> > +AEtY9QnvTvgmXmep7AMv/T6+GpERvsRdi+Lc+16L7uSCQhouDkeu5/sUHax6icX1
> > +NyDb3u6tyQhMnm7CD+7Mo74wrZ4vK2SzBoZSBLi+Tyz2ScyysdRIo7O42nxVyWm7
> > +ifZVfQKvanUjDSxPO89yJDYp0znvVpuZOzYXFHdprHoR5Atkth11HFHzWDzqblKS
> > +sx145wgPZ9bYohuOn1weyORsG9bJcHznPyJ1ceAOFk40bKWWLQtruWIhY4aZIlJN
> > +cDKv92rtgVApaamu+WRC4pzgQMQYKOcnMz4ZKeOKgEajfo6nOUVrvc0IYO6wixvi
> > +V+Msrg5o7ag2SN2AHg5/1/4=
> > +-----END CERTIFICATE-----
> > diff --git a/test/py/tests/test_efi_capsule/SIGNER2.key b/test/py/tests/test_efi_capsule/SIGNER2.key
> > new file mode 100644
> > index 000000000000..ee467fd9f7a6
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/SIGNER2.key
> > @@ -0,0 +1,28 @@
> > +-----BEGIN PRIVATE KEY-----
> > +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDaM10xShlcdNdt
> > +TCAaEoMXyPCB3H2N9k/y0LrLHj2l7JtBmiTcDoBD9+LtZNHM+OurMHwQqk3GUYyr
> > +g6XB9bIKxdV2io8bsGLoia27H8pFXrDdc9WyGppBXVUfwgSRMDf3qbMggUAkm3MV
> > +MBF/msqts6fpEsHnsNQeIt7vH526hQdeUbfigMxWgZbziYZqGT+7mLW/Mx2ufHrX
> > +msUJjxbd7+nhG4DrfdqFQfHz0CSQbsVAB3YpjA0PZgRlKLF0fDxcpmuYzojsmPtK
> > +E34oOG0R2xsQhjGMgASQx/o+Hu2Ze5VTLKtn05v5RjjUV9kDy3zDtvfKc/8Lp3SZ
> > +mIbHom71AgMBAAECggEBAJXskO3bAg364kJg+fWwHo7rLAWuYD54rXojXRVPFAC7
> > +z/mFVio1dIA/BJcknNr/db5MNBKnUYUgZ005yVy52rl4MTGgBrB5w5wPbWWTdEGx
> > +zEh83KnhiXe8D08g2k6AGRR8b224IUCF5s76FivdScGMHaURlFYDs9t5DkCzMocC
> > +ty0ewHv9aeMSzJl4y+DrRw+NkkAntlAkerCI5PInFtxyOQ6lFIRkMKlBA//VL0QF
> > +B9yGbmfoxlErWCqnj70DTcVO7O2AaijU+FTMRbb/V7r34GPU0Cfeum6gGNOtDkaX
> > +3UnWGR2esiHViMqz8vvEYtVIxHhLTD7INqDlK/yiNEECgYEA+ua1JcHXI2qS3cV/
> > +BuVvBrd3MzIpZvddCcTdo/B7WT3EoTupEG1gcajrCuNQDtRoizSbMuhCXYoMsktF
> > +wXFoTWoGr8yO7uVU5r2nCXZneprV3kuQmR0qYipN2GTCGSE1rKQI+YXeALPF1qIp
> > +12vUVdzWVDJvlQRMvSTlzpRZQkkCgYEA3qKI1ZsBszKPbnzLX91+ZAZeAwwN/HvS
> > +nrIveJAci/9U2yV2mw3l/Dulc8EkGABs/cMp47toje8DmsSfdu1yIYqpi3MHvefX
> > ++ijc3ry5v28Hia3WP3WPczqhbkT7cco0t8Vwm9w1B+kkreuRCtyoCOLsRauB0CH1
> > +QJjMtPAth00CgYAKUUhruA/nxe8qLX/uwaqSJSNCuLJZKJzr1OukXTRFVDPsyW5H
> > +XagUpHSd6wEUywlNiClFq6VnAVFKV6wTq101qcGCoy/RhR67qlrfGb5hnVJkJMla
> > +coeWp9SxrFsK+4GgitJPqICbmMju7ZY45JdDvKQXrEdIYnfhY04L86/D+QKBgBxx
> > +nZPU0vnHCuYt0Xn0/XHgEmDHSH4qf7VAxKndl5gXTgsVlTqoIur/39qTIX5jh4lA
> > +RvjOd8Qydj5uwoTaP0ujwJeNYb7UgRZ35AgdCoo3sDnZ2NaQuXwaUIebDpjyIZwd
> > +AI8ZKjlRgxspToWZvWotO8yG5fXmcMQJAZZYXSi9AoGBALfXX/C5ojwms1l+XP+p
> > +FKzOFZ/uEKPfQid+2Sm1BknXXGVbs3zJ4OdonTvhjq+VQvXTW4IvjgY8TpumQZvE
> > +8nb7I8E1B6ajkSvgfetN9jlKM5hzIfJ3Vxx6hMGMab1ySKy3rZGPL706CW2BeMI2
> > +v2k9P0qWItuE4S7I4hEsovwS
> > +-----END PRIVATE KEY-----
> > diff --git a/test/py/tests/test_efi_capsule/capsule_defs.py b/test/py/tests/test_efi_capsule/capsule_defs.py
> > index 4fd6353c2040..aa9bf5eee3aa 100644
> > --- a/test/py/tests/test_efi_capsule/capsule_defs.py
> > +++ b/test/py/tests/test_efi_capsule/capsule_defs.py
> > @@ -3,3 +3,8 @@
> >   # Directories
> >   CAPSULE_DATA_DIR = '/EFI/CapsuleTestData'
> >   CAPSULE_INSTALL_DIR = '/EFI/UpdateCapsule'
> > +
> > +# v1.5.1 or earlier of efitools has a bug in sha256 calculation, and
> > +# you need build a newer version on your own.
> > +# The path must terminate with '/'.
> > +EFITOOLS_PATH = ''
> > diff --git a/test/py/tests/test_efi_capsule/conftest.py b/test/py/tests/test_efi_capsule/conftest.py
> > index 6ad5608cd71c..35cfa5513703 100644
> > --- a/test/py/tests/test_efi_capsule/conftest.py
> > +++ b/test/py/tests/test_efi_capsule/conftest.py
> > @@ -10,13 +10,13 @@ import pytest
> >   from capsule_defs import *
> > 
> >   #
> > -# Fixture for UEFI secure boot test
> > +# Fixture for UEFI capsule test
> >   #
> > 
> > -
> >   @pytest.fixture(scope='session')
> >   def efi_capsule_data(request, u_boot_config):
> > -    """Set up a file system to be used in UEFI capsule test.
> > +    """Set up a file system to be used in UEFI capsule and
> > +       authentication test.
> > 
> >       Args:
> >           request: Pytest request object.
> > @@ -40,6 +40,22 @@ def efi_capsule_data(request, u_boot_config):
> >           check_call('mkdir -p %s' % data_dir, shell=True)
> >           check_call('mkdir -p %s' % install_dir, shell=True)
> > 
> > +        capsule_auth_enabled = u_boot_config.buildconfig.get(
> > +                    'config_efi_capsule_authenticate')
> > +        # NOTE:
> > +        # private keys (SIGNER?.key) dn certificates (SIGNER?.crt)
> > +        # in this pytest directory are created this way:
> > +        # Create private key (SIGNER.key) and certificate (SIGNER.crt)
> > +        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER.key -out SIGNER.crt -nodes -days 365'
> > +        #               % data_dir, shell=True)
> > +        #    check_call('cd %s; %scert-to-efi-sig-list SIGNER.crt SIGNER.esl'
> > +        #               % (data_dir, EFITOOLS_PATH), shell=True)
> > +
> > +        # Create *malicious* private key (SIGNER2.key) and certificate
> > +        # (SIGNER2.crt)
> > +        #    check_call('cd %s; openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=TEST_SIGNER/ -keyout SIGNER2.key -out SIGNER2.crt -nodes -days 365'
> > +        #               % data_dir, shell=True)
> > +
> >           # Create capsule files
> >           # two regions: one for u-boot.bin and the other for u-boot.env
> >           check_call('cd %s; echo -n u-boot:Old > u-boot.bin.old; echo -n u-boot:New > u-boot.bin.new; echo -n u-boot-env:Old -> u-boot.env.old; echo -n u-boot-env:New > u-boot.env.new' % data_dir,
> > @@ -56,6 +72,19 @@ def efi_capsule_data(request, u_boot_config):
> >           check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 Test02' %
> >                      (data_dir, u_boot_config.build_dir),
> >                      shell=True)
> > +        if capsule_auth_enabled:
> > +            # copy keys/certificates
> > +            check_call('cp %s/test/py/tests/test_efi_capsule/SIGNER*.* %s' %
> > +                       (u_boot_config.source_dir, data_dir),
> > +                       shell=True)
> > +            # firmware signed with proper key
> > +            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER.key --certificate SIGNER.crt Test03' %
> > +                       (data_dir, u_boot_config.build_dir),
> > +                       shell=True)
> > +            # firmware signed with *mal* key
> > +            check_call('cd %s; %s/tools/mkeficapsule --raw u-boot.bin.new --index 1 --monotonic-count 1 --private-key SIGNER2.key --certificate SIGNER2.crt Test04' %
> > +                       (data_dir, u_boot_config.build_dir),
> > +                       shell=True)
> > 
> >           # Create a disk image with EFI system partition
> >           check_call('virt-make-fs --partition=gpt --size=+1M --type=vfat %s %s' %
> > diff --git a/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > new file mode 100644
> > index 000000000000..8fe93ef424ac
> > --- /dev/null
> > +++ b/test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > @@ -0,0 +1,228 @@
> > +# SPDX-License-Identifier:      GPL-2.0+
> > +# Copyright (c) 2021, Linaro Limited
> > +# Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > +#
> > +# U-Boot UEFI: Firmware Update (Signed capsule) Test
> > +
> > +"""
> > +This test verifies capsule-on-disk firmware update
> > +with signed capsule files
> > +"""
> > +
> > +from subprocess import check_call, check_output, CalledProcessError
> > +import pytest
> > +from capsule_defs import *
> > +
> > +@pytest.mark.boardspec('sandbox')
> > +@pytest.mark.buildconfigspec('efi_capsule_firmware_raw')
> > +@pytest.mark.buildconfigspec('efi_capsule_authenticate')
> > +@pytest.mark.buildconfigspec('dfu')
> > +@pytest.mark.buildconfigspec('dfu_sf')
> > +@pytest.mark.buildconfigspec('cmd_efidebug')
> > +@pytest.mark.buildconfigspec('cmd_fat')
> > +@pytest.mark.buildconfigspec('cmd_memory')
> > +@pytest.mark.buildconfigspec('cmd_nvedit_efi')
> > +@pytest.mark.buildconfigspec('cmd_sf')
> > +@pytest.mark.slow
> > +class TestEfiCapsuleFirmwareSigned(object):
> > +    def test_efi_capsule_auth1(
> > +            self, u_boot_config, u_boot_console, efi_capsule_data):
> > +        """
> > +        Test Case 1 - Update U-Boot on SPI Flash, raw image format
> > +                      0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > +                      If the capsule is properly signed, the authentication
> > +                      should pass and the firmware be updated.
> > +        """
> > +        disk_img = efi_capsule_data
> > +        with u_boot_console.log.section('Test Case 1-a, before reboot'):
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > +                'efidebug boot order 1',
> > +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                'env save'])
> > +
> > +            # initialize content
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> > +                'sf write 4000000 100000 10',
> > +                'sf read 5000000 100000 10',
> > +                'md.b 5000000 10'])
> > +            assert 'Old' in ''.join(output)
> > +
> > +            # place a capsule file
> > +            output = u_boot_console.run_command_list([
> > +                'fatload host 0:1 4000000 %s/Test03' % CAPSULE_DATA_DIR,
> > +                'fatwrite host 0:1 4000000 %s/Test03 $filesize' % CAPSULE_INSTALL_DIR,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test03' in ''.join(output)
> > +
> > +        # reboot
> > +        u_boot_console.restart_uboot()
> > +
> > +        capsule_early = u_boot_config.buildconfig.get(
> > +            'config_efi_capsule_on_disk_early')
> > +        with u_boot_console.log.section('Test Case 1-b, after reboot'):
> > +            if not capsule_early:
> > +                # make sure that dfu_alt_info exists even persistent variables
> > +                # are not available.
> > +                output = u_boot_console.run_command_list([
> > +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                    'host bind 0 %s' % disk_img,
> > +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +                assert 'Test03' in ''.join(output)
> > +
> > +                # need to run uefi command to initiate capsule handling
> > +                output = u_boot_console.run_command(
> > +                    'env print -e Capsule0000')
> > +
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test03' not in ''.join(output)
> > +
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'sf read 4000000 100000 10',
> > +                'md.b 4000000 10'])
> > +            assert 'u-boot:New' in ''.join(output)
> > +
> > +    def test_efi_capsule_auth2(
> > +            self, u_boot_config, u_boot_console, efi_capsule_data):
> > +        """
> > +        Test Case 2 - Update U-Boot on SPI Flash, raw image format
> > +                      0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > +                      If the capsule is signed but with an invalid key,
> > +                      the authentication should fail and the firmware
> > +                      not be updated.
> > +        """
> > +        disk_img = efi_capsule_data
> > +        with u_boot_console.log.section('Test Case 2-a, before reboot'):
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > +                'efidebug boot order 1',
> > +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                'env save'])
> > +
> > +            # initialize content
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> > +                'sf write 4000000 100000 10',
> > +                'sf read 5000000 100000 10',
> > +                'md.b 5000000 10'])
> > +            assert 'Old' in ''.join(output)
> > +
> > +            # place a capsule file
> > +            output = u_boot_console.run_command_list([
> > +                'fatload host 0:1 4000000 %s/Test04' % CAPSULE_DATA_DIR,
> > +                'fatwrite host 0:1 4000000 %s/Test04 $filesize' % CAPSULE_INSTALL_DIR,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test04' in ''.join(output)
> > +
> > +        # reboot
> > +        u_boot_console.restart_uboot()
> > +
> > +        capsule_early = u_boot_config.buildconfig.get(
> > +            'config_efi_capsule_on_disk_early')
> > +        with u_boot_console.log.section('Test Case 2-b, after reboot'):
> > +            if not capsule_early:
> > +                # make sure that dfu_alt_info exists even persistent variables
> > +                # are not available.
> > +                output = u_boot_console.run_command_list([
> > +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                    'host bind 0 %s' % disk_img,
> > +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +                assert 'Test04' in ''.join(output)
> > +
> > +                # need to run uefi command to initiate capsule handling
> > +                output = u_boot_console.run_command(
> > +                    'env print -e Capsule0000')
> > +
> > +            # deleted any way
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test04' not in ''.join(output)
> > +
> > +            # TODO: check CapsuleStatus in CapsuleXXXX
> > +
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'sf read 4000000 100000 10',
> > +                'md.b 4000000 10'])
> > +            assert 'u-boot:Old' in ''.join(output)
> > +
> > +    def test_efi_capsule_auth3(
> > +            self, u_boot_config, u_boot_console, efi_capsule_data):
> > +        """
> > +        Test Case 3 - Update U-Boot on SPI Flash, raw image format
> > +                      0x100000-0x150000: U-Boot binary (but dummy)
> > +
> > +                      If the capsule is not signed, the authentication
> > +                      should fail and the firmware not be updated.
> > +        """
> > +        disk_img = efi_capsule_data
> > +        with u_boot_console.log.section('Test Case 3-a, before reboot'):
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'efidebug boot add -b 1 TEST host 0:1 /helloworld.efi',
> > +                'efidebug boot order 1',
> > +                'env set -e -nv -bs -rt OsIndications =0x0000000000000004',
> > +                'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                'env save'])
> > +
> > +            # initialize content
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'fatload host 0:1 4000000 %s/u-boot.bin.old' % CAPSULE_DATA_DIR,
> > +                'sf write 4000000 100000 10',
> > +                'sf read 5000000 100000 10',
> > +                'md.b 5000000 10'])
> > +            assert 'Old' in ''.join(output)
> > +
> > +            # place a capsule file
> > +            output = u_boot_console.run_command_list([
> > +                'fatload host 0:1 4000000 %s/Test02' % CAPSULE_DATA_DIR,
> > +                'fatwrite host 0:1 4000000 %s/Test02 $filesize' % CAPSULE_INSTALL_DIR,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test02' in ''.join(output)
> > +
> > +        # reboot
> > +        u_boot_console.restart_uboot()
> > +
> > +        capsule_early = u_boot_config.buildconfig.get(
> > +            'config_efi_capsule_on_disk_early')
> > +        with u_boot_console.log.section('Test Case 3-b, after reboot'):
> > +            if not capsule_early:
> > +                # make sure that dfu_alt_info exists even persistent variables
> > +                # are not available.
> > +                output = u_boot_console.run_command_list([
> > +                    'env set dfu_alt_info "sf 0:0=u-boot-bin raw 0x100000 0x50000;u-boot-env raw 0x150000 0x200000"',
> > +                    'host bind 0 %s' % disk_img,
> > +                    'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +                assert 'Test02' in ''.join(output)
> > +
> > +                # need to run uefi command to initiate capsule handling
> > +                output = u_boot_console.run_command(
> > +                    'env print -e Capsule0000')
> > +
> > +            # deleted any way
> > +            output = u_boot_console.run_command_list([
> > +                'host bind 0 %s' % disk_img,
> > +                'fatls host 0:1 %s' % CAPSULE_INSTALL_DIR])
> > +            assert 'Test02' not in ''.join(output)
> > +
> > +            # TODO: check CapsuleStatus in CapsuleXXXX
> > +
> > +            output = u_boot_console.run_command_list([
> > +                'sf probe 0:0',
> > +                'sf read 4000000 100000 10',
> > +                'md.b 4000000 10'])
> > +            assert 'u-boot:Old' in ''.join(output)
> > 
> 

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

* Re: [PATCH v2 4/9] efi_loader: ease the file path check for public key
  2021-08-01  9:35   ` Heinrich Schuchardt
@ 2021-08-02  4:50     ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-02  4:50 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

On Sun, Aug 01, 2021 at 11:35:15AM +0200, Heinrich Schuchardt wrote:
> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > The check for CONFIG_EFI_CAPSULE_KEY_PATH:
> >      ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
> > does not allow users to specify a relative path for including a public
> > key binary. This is fine for most of all cases, but it will make it
> > difficult to add pytest test cases as pre-created keys/certificates
> > are placed in "test" directory.
> > 
> > So just ease the check, still causing an error if the specified file
> > does not exist at compiling efi_capsule_key.S.
> > 
> > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > ---
> >   lib/efi_loader/Makefile | 5 +++--
> >   1 file changed, 3 insertions(+), 2 deletions(-)
> > 
> > diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
> > index 9b369430e258..fca0da4d131e 100644
> > --- a/lib/efi_loader/Makefile
> > +++ b/lib/efi_loader/Makefile
> > @@ -21,8 +21,9 @@ targets += helloworld.o
> >   endif
> > 
> >   ifeq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),y)
> > -EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
> > -ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
> > +#EFI_CAPSULE_KEY_PATH := $(subst $\",,$(CONFIG_EFI_CAPSULE_KEY_PATH))
> > +#ifeq ("$(wildcard $(EFI_CAPSULE_KEY_PATH))","")
> 
> Please, remove these two comment lines.

I forgot to do so.

> > +ifeq ($(CONFIG_EFI_CAPSULE_KEY_PATH),"")
> >   $(error .esl cerificate not found. Configure your CONFIG_EFI_CAPSULE_KEY_PATH)
> 
> %s/cerificate/certificate/

This misspelling does exist in the original.
I won't fix it.

-Takahiro Akashi


> Best regards
> 
> Heinrich
> 
> >   endif
> >   endif
> > 
> 

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

* Re: [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support
  2021-08-01  9:40 ` [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support Heinrich Schuchardt
@ 2021-08-02  5:00   ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-02  5:00 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

Heinrich,

On Sun, Aug 01, 2021 at 11:40:14AM +0200, Heinrich Schuchardt wrote:
> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > As I proposed and discussed in [1] and [2], I have made a couple of
> > improvements on the current implementation of capsule update in this
> > patch set.
> > 
> > * add signing feature to mkeficapsule
> > * add "--guid" option to mkeficapsule
> > * add man page of mkeficapsule
> > * add pytest for capsule authentication (on sandbox)
> > 
> > NOTE:
> > Due to Ilias's commit[3], we need to have a customized configuration
> > for sandbox to properly set up and run capsule authentication test.
> > See patch#5,#6 and #7.
> > 
> > [1] https://lists.denx.de/pipermail/u-boot/2021-April/447918.html
> > [2] https://lists.denx.de/pipermail/u-boot/2021-July/455292.html
> > [3] commit ddf67daac39d ("efi_capsule: Move signature from DTB to
> >      .rodata")
> 
> 
> Dear Takahiro,
> 
> thanks for driving this topic. I have finished with my review and will
> be waiting for v2.

Thanks for your review comments.

I'd like to know what's your thought on Patch#8 (and #9)
as I have not seen your comment at [2] above.
It is more or less an RFC since it breaks the compatibility
of command syntax although I believe that the change is
quite useful.

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > 
> > Prerequisite patches
> > ====================
> > None
> > 
> > Test
> > ====
> > * locally passed the pytest which is included in this patch series
> >    on sandbox built.
> > 
> > Todo
> > ====
> > * Confirm that the change in .gitlab-ci.yml works.
> > * Azure support(?)
> > 
> > Changes
> > =======
> > v2 (July 28, 2021)
> > * rebased on v2021.10-rc*
> > * removed dependency on target's configuration
> > * removed fdtsig.sh and others
> > * add man page
> > * update the UEFI document
> > * add dedicate defconfig for testing on sandbox
> > * add gitlab CI support
> > * add "--guid" option to mkeficapsule
> >    (yet rather RFC)
> > 
> > Initial release (May 12, 2021)
> > * based on v2021.07-rc2
> > 
> > AKASHI Takahiro (9):
> >    tools: mkeficapsule: add firmwware image signing
> >    tools: mkeficapsule: add man page
> >    doc: update UEFI document for usage of mkeficapsule
> >    efi_loader: ease the file path check for public key
> >    test/py: efi_capsule: add image authentication test
> >    sandbox: add config for efi capsule authentication test
> >    GitLab: add a test rule for efi capsule authentication test
> >    tools: mkeficapsule: allow for specifying GUID explicitly
> >    test/py: efi_capsule: align with the syntax change of mkeficapsule
> > 
> >   .gitlab-ci.yml                                |   6 +
> >   MAINTAINERS                                   |   1 +
> >   configs/sandbox_capsule_auth_defconfig        | 307 +++++++++++++++
> >   doc/develop/uefi/uefi.rst                     |  31 +-
> >   doc/mkeficapsule.1                            |  98 +++++
> >   lib/efi_loader/Makefile                       |   5 +-
> >   test/py/tests/test_efi_capsule/SIGNER.crt     |  19 +
> >   test/py/tests/test_efi_capsule/SIGNER.esl     | Bin 0 -> 829 bytes
> >   test/py/tests/test_efi_capsule/SIGNER.key     |  28 ++
> >   test/py/tests/test_efi_capsule/SIGNER2.crt    |  19 +
> >   test/py/tests/test_efi_capsule/SIGNER2.key    |  28 ++
> >   .../py/tests/test_efi_capsule/capsule_defs.py |   5 +
> >   test/py/tests/test_efi_capsule/conftest.py    |  39 +-
> >   .../test_capsule_firmware_signed.py           | 228 +++++++++++
> >   tools/Kconfig                                 |   7 +
> >   tools/Makefile                                |   8 +-
> >   tools/mkeficapsule.c                          | 368 ++++++++++++++++--
> >   17 files changed, 1129 insertions(+), 68 deletions(-)
> >   create mode 100644 configs/sandbox_capsule_auth_defconfig
> >   create mode 100644 doc/mkeficapsule.1
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.crt
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.esl
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER.key
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.crt
> >   create mode 100644 test/py/tests/test_efi_capsule/SIGNER2.key
> >   create mode 100644 test/py/tests/test_efi_capsule/test_capsule_firmware_signed.py
> > 
> 

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

* Re: [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-08-02  3:30     ` AKASHI Takahiro
@ 2021-08-02  6:18       ` Heinrich Schuchardt
  2021-08-02  6:55         ` AKASHI Takahiro
  0 siblings, 1 reply; 30+ messages in thread
From: Heinrich Schuchardt @ 2021-08-02  6:18 UTC (permalink / raw)
  To: AKASHI Takahiro, agraf, trini, sjg, ilias.apalodimas,
	sughosh.ganu, masami.hiramatsu, u-boot



On 8/2/21 5:30 AM, AKASHI Takahiro wrote:
> Heinrich,
>
> On Sun, Aug 01, 2021 at 11:21:55AM +0200, Heinrich Schuchardt wrote:
>> On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
>>> With this enhancement, mkeficapsule will be able to sign a capsule
>>> file when it is created. A signature added will be used later
>>> in the verification at FMP's SetImage() call.
>>>
>>> To do that, We need specify additional command parameters:
>>>     -monotonic-cout <count> : monotonic count
>>>     -private-key <private key file> : private key file
>>>     -certificate <certificate file> : certificate file
>>> Only when all of those parameters are given, a signature will be added
>>> to a capsule file.
>>>
>>> Users are expected to maintain and increment the monotonic count at
>>> every time of the update for each firmware image.
>>>
>>> Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
>>> ---
>>>    tools/Kconfig        |   7 +
>>>    tools/Makefile       |   8 +-
>>>    tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
>>>    3 files changed, 316 insertions(+), 31 deletions(-)
>>>
>>> diff --git a/tools/Kconfig b/tools/Kconfig
>>> index d6f82cd949b5..9a37ed035311 100644
>>> --- a/tools/Kconfig
>>> +++ b/tools/Kconfig
>>> @@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
>>>    	  This selection does not affect target features, such as runtime FIT
>>>    	  signature verification.
>>>
>>> +config TOOLS_MKEFICAPSULE
>>> +	bool "Build efimkcapsule command"
>>> +	default y if EFI_CAPSULE_ON_DISK
>>> +	help
>>> +	  This command allows users to create a UEFI capsule file and,
>>> +	  optionally sign that file. If you want to enable UEFI capsule
>>> +	  update feature on your target, you certainly need this.
>>>    endmenu
>>> diff --git a/tools/Makefile b/tools/Makefile
>>> index bae3f95c4995..af8536489652 100644
>>> --- a/tools/Makefile
>>> +++ b/tools/Makefile
>>> @@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
>>>    hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
>>>    HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
>>>
>>> -mkeficapsule-objs	:= mkeficapsule.o $(LIBFDT_OBJS)
>>> -hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
>>> +HOSTLDLIBS_mkeficapsule += -luuid
>>> +ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
>>> +HOSTLDLIBS_mkeficapsule += \
>>> +	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
>>
>> Please, add package pkg-config to the build dependencies enumerated in
>> doc/build/gcc.rst.
>
> Already there: libssl-dev

It is *pkg-config* that is missing.

>
>>> +endif
>>> +hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
>>>
>>>    # We build some files with extra pedantic flags to try to minimize things
>>>    # that won't build on some weird host compiler -- though there are lots of
>>> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
>>> index 4995ba4e0c2a..798706c7b5f7 100644
>>> --- a/tools/mkeficapsule.c
>>> +++ b/tools/mkeficapsule.c
>>> @@ -15,6 +15,16 @@
>>>    #include <sys/stat.h>
>>>    #include <sys/types.h>
>>>
>>> +#include <linux/kconfig.h>
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +#include <openssl/asn1.h>
>>> +#include <openssl/bio.h>
>>> +#include <openssl/evp.h>
>>> +#include <openssl/err.h>
>>> +#include <openssl/pem.h>
>>> +#include <openssl/pkcs7.h>
>>> +#endif
>>> +
>>>    typedef __u8 u8;
>>>    typedef __u16 u16;
>>>    typedef __u32 u32;
>>> @@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
>>>    		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
>>>    efi_guid_t efi_guid_image_type_uboot_raw =
>>>    		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
>>> +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
>>> +
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
>>> +#else
>>> +static const char *opts_short = "f:r:i:I:v:h";
>>> +#endif
>>>
>>>    static struct option options[] = {
>>>    	{"fit", required_argument, NULL, 'f'},
>>>    	{"raw", required_argument, NULL, 'r'},
>>>    	{"index", required_argument, NULL, 'i'},
>>>    	{"instance", required_argument, NULL, 'I'},
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +	{"private-key", required_argument, NULL, 'p'},
>>> +	{"certificate", required_argument, NULL, 'c'},
>>> +	{"monotonic-count", required_argument, NULL, 'm'},
>>> +	{"dump-sig", no_argument, NULL, 'd'},
>>> +#endif
>>>    	{"help", no_argument, NULL, 'h'},
>>>    	{NULL, 0, NULL, 0},
>>>    };
>>> @@ -57,16 +80,195 @@ static void print_usage(void)
>>>    	       "\t-r, --raw <raw image>       new raw image file\n"
>>>    	       "\t-i, --index <index>         update image index\n"
>>>    	       "\t-I, --instance <instance>   update hardware instance\n"
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +	       "\t-p, --private-key <privkey file>  private key file\n"
>>> +	       "\t-c, --certificate <cert file>     signer's certificate file\n"
>>> +	       "\t-m, --monotonic-count <count>     monotonic count\n"
>>> +	       "\t-d, --dump_sig              dump signature (*.p7)\n"
>>> +#endif
>>>    	       "\t-h, --help                  print a help message\n",
>>>    	       tool_name);
>>>    }
>>>
>>
>> Please, add Sphinx documentation.
>
> I added the man page. Why need another different format of doc?
> I think that doc/develop/uefi/uefi.rst gives you an enough
> introduction to the command.
> (Although the doc will have to been updated due to the latest change
> of mkeficapsule syntax that I'm also proposing.)
>
> Actually, there is no sphinx doc for any host tools.
>
>>> +struct auth_context {
>>> +	char *key_file;
>>> +	char *cert_file;
>>> +	u8 *image_data;
>>> +	size_t image_size;
>>> +	struct efi_firmware_image_authentication auth;
>>> +	u8 *sig_data;
>>> +	size_t sig_size;
>>> +};
>>> +
>>> +static int dump_sig;
>>> +
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +static EVP_PKEY *fileio_read_pkey(const char *filename)
>>> +{
>>> +	EVP_PKEY *key = NULL;
>>> +	BIO *bio;
>>> +
>>> +	bio = BIO_new_file(filename, "r");
>>> +	if (!bio)
>>> +		goto out;
>>> +
>>> +	key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
>>> +
>>> +out:
>>> +	BIO_free_all(bio);
>>> +	if (!key) {
>>> +		printf("Can't load key from file '%s'\n", filename);
>>> +		ERR_print_errors_fp(stderr);
>>> +	}
>>> +
>>> +	return key;
>>> +}
>>> +
>>
>> Please, add Sphinx documentation for all functions.
>
> Yeah, but "all" is a too forcible requirement.
> There is no source code of host tools to meet the requirement.
> Actually, most don't have even one description of a function.
>
> I think that, if it is a really required element in the source,
> it should be explicitly described somewhere under "doc".
>
>>> +static X509 *fileio_read_cert(const char *filename)
>>> +{
>>> +	X509 *cert = NULL;
>>> +	BIO *bio;
>>> +
>>> +	bio = BIO_new_file(filename, "r");
>>> +	if (!bio)
>>> +		goto out;
>>> +
>>> +	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
>>> +
>>> +out:
>>> +	BIO_free_all(bio);
>>> +	if (!cert) {
>>> +		printf("Can't load certificate from file '%s'\n", filename);
>>> +		ERR_print_errors_fp(stderr);
>>> +	}
>>> +
>>> +	return cert;
>>> +}
>>> +
>>> +static int create_auth_data(struct auth_context *ctx)
>>> +{
>>> +	EVP_PKEY *key = NULL;
>>> +	X509 *cert = NULL;
>>> +	BIO *data_bio = NULL;
>>> +	const EVP_MD *md;
>>> +	PKCS7 *p7;
>>> +	int flags, ret = -1;
>>> +
>>> +	OpenSSL_add_all_digests();
>>> +	OpenSSL_add_all_ciphers();
>>> +	ERR_load_crypto_strings();
>>> +
>>> +	key = fileio_read_pkey(ctx->key_file);
>>> +	if (!key)
>>> +		goto err;
>>> +	cert = fileio_read_cert(ctx->cert_file);
>>> +	if (!cert)
>>> +		goto err;
>>> +
>>> +	/*
>>> +	 * create a BIO, containing:
>>> +	 *  * firmware image
>>> +	 *  * monotonic count
>>> +	 * in this order!
>>> +	 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
>>> +	 */
>>> +	data_bio = BIO_new(BIO_s_mem());
>>> +	BIO_write(data_bio, ctx->image_data, ctx->image_size);
>>> +	BIO_write(data_bio, &ctx->auth.monotonic_count,
>>> +		  sizeof(ctx->auth.monotonic_count));
>>> +
>>> +	md = EVP_get_digestbyname("SHA256");
>>> +	if (!md)
>>> +		goto err;
>>> +
>>> +	/* create signature */
>>> +	/* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
>>> +	flags = PKCS7_BINARY | PKCS7_DETACHED;
>>> +	p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
>>> +	if (!p7)
>>> +		goto err;
>>> +	if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
>>> +		goto err;
>>> +	if (!PKCS7_final(p7, data_bio, flags))
>>> +		goto err;
>>> +
>>> +	/* convert pkcs7 into DER */
>>> +	ctx->sig_data = NULL;
>>> +	ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
>>> +				      ASN1_ITEM_rptr(PKCS7));
>>> +	if (!ctx->sig_size)
>>> +		goto err;
>>> +
>>> +	/* fill auth_info */
>>> +	ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
>>> +						+ ctx->sig_size;
>>> +	ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
>>> +	ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
>>> +	memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
>>> +	       sizeof(efi_guid_cert_type_pkcs7));
>>> +
>>> +	ret = 0;
>>> +err:
>>> +	BIO_free_all(data_bio);
>>> +	EVP_PKEY_free(key);
>>> +	X509_free(cert);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
>>> +{
>>> +	char *sig_path;
>>> +	FILE *f;
>>> +	size_t size;
>>> +	int ret = -1;
>>> +
>>> +	sig_path = malloc(strlen(path) + 3 + 1);
>>> +	if (!sig_path)
>>> +		return ret;
>>> +
>>> +	sprintf(sig_path, "%s.p7", path);
>>> +	f = fopen(sig_path, "w");
>>> +	if (!f)
>>> +		goto err;
>>> +
>>> +	size = fwrite(signature, 1, sig_size, f);
>>> +	if (size == sig_size)
>>> +		ret = 0;
>>> +
>>> +	fclose(f);
>>> +err:
>>> +	free(sig_path);
>>> +	return ret;
>>> +}
>>> +
>>> +static void free_sig_data(struct auth_context *ctx)
>>> +{
>>> +	if (ctx->sig_size)
>>> +		OPENSSL_free(ctx->sig_data);
>>> +}
>>> +#else
>>> +static int create_auth_data(struct auth_context *ctx)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
>>> +{
>>> +	return 0;
>>> +}
>>> +
>>> +static void free_sig_data(struct auth_context *ctx) {}
>>> +#endif
>>> +
>>>    static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>> -			unsigned long index, unsigned long instance)
>>> +			unsigned long index, unsigned long instance,
>>> +			uint64_t mcount, char *privkey_file, char *cert_file)
>>>    {
>>>    	struct efi_capsule_header header;
>>>    	struct efi_firmware_management_capsule_header capsule;
>>>    	struct efi_firmware_management_capsule_image_header image;
>>> +	struct auth_context auth_context;
>>>    	FILE *f, *g;
>>>    	struct stat bin_stat;
>>>    	u8 *data;
>>> @@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>>    	printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
>>>    	printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
>>
>> [tools/mkeficapsule.c:281] (warning) %ld in format string (no. 1)
>> requires 'long' but the argument type is 'unsigned long'.
>
> Will fix it.
>
> -Takahiro Akashi
>
>
>> Best regards
>>
>> Heinrich
>>
>>>    #endif
>>> +	auth_context.sig_size = 0;
>>>
>>>    	g = fopen(bin, "r");
>>>    	if (!g) {
>>> @@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>>    		printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
>>>    		goto err_1;
>>>    	}
>>> -	f = fopen(path, "w");
>>> -	if (!f) {
>>> -		printf("cannot open %s\n", path);
>>> +
>>> +	size = fread(data, 1, bin_stat.st_size, g);
>>> +	if (size < bin_stat.st_size) {
>>> +		printf("read failed (%zx)\n", size);
>>>    		goto err_2;
>>>    	}
>>> +
>>> +	/* first, calculate signature to determine its size */
>>> +	if (privkey_file && cert_file) {
>>> +		auth_context.key_file = privkey_file;
>>> +		auth_context.cert_file = cert_file;
>>> +		auth_context.auth.monotonic_count = mcount;
>>> +		auth_context.image_data = data;
>>> +		auth_context.image_size = bin_stat.st_size;
>>> +
>>> +		if (create_auth_data(&auth_context)) {
>>> +			printf("Signing firmware image failed\n");
>>> +			goto err_3;
>>> +		}
>>> +
>>> +		if (dump_sig &&
>>> +		    dump_signature(path, auth_context.sig_data,
>>> +				   auth_context.sig_size)) {
>>> +			printf("Creating signature file failed\n");
>>> +			goto err_3;
>>> +		}
>>> +	}
>>> +
>>>    	header.capsule_guid = efi_guid_fm_capsule;
>>>    	header.header_size = sizeof(header);
>>>    	/* TODO: The current implementation ignores flags */
>>> @@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>>    					+ sizeof(capsule) + sizeof(u64)
>>>    					+ sizeof(image)
>>>    					+ bin_stat.st_size;
>>> +	if (auth_context.sig_size)
>>> +		header.capsule_image_size += sizeof(auth_context.auth)
>>> +				+ auth_context.sig_size;
>>> +
>>> +	f = fopen(path, "w");
>>> +	if (!f) {
>>> +		printf("cannot open %s\n", path);
>>> +		goto err_3;
>>> +	}
>>>
>>>    	size = fwrite(&header, 1, sizeof(header), f);
>>>    	if (size < sizeof(header)) {
>>>    		printf("write failed (%zx)\n", size);
>>> -		goto err_3;
>>> +		goto err_4;
>>>    	}
>>>
>>>    	capsule.version = 0x00000001;
>>> @@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>>    	size = fwrite(&capsule, 1, sizeof(capsule), f);
>>>    	if (size < (sizeof(capsule))) {
>>>    		printf("write failed (%zx)\n", size);
>>> -		goto err_3;
>>> +		goto err_4;
>>>    	}
>>>    	offset = sizeof(capsule) + sizeof(u64);
>>>    	size = fwrite(&offset, 1, sizeof(offset), f);
>>>    	if (size < sizeof(offset)) {
>>>    		printf("write failed (%zx)\n", size);
>>> -		goto err_3;
>>> +		goto err_4;
>>>    	}
>>>
>>>    	image.version = 0x00000003;
>>> @@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
>>>    	image.reserved[1] = 0;
>>>    	image.reserved[2] = 0;
>>>    	image.update_image_size = bin_stat.st_size;
>>> +	if (auth_context.sig_size)
>>> +		image.update_image_size += sizeof(auth_context.auth)
>>> +				+ auth_context.sig_size;
>>>    	image.update_vendor_code_size = 0; /* none */
>>>    	image.update_hardware_instance = instance;
>>>    	image.image_capsule_support = 0;
>>> +	if (auth_context.sig_size)
>>> +		image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
>>>
>>>    	size = fwrite(&image, 1, sizeof(image), f);
>>>    	if (size < sizeof(image)) {
>>>    		printf("write failed (%zx)\n", size);
>>> -		goto err_3;
>>> +		goto err_4;
>>>    	}
>>> -	size = fread(data, 1, bin_stat.st_size, g);
>>> -	if (size < bin_stat.st_size) {
>>> -		printf("read failed (%zx)\n", size);
>>> -		goto err_3;
>>> +
>>> +	if (auth_context.sig_size) {
>>> +		size = fwrite(&auth_context.auth, 1,
>>> +			      sizeof(auth_context.auth), f);
>>> +		if (size < sizeof(auth_context.auth)) {
>>> +			printf("write failed (%zx)\n", size);
>>> +			goto err_4;
>>> +		}
>>> +		size = fwrite(auth_context.sig_data, 1,
>>> +			      auth_context.sig_size, f);
>>> +		if (size < auth_context.sig_size) {
>>> +			printf("write failed (%zx)\n", size);
>>> +			goto err_4;
>>> +		}
>>>    	}
>>> +
>>>    	size = fwrite(data, 1, bin_stat.st_size, f);
>>>    	if (size < bin_stat.st_size) {
>>>    		printf("write failed (%zx)\n", size);
>>> -		goto err_3;
>>> +		goto err_4;
>>>    	}
>>>
>>>    	fclose(f);
>>>    	fclose(g);
>>>    	free(data);
>>> +	free_sig_data(&auth_context);
>>>
>>>    	return 0;
>>>
>>> -err_3:
>>> +err_4:
>>>    	fclose(f);
>>> +err_3:
>>> +	free_sig_data(&auth_context);
>>>    err_2:
>>>    	free(data);
>>>    err_1:
>>> @@ -171,23 +425,25 @@ err_1:
>>>    	return -1;
>>>    }
>>>
>>> -/*
>>> - * Usage:
>>> - *   $ mkeficapsule -f <firmware binary> <output file>
>>> - */
>>>    int main(int argc, char **argv)
>>>    {
>>>    	char *file;
>>>    	efi_guid_t *guid;
>>>    	unsigned long index, instance;
>>> +	uint64_t mcount;
>>> +	char *privkey_file, *cert_file;
>>>    	int c, idx;
>>>
>>>    	file = NULL;
>>>    	guid = NULL;
>>>    	index = 0;
>>>    	instance = 0;
>>> +	mcount = 0;
>>> +	privkey_file = NULL;
>>> +	cert_file = NULL;
>>> +	dump_sig = 0;
>>>    	for (;;) {
>>> -		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
>>> +		c = getopt_long(argc, argv, opts_short, options, &idx);
>>>    		if (c == -1)
>>>    			break;
>>>
>>> @@ -214,26 +470,44 @@ int main(int argc, char **argv)
>>>    		case 'I':
>>>    			instance = strtoul(optarg, NULL, 0);
>>>    			break;
>>> +#ifdef CONFIG_TOOLS_LIBCRYPTO
>>> +		case 'p':
>>> +			if (privkey_file) {
>>> +				printf("Private Key already specified\n");
>>> +				return -1;
>>> +			}
>>> +			privkey_file = optarg;
>>> +			break;
>>> +		case 'c':
>>> +			if (cert_file) {
>>> +				printf("Certificate file already specified\n");
>>> +				return -1;
>>> +			}
>>> +			cert_file = optarg;
>>> +			break;
>>> +		case 'm':
>>> +			mcount = strtoul(optarg, NULL, 0);
>>> +			break;
>>> +		case 'd':
>>> +			dump_sig = 1;
>>> +			break;
>>> +#endif /* CONFIG_TOOLS_LIBCRYPTO */
>>>    		case 'h':
>>>    			print_usage();
>>>    			return 0;
>>>    		}
>>>    	}
>>>
>>> -	/* need an output file */
>>> -	if (argc != optind + 1) {
>>> +	/* check necessary parameters */
>>> +	if ((argc != optind + 1) || !file ||
>>> +	    ((privkey_file && !cert_file) ||
>>> +	     (!privkey_file && cert_file))) {
>>>    		print_usage();
>>>    		exit(EXIT_FAILURE);
>>>    	}
>>>
>>> -	/* need a fit image file or raw image file */
>>> -	if (!file) {
>>> -		print_usage();
>>> -		exit(EXIT_SUCCESS);
>>> -	}
>>> -
>>> -	if (create_fwbin(argv[optind], file, guid, index, instance)
>>> -			< 0) {
>>> +	if (create_fwbin(argv[optind], file, guid, index, instance,
>>> +			 mcount, privkey_file, cert_file) < 0) {
>>>    		printf("Creating firmware capsule failed\n");
>>>    		exit(EXIT_FAILURE);
>>>    	}
>>>
>>

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

* Re: [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing
  2021-08-02  6:18       ` Heinrich Schuchardt
@ 2021-08-02  6:55         ` AKASHI Takahiro
  0 siblings, 0 replies; 30+ messages in thread
From: AKASHI Takahiro @ 2021-08-02  6:55 UTC (permalink / raw)
  To: Heinrich Schuchardt
  Cc: agraf, trini, sjg, ilias.apalodimas, sughosh.ganu,
	masami.hiramatsu, u-boot

On Mon, Aug 02, 2021 at 08:18:37AM +0200, Heinrich Schuchardt wrote:
> 
> 
> On 8/2/21 5:30 AM, AKASHI Takahiro wrote:
> > Heinrich,
> > 
> > On Sun, Aug 01, 2021 at 11:21:55AM +0200, Heinrich Schuchardt wrote:
> > > On 7/27/21 11:10 AM, AKASHI Takahiro wrote:
> > > > With this enhancement, mkeficapsule will be able to sign a capsule
> > > > file when it is created. A signature added will be used later
> > > > in the verification at FMP's SetImage() call.
> > > > 
> > > > To do that, We need specify additional command parameters:
> > > >     -monotonic-cout <count> : monotonic count
> > > >     -private-key <private key file> : private key file
> > > >     -certificate <certificate file> : certificate file
> > > > Only when all of those parameters are given, a signature will be added
> > > > to a capsule file.
> > > > 
> > > > Users are expected to maintain and increment the monotonic count at
> > > > every time of the update for each firmware image.
> > > > 
> > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > ---
> > > >    tools/Kconfig        |   7 +
> > > >    tools/Makefile       |   8 +-
> > > >    tools/mkeficapsule.c | 332 +++++++++++++++++++++++++++++++++++++++----
> > > >    3 files changed, 316 insertions(+), 31 deletions(-)
> > > > 
> > > > diff --git a/tools/Kconfig b/tools/Kconfig
> > > > index d6f82cd949b5..9a37ed035311 100644
> > > > --- a/tools/Kconfig
> > > > +++ b/tools/Kconfig
> > > > @@ -20,4 +20,11 @@ config TOOLS_LIBCRYPTO
> > > >    	  This selection does not affect target features, such as runtime FIT
> > > >    	  signature verification.
> > > > 
> > > > +config TOOLS_MKEFICAPSULE
> > > > +	bool "Build efimkcapsule command"
> > > > +	default y if EFI_CAPSULE_ON_DISK
> > > > +	help
> > > > +	  This command allows users to create a UEFI capsule file and,
> > > > +	  optionally sign that file. If you want to enable UEFI capsule
> > > > +	  update feature on your target, you certainly need this.
> > > >    endmenu
> > > > diff --git a/tools/Makefile b/tools/Makefile
> > > > index bae3f95c4995..af8536489652 100644
> > > > --- a/tools/Makefile
> > > > +++ b/tools/Makefile
> > > > @@ -245,8 +245,12 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
> > > >    hostprogs-$(CONFIG_ASN1_COMPILER)	+= asn1_compiler
> > > >    HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
> > > > 
> > > > -mkeficapsule-objs	:= mkeficapsule.o $(LIBFDT_OBJS)
> > > > -hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
> > > > +HOSTLDLIBS_mkeficapsule += -luuid
> > > > +ifeq ($(CONFIG_TOOLS_LIBCRYPTO),y)
> > > > +HOSTLDLIBS_mkeficapsule += \
> > > > +	$(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
> > > 
> > > Please, add package pkg-config to the build dependencies enumerated in
> > > doc/build/gcc.rst.
> > 
> > Already there: libssl-dev
> 
> It is *pkg-config* that is missing.

OK, I see what you mean.
But this use is not quite new as the first appearance of
pkg-config was found in the commit 4839836a124e
  Author: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
  Date:   Sat May 16 18:36:15 2015 +0200

    tools: use pkg-config when available to get SSL flags

So a separate patch would be appropriate.

-Takahiro Akashi

> > 
> > > > +endif
> > > > +hostprogs-$(CONFIG_TOOLS_MKEFICAPSULE) += mkeficapsule
> > > > 
> > > >    # We build some files with extra pedantic flags to try to minimize things
> > > >    # that won't build on some weird host compiler -- though there are lots of
> > > > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> > > > index 4995ba4e0c2a..798706c7b5f7 100644
> > > > --- a/tools/mkeficapsule.c
> > > > +++ b/tools/mkeficapsule.c
> > > > @@ -15,6 +15,16 @@
> > > >    #include <sys/stat.h>
> > > >    #include <sys/types.h>
> > > > 
> > > > +#include <linux/kconfig.h>
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +#include <openssl/asn1.h>
> > > > +#include <openssl/bio.h>
> > > > +#include <openssl/evp.h>
> > > > +#include <openssl/err.h>
> > > > +#include <openssl/pem.h>
> > > > +#include <openssl/pkcs7.h>
> > > > +#endif
> > > > +
> > > >    typedef __u8 u8;
> > > >    typedef __u16 u16;
> > > >    typedef __u32 u32;
> > > > @@ -38,12 +48,25 @@ efi_guid_t efi_guid_image_type_uboot_fit =
> > > >    		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
> > > >    efi_guid_t efi_guid_image_type_uboot_raw =
> > > >    		EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
> > > > +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> > > > +
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +static const char *opts_short = "f:r:i:I:v:p:c:m:dh";
> > > > +#else
> > > > +static const char *opts_short = "f:r:i:I:v:h";
> > > > +#endif
> > > > 
> > > >    static struct option options[] = {
> > > >    	{"fit", required_argument, NULL, 'f'},
> > > >    	{"raw", required_argument, NULL, 'r'},
> > > >    	{"index", required_argument, NULL, 'i'},
> > > >    	{"instance", required_argument, NULL, 'I'},
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +	{"private-key", required_argument, NULL, 'p'},
> > > > +	{"certificate", required_argument, NULL, 'c'},
> > > > +	{"monotonic-count", required_argument, NULL, 'm'},
> > > > +	{"dump-sig", no_argument, NULL, 'd'},
> > > > +#endif
> > > >    	{"help", no_argument, NULL, 'h'},
> > > >    	{NULL, 0, NULL, 0},
> > > >    };
> > > > @@ -57,16 +80,195 @@ static void print_usage(void)
> > > >    	       "\t-r, --raw <raw image>       new raw image file\n"
> > > >    	       "\t-i, --index <index>         update image index\n"
> > > >    	       "\t-I, --instance <instance>   update hardware instance\n"
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +	       "\t-p, --private-key <privkey file>  private key file\n"
> > > > +	       "\t-c, --certificate <cert file>     signer's certificate file\n"
> > > > +	       "\t-m, --monotonic-count <count>     monotonic count\n"
> > > > +	       "\t-d, --dump_sig              dump signature (*.p7)\n"
> > > > +#endif
> > > >    	       "\t-h, --help                  print a help message\n",
> > > >    	       tool_name);
> > > >    }
> > > > 
> > > 
> > > Please, add Sphinx documentation.
> > 
> > I added the man page. Why need another different format of doc?
> > I think that doc/develop/uefi/uefi.rst gives you an enough
> > introduction to the command.
> > (Although the doc will have to been updated due to the latest change
> > of mkeficapsule syntax that I'm also proposing.)
> > 
> > Actually, there is no sphinx doc for any host tools.
> > 
> > > > +struct auth_context {
> > > > +	char *key_file;
> > > > +	char *cert_file;
> > > > +	u8 *image_data;
> > > > +	size_t image_size;
> > > > +	struct efi_firmware_image_authentication auth;
> > > > +	u8 *sig_data;
> > > > +	size_t sig_size;
> > > > +};
> > > > +
> > > > +static int dump_sig;
> > > > +
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +static EVP_PKEY *fileio_read_pkey(const char *filename)
> > > > +{
> > > > +	EVP_PKEY *key = NULL;
> > > > +	BIO *bio;
> > > > +
> > > > +	bio = BIO_new_file(filename, "r");
> > > > +	if (!bio)
> > > > +		goto out;
> > > > +
> > > > +	key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
> > > > +
> > > > +out:
> > > > +	BIO_free_all(bio);
> > > > +	if (!key) {
> > > > +		printf("Can't load key from file '%s'\n", filename);
> > > > +		ERR_print_errors_fp(stderr);
> > > > +	}
> > > > +
> > > > +	return key;
> > > > +}
> > > > +
> > > 
> > > Please, add Sphinx documentation for all functions.
> > 
> > Yeah, but "all" is a too forcible requirement.
> > There is no source code of host tools to meet the requirement.
> > Actually, most don't have even one description of a function.
> > 
> > I think that, if it is a really required element in the source,
> > it should be explicitly described somewhere under "doc".
> > 
> > > > +static X509 *fileio_read_cert(const char *filename)
> > > > +{
> > > > +	X509 *cert = NULL;
> > > > +	BIO *bio;
> > > > +
> > > > +	bio = BIO_new_file(filename, "r");
> > > > +	if (!bio)
> > > > +		goto out;
> > > > +
> > > > +	cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
> > > > +
> > > > +out:
> > > > +	BIO_free_all(bio);
> > > > +	if (!cert) {
> > > > +		printf("Can't load certificate from file '%s'\n", filename);
> > > > +		ERR_print_errors_fp(stderr);
> > > > +	}
> > > > +
> > > > +	return cert;
> > > > +}
> > > > +
> > > > +static int create_auth_data(struct auth_context *ctx)
> > > > +{
> > > > +	EVP_PKEY *key = NULL;
> > > > +	X509 *cert = NULL;
> > > > +	BIO *data_bio = NULL;
> > > > +	const EVP_MD *md;
> > > > +	PKCS7 *p7;
> > > > +	int flags, ret = -1;
> > > > +
> > > > +	OpenSSL_add_all_digests();
> > > > +	OpenSSL_add_all_ciphers();
> > > > +	ERR_load_crypto_strings();
> > > > +
> > > > +	key = fileio_read_pkey(ctx->key_file);
> > > > +	if (!key)
> > > > +		goto err;
> > > > +	cert = fileio_read_cert(ctx->cert_file);
> > > > +	if (!cert)
> > > > +		goto err;
> > > > +
> > > > +	/*
> > > > +	 * create a BIO, containing:
> > > > +	 *  * firmware image
> > > > +	 *  * monotonic count
> > > > +	 * in this order!
> > > > +	 * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
> > > > +	 */
> > > > +	data_bio = BIO_new(BIO_s_mem());
> > > > +	BIO_write(data_bio, ctx->image_data, ctx->image_size);
> > > > +	BIO_write(data_bio, &ctx->auth.monotonic_count,
> > > > +		  sizeof(ctx->auth.monotonic_count));
> > > > +
> > > > +	md = EVP_get_digestbyname("SHA256");
> > > > +	if (!md)
> > > > +		goto err;
> > > > +
> > > > +	/* create signature */
> > > > +	/* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
> > > > +	flags = PKCS7_BINARY | PKCS7_DETACHED;
> > > > +	p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
> > > > +	if (!p7)
> > > > +		goto err;
> > > > +	if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
> > > > +		goto err;
> > > > +	if (!PKCS7_final(p7, data_bio, flags))
> > > > +		goto err;
> > > > +
> > > > +	/* convert pkcs7 into DER */
> > > > +	ctx->sig_data = NULL;
> > > > +	ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
> > > > +				      ASN1_ITEM_rptr(PKCS7));
> > > > +	if (!ctx->sig_size)
> > > > +		goto err;
> > > > +
> > > > +	/* fill auth_info */
> > > > +	ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
> > > > +						+ ctx->sig_size;
> > > > +	ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> > > > +	ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> > > > +	memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
> > > > +	       sizeof(efi_guid_cert_type_pkcs7));
> > > > +
> > > > +	ret = 0;
> > > > +err:
> > > > +	BIO_free_all(data_bio);
> > > > +	EVP_PKEY_free(key);
> > > > +	X509_free(cert);
> > > > +
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> > > > +{
> > > > +	char *sig_path;
> > > > +	FILE *f;
> > > > +	size_t size;
> > > > +	int ret = -1;
> > > > +
> > > > +	sig_path = malloc(strlen(path) + 3 + 1);
> > > > +	if (!sig_path)
> > > > +		return ret;
> > > > +
> > > > +	sprintf(sig_path, "%s.p7", path);
> > > > +	f = fopen(sig_path, "w");
> > > > +	if (!f)
> > > > +		goto err;
> > > > +
> > > > +	size = fwrite(signature, 1, sig_size, f);
> > > > +	if (size == sig_size)
> > > > +		ret = 0;
> > > > +
> > > > +	fclose(f);
> > > > +err:
> > > > +	free(sig_path);
> > > > +	return ret;
> > > > +}
> > > > +
> > > > +static void free_sig_data(struct auth_context *ctx)
> > > > +{
> > > > +	if (ctx->sig_size)
> > > > +		OPENSSL_free(ctx->sig_data);
> > > > +}
> > > > +#else
> > > > +static int create_auth_data(struct auth_context *ctx)
> > > > +{
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> > > > +{
> > > > +	return 0;
> > > > +}
> > > > +
> > > > +static void free_sig_data(struct auth_context *ctx) {}
> > > > +#endif
> > > > +
> > > >    static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > > -			unsigned long index, unsigned long instance)
> > > > +			unsigned long index, unsigned long instance,
> > > > +			uint64_t mcount, char *privkey_file, char *cert_file)
> > > >    {
> > > >    	struct efi_capsule_header header;
> > > >    	struct efi_firmware_management_capsule_header capsule;
> > > >    	struct efi_firmware_management_capsule_image_header image;
> > > > +	struct auth_context auth_context;
> > > >    	FILE *f, *g;
> > > >    	struct stat bin_stat;
> > > >    	u8 *data;
> > > > @@ -78,6 +280,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > >    	printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
> > > >    	printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
> > > 
> > > [tools/mkeficapsule.c:281] (warning) %ld in format string (no. 1)
> > > requires 'long' but the argument type is 'unsigned long'.
> > 
> > Will fix it.
> > 
> > -Takahiro Akashi
> > 
> > 
> > > Best regards
> > > 
> > > Heinrich
> > > 
> > > >    #endif
> > > > +	auth_context.sig_size = 0;
> > > > 
> > > >    	g = fopen(bin, "r");
> > > >    	if (!g) {
> > > > @@ -93,11 +296,34 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > >    		printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
> > > >    		goto err_1;
> > > >    	}
> > > > -	f = fopen(path, "w");
> > > > -	if (!f) {
> > > > -		printf("cannot open %s\n", path);
> > > > +
> > > > +	size = fread(data, 1, bin_stat.st_size, g);
> > > > +	if (size < bin_stat.st_size) {
> > > > +		printf("read failed (%zx)\n", size);
> > > >    		goto err_2;
> > > >    	}
> > > > +
> > > > +	/* first, calculate signature to determine its size */
> > > > +	if (privkey_file && cert_file) {
> > > > +		auth_context.key_file = privkey_file;
> > > > +		auth_context.cert_file = cert_file;
> > > > +		auth_context.auth.monotonic_count = mcount;
> > > > +		auth_context.image_data = data;
> > > > +		auth_context.image_size = bin_stat.st_size;
> > > > +
> > > > +		if (create_auth_data(&auth_context)) {
> > > > +			printf("Signing firmware image failed\n");
> > > > +			goto err_3;
> > > > +		}
> > > > +
> > > > +		if (dump_sig &&
> > > > +		    dump_signature(path, auth_context.sig_data,
> > > > +				   auth_context.sig_size)) {
> > > > +			printf("Creating signature file failed\n");
> > > > +			goto err_3;
> > > > +		}
> > > > +	}
> > > > +
> > > >    	header.capsule_guid = efi_guid_fm_capsule;
> > > >    	header.header_size = sizeof(header);
> > > >    	/* TODO: The current implementation ignores flags */
> > > > @@ -106,11 +332,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > >    					+ sizeof(capsule) + sizeof(u64)
> > > >    					+ sizeof(image)
> > > >    					+ bin_stat.st_size;
> > > > +	if (auth_context.sig_size)
> > > > +		header.capsule_image_size += sizeof(auth_context.auth)
> > > > +				+ auth_context.sig_size;
> > > > +
> > > > +	f = fopen(path, "w");
> > > > +	if (!f) {
> > > > +		printf("cannot open %s\n", path);
> > > > +		goto err_3;
> > > > +	}
> > > > 
> > > >    	size = fwrite(&header, 1, sizeof(header), f);
> > > >    	if (size < sizeof(header)) {
> > > >    		printf("write failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +		goto err_4;
> > > >    	}
> > > > 
> > > >    	capsule.version = 0x00000001;
> > > > @@ -119,13 +354,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > >    	size = fwrite(&capsule, 1, sizeof(capsule), f);
> > > >    	if (size < (sizeof(capsule))) {
> > > >    		printf("write failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +		goto err_4;
> > > >    	}
> > > >    	offset = sizeof(capsule) + sizeof(u64);
> > > >    	size = fwrite(&offset, 1, sizeof(offset), f);
> > > >    	if (size < sizeof(offset)) {
> > > >    		printf("write failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +		goto err_4;
> > > >    	}
> > > > 
> > > >    	image.version = 0x00000003;
> > > > @@ -135,34 +370,53 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> > > >    	image.reserved[1] = 0;
> > > >    	image.reserved[2] = 0;
> > > >    	image.update_image_size = bin_stat.st_size;
> > > > +	if (auth_context.sig_size)
> > > > +		image.update_image_size += sizeof(auth_context.auth)
> > > > +				+ auth_context.sig_size;
> > > >    	image.update_vendor_code_size = 0; /* none */
> > > >    	image.update_hardware_instance = instance;
> > > >    	image.image_capsule_support = 0;
> > > > +	if (auth_context.sig_size)
> > > > +		image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
> > > > 
> > > >    	size = fwrite(&image, 1, sizeof(image), f);
> > > >    	if (size < sizeof(image)) {
> > > >    		printf("write failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +		goto err_4;
> > > >    	}
> > > > -	size = fread(data, 1, bin_stat.st_size, g);
> > > > -	if (size < bin_stat.st_size) {
> > > > -		printf("read failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +
> > > > +	if (auth_context.sig_size) {
> > > > +		size = fwrite(&auth_context.auth, 1,
> > > > +			      sizeof(auth_context.auth), f);
> > > > +		if (size < sizeof(auth_context.auth)) {
> > > > +			printf("write failed (%zx)\n", size);
> > > > +			goto err_4;
> > > > +		}
> > > > +		size = fwrite(auth_context.sig_data, 1,
> > > > +			      auth_context.sig_size, f);
> > > > +		if (size < auth_context.sig_size) {
> > > > +			printf("write failed (%zx)\n", size);
> > > > +			goto err_4;
> > > > +		}
> > > >    	}
> > > > +
> > > >    	size = fwrite(data, 1, bin_stat.st_size, f);
> > > >    	if (size < bin_stat.st_size) {
> > > >    		printf("write failed (%zx)\n", size);
> > > > -		goto err_3;
> > > > +		goto err_4;
> > > >    	}
> > > > 
> > > >    	fclose(f);
> > > >    	fclose(g);
> > > >    	free(data);
> > > > +	free_sig_data(&auth_context);
> > > > 
> > > >    	return 0;
> > > > 
> > > > -err_3:
> > > > +err_4:
> > > >    	fclose(f);
> > > > +err_3:
> > > > +	free_sig_data(&auth_context);
> > > >    err_2:
> > > >    	free(data);
> > > >    err_1:
> > > > @@ -171,23 +425,25 @@ err_1:
> > > >    	return -1;
> > > >    }
> > > > 
> > > > -/*
> > > > - * Usage:
> > > > - *   $ mkeficapsule -f <firmware binary> <output file>
> > > > - */
> > > >    int main(int argc, char **argv)
> > > >    {
> > > >    	char *file;
> > > >    	efi_guid_t *guid;
> > > >    	unsigned long index, instance;
> > > > +	uint64_t mcount;
> > > > +	char *privkey_file, *cert_file;
> > > >    	int c, idx;
> > > > 
> > > >    	file = NULL;
> > > >    	guid = NULL;
> > > >    	index = 0;
> > > >    	instance = 0;
> > > > +	mcount = 0;
> > > > +	privkey_file = NULL;
> > > > +	cert_file = NULL;
> > > > +	dump_sig = 0;
> > > >    	for (;;) {
> > > > -		c = getopt_long(argc, argv, "f:r:i:I:v:h", options, &idx);
> > > > +		c = getopt_long(argc, argv, opts_short, options, &idx);
> > > >    		if (c == -1)
> > > >    			break;
> > > > 
> > > > @@ -214,26 +470,44 @@ int main(int argc, char **argv)
> > > >    		case 'I':
> > > >    			instance = strtoul(optarg, NULL, 0);
> > > >    			break;
> > > > +#ifdef CONFIG_TOOLS_LIBCRYPTO
> > > > +		case 'p':
> > > > +			if (privkey_file) {
> > > > +				printf("Private Key already specified\n");
> > > > +				return -1;
> > > > +			}
> > > > +			privkey_file = optarg;
> > > > +			break;
> > > > +		case 'c':
> > > > +			if (cert_file) {
> > > > +				printf("Certificate file already specified\n");
> > > > +				return -1;
> > > > +			}
> > > > +			cert_file = optarg;
> > > > +			break;
> > > > +		case 'm':
> > > > +			mcount = strtoul(optarg, NULL, 0);
> > > > +			break;
> > > > +		case 'd':
> > > > +			dump_sig = 1;
> > > > +			break;
> > > > +#endif /* CONFIG_TOOLS_LIBCRYPTO */
> > > >    		case 'h':
> > > >    			print_usage();
> > > >    			return 0;
> > > >    		}
> > > >    	}
> > > > 
> > > > -	/* need an output file */
> > > > -	if (argc != optind + 1) {
> > > > +	/* check necessary parameters */
> > > > +	if ((argc != optind + 1) || !file ||
> > > > +	    ((privkey_file && !cert_file) ||
> > > > +	     (!privkey_file && cert_file))) {
> > > >    		print_usage();
> > > >    		exit(EXIT_FAILURE);
> > > >    	}
> > > > 
> > > > -	/* need a fit image file or raw image file */
> > > > -	if (!file) {
> > > > -		print_usage();
> > > > -		exit(EXIT_SUCCESS);
> > > > -	}
> > > > -
> > > > -	if (create_fwbin(argv[optind], file, guid, index, instance)
> > > > -			< 0) {
> > > > +	if (create_fwbin(argv[optind], file, guid, index, instance,
> > > > +			 mcount, privkey_file, cert_file) < 0) {
> > > >    		printf("Creating firmware capsule failed\n");
> > > >    		exit(EXIT_FAILURE);
> > > >    	}
> > > > 
> > > 

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

* Re: [PATCH v2 6/9] sandbox: add config for efi capsule authentication test
  2021-08-01 22:57         ` AKASHI Takahiro
@ 2021-08-02 19:19           ` Simon Glass
  0 siblings, 0 replies; 30+ messages in thread
From: Simon Glass @ 2021-08-02 19:19 UTC (permalink / raw)
  To: AKASHI Takahiro, Simon Glass, Heinrich Schuchardt, Alex Graf,
	Tom Rini, Ilias Apalodimas, Sughosh Ganu, Masami Hiramatsu,
	U-Boot Mailing List

Hi Takahiro,

On Sun, 1 Aug 2021 at 16:57, AKASHI Takahiro <takahiro.akashi@linaro.org> wrote:
>
> Simon,
>
> On Sun, Aug 01, 2021 at 01:00:20PM -0600, Simon Glass wrote:
> > Hi Takahiro,
> >
> > On Sat, 31 Jul 2021 at 22:29, AKASHI Takahiro
> > <takahiro.akashi@linaro.org> wrote:
> > >
> > > Simon,
> > >
> > > On Sat, Jul 31, 2021 at 10:59:32AM -0600, Simon Glass wrote:
> > > > Hi Takahiro,
> > > >
> > > > On Tue, 27 Jul 2021 at 03:12, AKASHI Takahiro
> > > > <takahiro.akashi@linaro.org> wrote:
> > > > >
> > > > > This new configuration, which was derived from sandbox_defconfig, will be
> > > > > used solely to run efi capsule authentication test as the test requires
> > > > > a public key (esl file) to be embedded in U-Boot binary.
> > > > >
> > > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
> > > > > ---
> > > > >  configs/sandbox_capsule_auth_defconfig | 307 +++++++++++++++++++++++++
> > > > >  1 file changed, 307 insertions(+)
> > > > >  create mode 100644 configs/sandbox_capsule_auth_defconfig
> > > >
> > > > NAK.
> > > >
> > > > Please just add it to sandbox_defconfig. We sometimes have to create
> > >
> > > Unfortunately, I can't.
> > > Look, we now have two tests, test_capsule_firmware.py and
> > > test_capsule_firmware_signed.py, and we need U-Boot binaries,
> > > respectively, without a key and with a key.
> > > A single configuration cannot satisfy both.
> > >
> > > > new variants when dealing with actual build variations (e.g. SPL,
> > > > building without OF_LIVE), but here we should just enable the feature
> > > > in sandbox_defconfig.
> > > >
> > > > We already covered embedding key in the binary on another thread.
> > > > Please don't do that. After that debacle I sent a patch explaining
> > > > this:
> > > >
> > > > http://patchwork.ozlabs.org/project/uboot/patch/20210725164400.468319-3-sjg@chromium.org/
> > >
> > > Please discuss and make an agreement with Heinrich.
> > > The patch for embedding a key has already been merged in -rc1.
> >
> > Which patch was that? I thought I pushed back on the one that did that.
>
> The commit ddf67daac39d
>   Author: Ilias Apalodimas <ilias.apalodimas@linaro.org>
>   Date:   Sat Jul 17 17:26:44 2021 +0300
>
>     efi_capsule: Move signature from DTB to .rodata

OK I sent a revert of that as you saw. Then I sent a v2 revert of
three patches when you explained that was not enough. I hope we can
figure this out quickly.

>
>
> > > In my personal opinion, neither approaches won't apply to production
> > > any way.

I have not seen any design for how EFI signing would work in
production but I am happy to review it. The existing FIT-signing
scheme is widely used in production environments. If we use similar
processes then we should be OK.

Regards,
Simon

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

end of thread, other threads:[~2021-08-02 19:20 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-27  9:10 [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 1/9] tools: mkeficapsule: add firmwware image signing AKASHI Takahiro
2021-07-28  8:12   ` Masami Hiramatsu
2021-08-01  9:21   ` Heinrich Schuchardt
2021-08-02  3:30     ` AKASHI Takahiro
2021-08-02  6:18       ` Heinrich Schuchardt
2021-08-02  6:55         ` AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 2/9] tools: mkeficapsule: add man page AKASHI Takahiro
2021-08-01  9:28   ` Heinrich Schuchardt
2021-07-27  9:10 ` [PATCH v2 3/9] doc: update UEFI document for usage of mkeficapsule AKASHI Takahiro
2021-08-01  9:31   ` Heinrich Schuchardt
2021-07-27  9:10 ` [PATCH v2 4/9] efi_loader: ease the file path check for public key AKASHI Takahiro
2021-08-01  9:35   ` Heinrich Schuchardt
2021-08-02  4:50     ` AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 5/9] test/py: efi_capsule: add image authentication test AKASHI Takahiro
2021-08-01  9:38   ` Heinrich Schuchardt
2021-08-02  4:02     ` AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 6/9] sandbox: add config for efi capsule " AKASHI Takahiro
2021-07-28 20:21   ` Heinrich Schuchardt
2021-07-29  0:39     ` AKASHI Takahiro
2021-07-31 16:59   ` Simon Glass
2021-08-01  4:29     ` AKASHI Takahiro
2021-08-01 19:00       ` Simon Glass
2021-08-01 22:57         ` AKASHI Takahiro
2021-08-02 19:19           ` Simon Glass
2021-07-27  9:10 ` [PATCH v2 7/9] GitLab: add a test rule " AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 8/9] tools: mkeficapsule: allow for specifying GUID explicitly AKASHI Takahiro
2021-07-27  9:10 ` [PATCH v2 9/9] test/py: efi_capsule: align with the syntax change of mkeficapsule AKASHI Takahiro
2021-08-01  9:40 ` [PATCH v2 0/9] efi_loader: capsule: improve capsule authentication support Heinrich Schuchardt
2021-08-02  5:00   ` AKASHI Takahiro

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