All of lore.kernel.org
 help / color / mirror / Atom feed
From: Pegorer Massimo <Massimo.Pegorer@vimar.com>
To: Simon Glass <sjg@chromium.org>,
	Sean Anderson <sean.anderson@seco.com>,
	"u-boot@lists.denx.de" <u-boot@lists.denx.de>
Subject: [PATCH] mkimage: fit: Support signed configurations in 'auto' FITs
Date: Sun, 11 Dec 2022 14:54:21 +0000	[thread overview]
Message-ID: <GV1PR08MB801066863097F9433F1BD87CE51E9@GV1PR08MB8010.eurprd08.prod.outlook.com> (raw)
In-Reply-To: <GV1PR08MB801062D500653F19EF7F7BF1E51C9@GV1PR08MB8010.eurprd08.prod.outlook.com>

Hi,

The patch follows, as per discussion in email thread "Patch proposal
 - mkimage: fit: Support signed conf 'auto' FITs". Let me know if you
prefer something to be changed, or patch to be split in several
commits.

I have updated the man page with description of the new feature and
examples. Also fixed some wrong or misleading information.

===

mkimage: fit: Support signed configurations in 'auto' FITs

Extend support for signing in auto-generated (-f auto) FIT. Previously,
it was possible to get signed 'images' subnodes in the FIT using
options -g and -o together with -f auto. This patch allows signing
'configurations' subnodes instead of 'images' ones (which are hashed),
using option -f auto-conf instead of -f auto. Adding also -K <dtb> and
-r options, will add public key to <dtb> file with required = "conf"
property.

Summary:
    -f auto => FIT with crc32 images
    -f auto -g ... -o ... => FIT with signed images
    -f auto-conf -g ... -o ... => FIT with sha1 images and signed confs

Example: FIT with kernel, two device tree files, and signed
configurations; public key (needed to verify signatures) is
added to u-boot.dtb with required = "conf" property.

mkimage -f auto-conf -A arm -O linux -T kernel -C none -a 43e00000 \
        -e 0 -d vmlinuz -b /path/to/first.dtb -b /path/to/second.dtb \
        -k /folder/with/key-files -g keyname -o sha256,rsa4096 \
        -K u-boot.dtb -r kernel.itb

Example: Add public key with required = "conf" property to u-boot.dtb
without needing to sign anything. This will also create a useless FIT
named unused.itb.

mkimage -f auto-conf -d /dev/null -k /folder/with/key-files \
        -g keyname -o sha256,rsa4096 -K u-boot.dtb -r unused.itb

Signed-off-by: Massimo Pegorer <massimo.pegorer@vimar.com>
---
 doc/mkimage.1     | 119 ++++++++++++++++++++++++++++++++--------------
 tools/fit_image.c |  75 +++++++++++++++++++----------
 tools/imagetool.h |  10 +++-
 tools/mkimage.c   |  23 +++++++--
 4 files changed, 160 insertions(+), 67 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 353ea8b2f7..d8727ec73c 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -22,7 +22,8 @@ mkimage \- generate images for U-Boot
 .SY mkimage
 .RI [ option\~ .\|.\|.\&]
 .BI \-f\~ image-tree-source-file\c
-.RB | auto
+.RB | auto\c
+.RB | auto-conf
 .I image-file-name
 .YS
 .
@@ -296,9 +297,9 @@ FIT. See
 for details on using external data.
 .
 .TP
-\fB\-f \fIimage-tree-source-file\fR | \fBauto
+\fB\-f \fIimage-tree-source-file\fR | \fBauto\fR | \fBauto-conf
 .TQ
-\fB\-\-fit \fIimage-tree-source-file\fR | \fBauto
+\fB\-\-fit \fIimage-tree-source-file\fR | \fBauto\fR | \fBauto-conf
 Image tree source file that describes the structure and contents of the
 FIT image.
 .IP
@@ -317,7 +318,25 @@ and
 options may be used to specify the image to include in the FIT and its
 attributes. No
 .I image-tree-source-file
-is required.
+is required. The
+.BR \-g ,
+.BR \-o ,
+and
+.B \-k
+or
+.B \-G
+options may be used to get \(oqimages\(cq signed subnodes in the generated
+auto FIT. Instead, to get \(oqconfigurations\(cq signed subnodes and
+\(oqimages\(cq hashed subnodes, pass
+.BR "\-f auto-conf".
+In this case
+.BR \-g ,
+.BR \-o ,
+and
+.B \-k
+or
+.B \-G
+are mandatory options.
 .
 .TP
 .B \-F
@@ -348,16 +367,16 @@ for use with signing, and a certificate
 necessary when embedding it into another device tree using
 .BR \-K .
 .I name
-defaults to the value of the signature node's \(oqkey-name-hint\(cq property,
-but may be overridden using
-.BR \-g .
+is the value of the signature node's \(oqkey-name-hint\(cq property.
 .
 .TP
 .BI \-G " key-file"
 .TQ
 .BI \-\-key\-file " key-file"
 Specifies the private key file to use when signing. This option may be used
-instead of \-k.
+instead of \-k. Useful when the private key file basename does not match
+\(oqkey-name-hint\(cq value. But note that it may lead to unexpected results
+when used together with -K and/or -k options.
 .
 .TP
 .BI \-K " key-destination"
@@ -373,49 +392,50 @@ CONFIG_OF_CONTROL in U-Boot.
 .BI \-g " key-name-hint"
 .TQ
 .BI \-\-key\-name\-hint " key-name-hint"
-Overrides the signature node's \(oqkey-name-hint\(cq property. This is
-especially useful when signing an image with
-.BR "\-f auto" .
-This is the
-.I name
-part of the key. The directory part is set by
-.BR \-k .
-This option also indicates that the images included in the FIT should be signed.
-If this option is specified, then
+Specifies the value of signature node \(oqkey-name-hint\(cq property for
+an automatically generated FIT image. It makes sense only when used with
+.B "\-f auto"
+or
+.BR "\-f auto-conf".
+This option also indicates that the images or configurations included in
+the FIT should be signed. If this option is specified, then
 .B \-o
 must be specified as well.
 .
 .TP
-.BI \-o " crypto" , checksum
+.BI \-o " checksum" , crypto
 .TQ
-.BI \-\-algo " crypto" , checksum
-Specifies the algorithm to be used for signing a FIT image. The default is
-taken from the signature node's \(oqalgo\(cq property.
+.BI \-\-algo " checksum" , crypto
+Specifies the algorithm to be used for signing a FIT image, overriding value
+taken from the signature node \(oqalgo\(cq property in the
+.IR image-tree-source-file .
+It is mandatory for automatically generated FIT.
+.IP
 The valid values for
-.I crypto
+.I checksum
 are:
 .RS
 .IP
 .TS
 lb.
-rsa2048
-rsa3072
-rsa4096
-ecdsa256
+sha1
+sha256
+sha384
+sha512
 .TE
 .RE
 .IP
 The valid values for
-.I checksum
-are
+.I crypto
+are:
 .RS
 .IP
 .TS
 lb.
-sha1
-sha256
-sha384
-sha512
+rsa2048
+rsa3072
+rsa4096
+ecdsa256
 .TE
 .RE
 .
@@ -423,9 +443,13 @@ sha512
 .B \-r
 .TQ
 .B \-\-key\-required
-Specifies that keys used to sign the FIT are required. This means that they
-must be verified for the image to boot. Without this option, the verification
-will be optional (useful for testing but not for release).
+Specifies that keys used to sign the FIT are required. This means that images
+or configurations signatures must be verified before using them (i.e. to
+boot). Without this option, the verification will be optional (useful for
+testing but not for release). It makes sense only when used with
+.BR \-K.
+When both, images and configurations, are signed, \(oqrequired\(cq property
+value will be "conf".
 .
 .TP
 .BI \-N " engine"
@@ -716,7 +740,7 @@ skipping those for which keys cannot be found. Also add a comment.
 .EE
 .RE
 .P
-Add public keys to u\-boot.dtb without needing a FIT to sign. This will also
+Add public key to u\-boot.dtb without needing a FIT to sign. This will also
 create a FIT containing an images node with no data named unused.itb.
 .RS
 .P
@@ -726,6 +750,16 @@ create a FIT containing an images node with no data named unused.itb.
 .EE
 .RE
 .P
+Add public key with required = "conf" property to u\-boot.dtb without needing
+a FIT to sign. This will also create a useless FIT named unused.itb.
+.RS
+.P
+.EX
+\fBmkimage \-f auto-conf \-d /dev/null \-k /public/signing\-keys \-g dev \\
+	\-o sha256,rsa2048 \-K u\-boot.dtb -r unused.itb
+.EE
+.RE
+.P
 Update an existing FIT image, signing it with additional keys.
 Add corresponding public keys into u\-boot.dtb. This will resign all images
 with keys that are available in the new directory. Images that request signing
@@ -768,6 +802,19 @@ file is required.
 	\-d vmlinuz \-k /secret/signing\-keys \-g dev \-o sha256,rsa2048 kernel.itb
 .EE
 .RE
+.P
+Create a FIT image containing a kernel and some device tree files, signing
+each configuration, using automatic mode. Moreover, the public key needed to
+verify signatures is added to u\-boot.dtb with required = "conf" property.
+.RS
+.P
+.EX
+\fBmkimage \-f auto-conf \-A arm \-O linux \-T kernel \-C none \-a 43e00000 \\
+	\-e 0 \-d vmlinuz \-b /path/to/file\-1.dtb \-b /path/to/file\-2.dtb \\
+	\-k /folder/with/signing\-keys \-g dev \-o sha256,rsa2048 \\
+	\-K u\-boot.dtb -r kernel.itb
+.EE
+.RE
 .
 .SH SEE ALSO
 .BR dtc (1),
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 923a9755b7..d15a377779 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -199,36 +199,59 @@ static void get_basename(char *str, int size, const char *fname)
 }
 
 /**
- * add_hash_node() - Add a hash or signature node
+ * fit_add_hash_or_sign() - Add a hash or signature node
  *
  * @params: Image parameters
  * @fdt: Device tree to add to (in sequential-write mode)
+ * @is_images_subnode: true to add hash even if key name hint is provided
  *
- * If there is a key name hint, try to sign the images. Otherwise, just add a
- * CRC.
- *
- * Return: 0 on success, or -1 on failure
+ * If do_add_hash is false (default) and there is a key name hint, try to add
+ * a sign node to parent. Otherwise, just add a CRC. Rationale: if conf have
+ * to be signed, image/dt have to be hashed even if there is a key name hint.
  */
-static int add_hash_node(struct image_tool_params *params, void *fdt)
+static void fit_add_hash_or_sign(struct image_tool_params *params, void *fdt,
+				 bool is_images_subnode)
 {
-	if (params->keyname) {
-		if (!params->algo_name) {
-			fprintf(stderr,
-				"%s: Algorithm name must be specified\n",
-				params->cmdname);
-			return -1;
+	const char *hash_algo = "crc32";
+	bool do_hash = false;
+	bool do_sign = false;
+
+	switch (params->auto_fit) {
+	case AF_OFF:
+		break;
+	case AF_HASHED_IMG:
+		do_hash = is_images_subnode;
+		break;
+	case AF_SIGNED_IMG:
+		do_sign = is_images_subnode;
+		break;
+	case AF_SIGNED_CONF:
+		if (is_images_subnode) {
+			do_hash = true;
+			hash_algo = "sha1";
+		} else {
+			do_sign = true;
 		}
+		break;
+	default:
+		fprintf(stderr,
+			"%s: Unsupported auto FIT mode %u\n",
+			params->cmdname, params->auto_fit);
+		break;
+	}
+
+	if (do_hash) {
+		fdt_begin_node(fdt, FIT_HASH_NODENAME);
+		fdt_property_string(fdt, FIT_ALGO_PROP, hash_algo);
+		fdt_end_node(fdt);
+	}
 
-		fdt_begin_node(fdt, "signature-1");
+	if (do_sign) {
+		fdt_begin_node(fdt, FIT_SIG_NODENAME);
 		fdt_property_string(fdt, FIT_ALGO_PROP, params->algo_name);
 		fdt_property_string(fdt, FIT_KEY_HINT, params->keyname);
-	} else {
-		fdt_begin_node(fdt, "hash-1");
-		fdt_property_string(fdt, FIT_ALGO_PROP, "crc32");
+		fdt_end_node(fdt);
 	}
-
-	fdt_end_node(fdt);
-	return 0;
 }
 
 /**
@@ -269,9 +292,7 @@ static int fit_write_images(struct image_tool_params *params, char *fdt)
 	ret = fdt_property_file(params, fdt, FIT_DATA_PROP, params->datafile);
 	if (ret)
 		return ret;
-	ret = add_hash_node(params, fdt);
-	if (ret)
-		return ret;
+	fit_add_hash_or_sign(params, fdt, true);
 	fdt_end_node(fdt);
 
 	/* Now the device tree files if available */
@@ -294,7 +315,7 @@ static int fit_write_images(struct image_tool_params *params, char *fdt)
 				    genimg_get_arch_short_name(params->arch));
 		fdt_property_string(fdt, FIT_COMP_PROP,
 				    genimg_get_comp_short_name(IH_COMP_NONE));
-		ret = add_hash_node(params, fdt);
+		fit_add_hash_or_sign(params, fdt, true);
 		if (ret)
 			return ret;
 		fdt_end_node(fdt);
@@ -314,7 +335,7 @@ static int fit_write_images(struct image_tool_params *params, char *fdt)
 					params->fit_ramdisk);
 		if (ret)
 			return ret;
-		ret = add_hash_node(params, fdt);
+		fit_add_hash_or_sign(params, fdt, true);
 		if (ret)
 			return ret;
 		fdt_end_node(fdt);
@@ -366,6 +387,7 @@ static void fit_write_configs(struct image_tool_params *params, char *fdt)
 
 		snprintf(str, sizeof(str), FIT_FDT_PROP "-%d", upto);
 		fdt_property_string(fdt, FIT_FDT_PROP, str);
+		fit_add_hash_or_sign(params, fdt, false);
 		fdt_end_node(fdt);
 	}
 
@@ -378,6 +400,7 @@ static void fit_write_configs(struct image_tool_params *params, char *fdt)
 		if (params->fit_ramdisk)
 			fdt_property_string(fdt, FIT_RAMDISK_PROP,
 					    FIT_RAMDISK_PROP "-1");
+		fit_add_hash_or_sign(params, fdt, false);
 
 		fdt_end_node(fdt);
 	}
@@ -721,7 +744,7 @@ static int fit_handle_file(struct image_tool_params *params)
 	sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
 
 	/* We either compile the source file, or use the existing FIT image */
-	if (params->auto_its) {
+	if (params->auto_fit) {
 		if (fit_build(params, tmpfile)) {
 			fprintf(stderr, "%s: failed to build FIT\n",
 				params->cmdname);
@@ -905,7 +928,7 @@ static int fit_extract_contents(void *ptr, struct image_tool_params *params)
 
 static int fit_check_params(struct image_tool_params *params)
 {
-	if (params->auto_its)
+	if (params->auto_fit)
 		return 0;
 	return	((params->dflag && params->fflag) ||
 		 (params->fflag && params->lflag) ||
diff --git a/tools/imagetool.h b/tools/imagetool.h
index ca7c2e48ba..fdceea46c0 100644
--- a/tools/imagetool.h
+++ b/tools/imagetool.h
@@ -39,6 +39,14 @@ struct content_info {
 	const char *fname;
 };
 
+/* FIT auto generation modes */
+enum af_mode {
+	AF_OFF = 0,	/* Needs .its or existing FIT to be provided */
+	AF_HASHED_IMG,	/* Auto FIT with crc32 hashed images subnodes */
+	AF_SIGNED_IMG,	/* Auto FIT with signed images subnodes */
+	AF_SIGNED_CONF,	/* Auto FIT with sha1 images and signed configs */
+};
+
 /*
  * This structure defines all such variables those are initialized by
  * mkimage and dumpimage main core and need to be referred by image
@@ -79,7 +87,7 @@ struct image_tool_params {
 	int require_keys;	/* 1 to mark signing keys as 'required' */
 	int file_size;		/* Total size of output file */
 	int orig_file_size;	/* Original size for file before padding */
-	bool auto_its;		/* Automatically create the .its file */
+	enum af_mode auto_fit;	/* Automatically create the FIT */
 	int fit_image_type;	/* Image type to put into the FIT */
 	char *fit_ramdisk;	/* Ramdisk file to include */
 	struct content_info *content_head;	/* List of files to include */
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 30c6df7708..75b72420b9 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -104,7 +104,7 @@ static void usage(const char *msg)
 		"          -v ==> verbose\n",
 		params.cmdname);
 	fprintf(stderr,
-		"       %s [-D dtc_options] [-f fit-image.its|-f auto|-F] [-b <dtb> [-b <dtb>]] [-E] [-B size] [-i <ramdisk.cpio.gz>] fit-image\n"
+		"       %s [-D dtc_options] [-f fit-image.its|-f auto|-f auto-conf|-F] [-b <dtb> [-b <dtb>]] [-E] [-B size] [-i <ramdisk.cpio.gz>] fit-image\n"
 		"           <dtb> file is used with -f auto, it may occur multiple times.\n",
 		params.cmdname);
 	fprintf(stderr,
@@ -271,7 +271,10 @@ static void process_args(int argc, char **argv)
 			break;
 		case 'f':
 			datafile = optarg;
-			params.auto_its = !strcmp(datafile, "auto");
+			if (!strcmp(datafile, "auto"))
+				params.auto_fit = AF_HASHED_IMG;
+			else if (!strcmp(datafile, "auto-conf"))
+				params.auto_fit = AF_SIGNED_CONF;
 			/* fallthrough */
 		case 'F':
 			/*
@@ -283,6 +286,7 @@ static void process_args(int argc, char **argv)
 			break;
 		case 'g':
 			params.keyname = optarg;
+			break;
 		case 'G':
 			params.keyfile = optarg;
 			break;
@@ -370,6 +374,17 @@ static void process_args(int argc, char **argv)
 	if (optind < argc)
 		params.imagefile = argv[optind];
 
+	if (params.auto_fit == AF_SIGNED_CONF) {
+		if (!params.keyname || !params.algo_name)
+			usage("Auto FIT with signed configs requires -f auto-conf "
+				"-g <key name hint> -o <algorithm>");
+	} else if (params.auto_fit == AF_HASHED_IMG && params.keyname) {
+		params.auto_fit = AF_SIGNED_IMG;
+		if (!params.algo_name)
+			usage("Auto FIT with signed images requires -f auto "
+				"-g <key name hint> -o <algorithm>");
+	}
+
 	/*
 	 * For auto-generated FIT images we need to know the image type to put
 	 * in the FIT, which is separate from the file's image type (which
@@ -377,8 +392,8 @@ static void process_args(int argc, char **argv)
 	 */
 	if (params.type == IH_TYPE_FLATDT) {
 		params.fit_image_type = type ? type : IH_TYPE_KERNEL;
-		/* For auto_its, datafile is always 'auto' */
-		if (!params.auto_its)
+		/* For auto-FIT, datafile has to be provided with -d */
+		if (!params.auto_fit)
 			params.datafile = datafile;
 		else if (!params.datafile)
 			usage("Missing data file for auto-FIT (use -d)");
-- 
2.34.1


  reply	other threads:[~2022-12-11 14:54 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-11-19 18:00 Patch proposal - mkimage: fit: Support signed conf 'auto' FITs Pegorer Massimo
2022-11-23  2:09 ` Simon Glass
2022-11-24  7:32   ` R: " Pegorer Massimo
2022-11-28 15:45   ` Sean Anderson
2022-12-04 21:16     ` Simon Glass
2022-12-09 15:47       ` R: " Pegorer Massimo
2022-12-09 16:09     ` Pegorer Massimo
2022-12-11 14:54       ` Pegorer Massimo [this message]
2022-12-15 21:16         ` [PATCH] mkimage: fit: Support signed configurations in " Simon Glass
2023-01-05  9:31 Massimo Pegorer
2023-01-13 18:00 ` Simon Glass
2023-01-27 19:07 ` Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=GV1PR08MB801066863097F9433F1BD87CE51E9@GV1PR08MB8010.eurprd08.prod.outlook.com \
    --to=massimo.pegorer@vimar.com \
    --cc=sean.anderson@seco.com \
    --cc=sjg@chromium.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.