Skip to contentSkip to conversation

RFC: Verified boot implementation based on FIT

RFC PATCH New Simon Glass 2 participants 74 messages Jan 5, 2013 – Mar 18, 2013

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover RFC: Verified boot implementation based on FIT

This series implemented a verified boot system based around FIT images as discussed on the U-Boot mailing list, including on this thread:

http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/147830

RSA is used to implement the encryption. Images are signed by mkimage using private keys created by the user. Public keys are written into U-Boot control FDT (CONFIG_OF_CONTROL) for access by bootm etc. at run-time. The control FDT must be stored in a secure place where it cannot be changed after manufacture. Some notes are provided in the documentaion on how this can be achieved.

When images are loaded, they are verified with the public keys.

Some minor restructuring of the image code is included in this series, since we now support signatures as well as hashes.

It is important to have a test framework for this series. For this, sandbox is used, and a script is provided which signs images and gets sandbox to load them using a script, to check that all is well. So some of the patches here release to adding image support for sandbox.

This series is not quite in final form since it still needs rollback support, using a TPM or some other mechanism to make sure that an attacker cannot boot your system with an old image that has been compromised.

Also a few more tests are needed to check that image corruption has the desired effect, some proofreading is required, another review of error checking, etc.

This series relies on two previous series: sandbox filesystem and sandbox memory. Without these, it is (at best) not possible to run the verified boot test on sandbox.

This series and its dependencies are available at:

http://git.denx.de/u-boot-x86.git

in the branch 'vboot'.

Comments welcome.

Simon Glass (44):
sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT
bootstage: Don't build for HOSTCC
mkimage: Move ARRAY_SIZE to header file
libfdt: Add fdt_next_subnode() to permit easy subnode iteration
image: Move timestamp #ifdefs to header file
image: Export fit_check_ramdisk()
image: Split FIT code into new image-fit.c
image: Move HOSTCC image code to tools/
image: Split hash node processing into its own function
image: Convert fit_image_hash_set_value() to static, and rename
image: Rename fit_image_check_hashes() to fit_image_verify()
image: Move hash checking into its own functions
image: Move error! string to common place
image: Export fit_conf_get_prop_node()
image: Rename fit_add_hashes() to fit_add_verification_data()
image: Rename hash printing to fit_image_print_verification_data()
sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file
fdt: Add a parameter to fdt_valid()
Add getenv_hex() to return an environment variable as hex
fdt: Allow fdt command to check and update control FDT
sandbox: fdt: Support fdt command for sandbox
env: Fix minor comment typos in cmd_nvedit
fdt: Skip checking FDT if the pointer is NULL
Revert "fdt- Tell the FDT library where the device tree is" Add stdarg to vsprintf.h
Add minor updates to README.fdt-control
hash: Add a way to calculate a hash for any algortihm
sandbox: config: Enable FIT signatures with RSA
sandbox: Provide a way to map from host RAM to U-Boot RAM
sandbox: image: Add support for booting images in sandbox
image: Add signing infrastructure
image: Support signing of images
image: Verify signatures in FIT images
image: Add RSA support for image signing
mkimage: Put FIT loading in function and tidy error handling
mkimage: Add -k option to specify key directory
mkimage: Add -K to write public keys to an FDT blob
mkimage: Add -F option to modify an existing .fit file
mkimage: Add -c option to specify a comment for key signing
mkimage: Add -r option to specify keys that must be verified
libfdt: Add fdt_find_regions()
image: Add support for signing of FIT configurations Add verified boot information and test
WIP: sandbox: config: Add test config for verified boot

 Makefile                         |    1 +
 README                           |   15 +
 arch/sandbox/cpu/cpu.c           |    5 +
 arch/sandbox/cpu/start.c         |    7 +
 arch/sandbox/include/asm/io.h    |    2 +
 arch/sandbox/include/asm/state.h |    1 +
 arch/sandbox/lib/board.c         |   42 +-
 common/Makefile                  |    2 +
 common/cmd_bootm.c               |   37 +-
 common/cmd_fdt.c                 |   83 ++-
 common/cmd_fpga.c                |    2 +-
 common/cmd_nvedit.c              |   19 +-
 common/cmd_source.c              |    2 +-
 common/cmd_ximg.c                |    2 +-
 common/hash.c                    |   22 +
 common/image-fit.c               | 1544 +++++++++++++++++++++++++++++++++++
 common/image-sig.c               |  407 +++++++++
 common/image.c                   | 1677 +-------------------------------------
 common/main.c                    |    8 -
 common/update.c                  |    2 +-
 config.mk                        |    1 +
 doc/README.fdt-control           |   13 +-
 doc/mkimage.1                    |   73 ++-
 doc/uImage.FIT/sign-configs.its  |   45 +
 doc/uImage.FIT/sign-images.its   |   42 +
 doc/uImage.FIT/signature.txt     |  376 +++++++++
 doc/uImage.FIT/verified-boot.txt |  104 +++
 include/bootstage.h              |    5 +-
 include/common.h                 |   18 +
 include/configs/sandbox.h        |   20 +-
 include/hash.h                   |   15 +
 include/image.h                  |  213 +++++-
 include/libfdt.h                 |   81 ++
 include/rsa.h                    |  108 +++
 include/vsprintf.h               |    2 +
 lib/fdtdec.c                     |    3 +-
 lib/libfdt/fdt.c                 |   12 +
 lib/libfdt/fdt_wip.c             |  129 +++
 lib/rsa/Makefile                 |   46 +
 lib/rsa/rsa-sign.c               |  454 +++++++++++
 lib/rsa/rsa-verify.c             |  374 +++++++++
 test/vboot/.gitignore            |    3 +
 test/vboot/sandbox-kernel.dts    |    7 +
 test/vboot/sandbox-u-boot.dts    |    7 +
 test/vboot/sign-configs.its      |   45 +
 test/vboot/sign-images.its       |   42 +
 test/vboot/vboot_test.sh         |  122 +++
 tools/Makefile                   |   21 +-
 tools/aisimage.c                 |    1 -
 tools/fit_image.c                |  134 ++-
 tools/image-host.c               |  727 +++++++++++++++++
 tools/mkimage.c                  |   27 +-
 tools/mkimage.h                  |    6 +
 53 files changed, 5386 insertions(+), 1770 deletions(-)
 create mode 100644 common/image-fit.c
 create mode 100644 common/image-sig.c
 create mode 100644 doc/uImage.FIT/sign-configs.its
 create mode 100644 doc/uImage.FIT/sign-images.its
 create mode 100644 doc/uImage.FIT/signature.txt
 create mode 100644 doc/uImage.FIT/verified-boot.txt
 create mode 100644 include/rsa.h
 create mode 100644 lib/rsa/Makefile
 create mode 100644 lib/rsa/rsa-sign.c
 create mode 100644 lib/rsa/rsa-verify.c
 create mode 100644 test/vboot/.gitignore
 create mode 100644 test/vboot/sandbox-kernel.dts
 create mode 100644 test/vboot/sandbox-u-boot.dts
 create mode 100644 test/vboot/sign-configs.its
 create mode 100644 test/vboot/sign-images.its
 create mode 100755 test/vboot/vboot_test.sh
 create mode 100644 tools/image-host.c
Signature · 1 line
1.7.7.3
#1 lore raw

RFC PATCH 1/44 sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT

Enable these options to use FITs on sandbox.

---
 include/configs/sandbox.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/configs/sandbox.h +2 -0
index 406da43..67d788a 100644
@@ -31,6 +31,8 @@
 #define CONFIG_OF_CONTROL
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
+#define CONFIG_FIT
+#define CONFIG_CMD_FDT
 
 #define CONFIG_FS_FAT
 #define CONFIG_FS_EXT4
Signature · 1 line
1.7.7.3
#2 lore raw

RFC PATCH 2/44 bootstage: Don't build for HOSTCC

In reply to Simon Glass

We don't measure boot timing on the host, or with SPL, so use both conditions in the bootstage header. This allows us to avoid using conditional compilation around bootstage_...() calls. (#ifdef)

---
 include/bootstage.h |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
include/bootstage.h +3 -2
index 3b2216b..08bf2b0 100644
@@ -221,7 +221,7 @@ enum bootstage_id {
  */
 ulong timer_get_boot_us(void);
 
-#ifndef CONFIG_SPL_BUILD
+#if !defined(CONFIG_SPL_BUILD) && !defined(USE_HOSTCC)
 /*
  * Board code can implement show_boot_progress() if needed.
  *
@@ -233,7 +233,8 @@ void show_boot_progress(int val);
 #define show_boot_progress(val) do {} while (0)
 #endif
 
-#if defined(CONFIG_BOOTSTAGE) && !defined(CONFIG_SPL_BUILD)
+#if defined(CONFIG_BOOTSTAGE) && !defined(CONFIG_SPL_BUILD) \
+	&& !defined(USE_HOSTCC)
 /* This is the full bootstage implementation */
 
 /**
Signature · 1 line
1.7.7.3
#3 lore raw

RFC PATCH 3/44 mkimage: Move ARRAY_SIZE to header file

In reply to Simon Glass

Move this definition from aisimage.c to mkimage.h so that it is available more widely.

---
 tools/aisimage.c |    1 -
 tools/mkimage.h  |    2 ++
 2 files changed, 2 insertions(+), 1 deletions(-)
tools/aisimage.c +0 -1
index c645708..659df8c 100644
@@ -32,7 +32,6 @@
 #define WORD_ALIGN0	4
 #define WORD_ALIGN(len) (((len)+WORD_ALIGN0-1) & ~(WORD_ALIGN0-1))
 #define MAX_CMD_BUFFER	4096
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
 static uint32_t ais_img_size;
 
tools/mkimage.h +2 -0
index ea45f5c..e07a615 100644
@@ -42,6 +42,8 @@
 #define debug(fmt,args...)
 #endif /* MKIMAGE_DEBUG */
 
+#define ARRAY_SIZE(x)		(sizeof(x) / sizeof((x)[0]))
+
 #define MKIMAGE_TMPFILE_SUFFIX		".tmp"
 #define MKIMAGE_MAX_TMPFILE_LEN		256
 #define MKIMAGE_DEFAULT_DTC_OPTIONS	"-I dts -O dtb -p 500"
Signature · 1 line
1.7.7.3
#5 lore raw

RFC PATCH 4/44 libfdt: Add fdt_next_subnode() to permit easy subnode iteration

In reply to Simon Glass

This allows use to replace code like this:

for (ndepth = 0, count = 0,

	noffset = fdt_next_node(fit, images_noffset, &ndepth);
     (noffset >= 0) && (ndepth > 0);
     noffset = fdt_next_node(fit, noffset, &ndepth)) {
	if (ndepth == 1)
			...

with:

for (ndepth = 0,

		noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
		noffset >= 0;
		noffset = fdt_next_subnode(fit, noffset, &ndepth)) {

which is slightly better, and doesn't require two levels of indentation for code in the loop.

---
 include/libfdt.h |   17 +++++++++++++++++
 lib/libfdt/fdt.c |   12 ++++++++++++
 2 files changed, 29 insertions(+), 0 deletions(-)
include/libfdt.h +17 -0
index c93ae28..0dfb8a0 100644
@@ -136,6 +136,23 @@ uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
 
 int fdt_next_node(const void *fdt, int offset, int *depth);
 
+/**
+ * fdt_next_subnode() - get offset of next direct child
+ *
+ * Set depth to 0, offset to parent, then call this function repeatedly
+ * to get direct subnodes of a parent node.
+ *
+ * @fdt:	FDT blob
+ * @offset:	Set this to offset of parent for the first call. For
+ *		subsquent calls, pass in the value returns from the last
+ *		call.
+ * @depth:	Used internally to monitor depth - set this to 0 for the
+ *		first call.
+ * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more
+ * children
+ */
+int fdt_next_subnode(const void *fdt, int offset, int *depth);
+
 /**********************************************************************/
 /* General functions                                                  */
 /**********************************************************************/
lib/libfdt/fdt.c +12 -0
index 4157b21..8a0f323 100644
@@ -202,6 +202,18 @@ int fdt_next_node(const void *fdt, int offset, int *depth)
 	return offset;
 }
 
+int fdt_next_subnode(const void *fdt, int offset, int *depth)
+{
+	/* Loop until we find a direct child of the parent (depth == 1) */
+	do {
+		offset = fdt_next_node(fdt, offset, depth);
+		if (offset < 0 || *depth < 1)
+			return -FDT_ERR_NOTFOUND;
+	} while (*depth > 1);
+
+	return offset;
+}
+
 const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
 {
 	int len = strlen(s) + 1;
Signature · 1 line
1.7.7.3
#6 lore raw

RFC PATCH 5/44 image: Move timestamp #ifdefs to header file

In reply to Simon Glass

Rather than repeat the line
#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || \
defined(USE_HOSTCC)

everywhere, put this in a header file and #define IMAGE_ENABLE_TIMESTAMP to either 1 or 0. Then we can use a plain if() in most code and avoid the #ifdefs.

The compiler's dead code elimination ensures that the result is the same.

---
 common/image.c  |   50 +++++++++++++++++++++-----------------------------
 include/image.h |    8 ++++++++
 2 files changed, 29 insertions(+), 29 deletions(-)
common/image.c +21 -29
index 936b08c..b75a9d0 100644
@@ -39,9 +39,7 @@
 #include <logbuff.h>
 #endif
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE)
 #include <rtc.h>
-#endif
 
 #include <environment.h>
 #include <image.h>
@@ -163,10 +161,6 @@ static const table_entry_t uimage_comp[] = {
 	{	-1,		"",		"",			},
 };
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
-static void genimg_print_time(time_t timestamp);
-#endif
-
 /*****************************************************************************/
 /* Legacy format routines */
 /*****************************************************************************/
@@ -312,10 +306,10 @@ void image_print_contents(const void *ptr)
 #endif
 
 	printf("%sImage Name:   %.*s\n", p, IH_NMLEN, image_get_name(hdr));
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
-	printf("%sCreated:      ", p);
-	genimg_print_time((time_t)image_get_time(hdr));
-#endif
+	if (IMAGE_ENABLE_TIMESTAMP) {
+		printf("%sCreated:      ", p);
+		genimg_print_time((time_t)image_get_time(hdr));
+	}
 	printf("%sImage Type:   ", p);
 	image_print_type(hdr);
 	printf("%sData Size:    ", p);
@@ -524,8 +518,8 @@ void genimg_print_size(uint32_t size)
 #endif
 }
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
-static void genimg_print_time(time_t timestamp)
+#if IMAGE_ENABLE_TIMESTAMP
+void genimg_print_time(time_t timestamp)
 {
 #ifndef USE_HOSTCC
 	struct rtc_time tm;
@@ -538,7 +532,7 @@ static void genimg_print_time(time_t timestamp)
 	printf("%s", ctime(&timestamp));
 #endif
 }
-#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || USE_HOSTCC */
+#endif
 
 /**
  * get_table_entry_name - translate entry id to long name
@@ -1911,9 +1905,7 @@ void fit_print_contents(const void *fit)
 	int count = 0;
 	int ret;
 	const char *p;
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
 	time_t timestamp;
-#endif
 
 #ifdef USE_HOSTCC
 	p = "";
@@ -1929,14 +1921,14 @@ void fit_print_contents(const void *fit)
 	else
 		printf("%s\n", desc);
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
-	ret = fit_get_timestamp(fit, 0, &timestamp);
-	printf("%sCreated:         ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		genimg_print_time(timestamp);
-#endif
+	if (IMAGE_ENABLE_TIMESTAMP) {
+		ret = fit_get_timestamp(fit, 0, &timestamp);
+		printf("%sCreated:         ", p);
+		if (ret)
+			printf("unavailable\n");
+		else
+			genimg_print_time(timestamp);
+	}
 
 	/* Find images parent node offset */
 	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
@@ -3047,13 +3039,13 @@ int fit_check_format(const void *fit)
 		return 0;
 	}
 
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || defined(USE_HOSTCC)
-	/* mandatory / node 'timestamp' property */
-	if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
-		debug("Wrong FIT format: no timestamp\n");
-		return 0;
+	if (IMAGE_ENABLE_TIMESTAMP) {
+		/* mandatory / node 'timestamp' property */
+		if (fdt_getprop(fit, 0, FIT_TIMESTAMP_PROP, NULL) == NULL) {
+			debug("Wrong FIT format: no timestamp\n");
+			return 0;
+		}
 	}
-#endif
 
 	/* mandatory subimages parent '/images' node */
 	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
include/image.h +8 -0
index b958b18..e8ddb8f 100644
@@ -330,6 +330,14 @@ int genimg_get_type_id(const char *name);
 int genimg_get_comp_id(const char *name);
 void genimg_print_size(uint32_t size);
 
+#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || \
+	defined(USE_HOSTCC)
+#define IMAGE_ENABLE_TIMESTAMP 1
+#else
+#define IMAGE_ENABLE_TIMESTAMP 0
+#endif
+void genimg_print_time(time_t timestamp);
+
 #ifndef USE_HOSTCC
 /* Image format types, returned by _get_format() routine */
 #define IMAGE_FORMAT_INVALID	0x00
Signature · 1 line
1.7.7.3
#7 lore raw

RFC PATCH 5/44 image: Move timestamp #ifdefs to header file

Dear Simon Glass,

Quoted 11 lines

Rather than repeat the line
#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || \
defined(USE_HOSTCC)

everywhere, put this in a header file and #define IMAGE_ENABLE_TIMESTAMP to either 1 or 0. Then we can use a plain if() in most code and avoid the #ifdefs.

The compiler's dead code elimination ensures that the result is the same.

Best regards,
Marek Vasut

#8 lore raw

RFC PATCH 6/44 image: Export fit_check_ramdisk()

In reply to Simon Glass

One we split out the FIT code from image.c we will need this function. Export it in the header.

---
 common/image.c  |    9 ++-------
 include/image.h |    3 +++
 2 files changed, 5 insertions(+), 7 deletions(-)
common/image.c +2 -7
index b75a9d0..c030e1a 100644
@@ -50,14 +50,9 @@
 #include <fdt_support.h>
 #endif
 
-#if defined(CONFIG_FIT)
 #include <u-boot/md5.h>
 #include <sha1.h>
 
-static int fit_check_ramdisk(const void *fit, int os_noffset,
-		uint8_t arch, int verify);
-#endif
-
 #ifdef CONFIG_CMD_BDI
 extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 #endif
@@ -3364,8 +3359,8 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
  *     0, on failure
  */
 #ifndef USE_HOSTCC
-static int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
-				int verify)
+int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
+			int verify)
 {
 	fit_image_print(fit, rd_noffset, "   ");
 
include/image.h +3 -0
index e8ddb8f..7543512 100644
@@ -630,6 +630,9 @@ int fit_conf_get_fdt_node(const void *fit, int noffset);
 
 void fit_conf_print(const void *fit, int noffset, const char *p);
 
+int fit_check_ramdisk(const void *fit, int os_noffset,
+		uint8_t arch, int verify);
+
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
Signature · 1 line
1.7.7.3
#10 lore raw

RFC PATCH 7/44 image: Split FIT code into new image-fit.c

In reply to Simon Glass

The FIT code is about half the size of the >3000-line image.c. Split this code into its own file.

---
 common/Makefile    |    1 +
 common/image-fit.c | 1645 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/image.c     | 1602 --------------------------------------------------
 tools/Makefile     |    2 +
 4 files changed, 1648 insertions(+), 1602 deletions(-)
 create mode 100644 common/image-fit.c
common/Makefile +1 -0
index 719fc23..f945911 100644
@@ -223,6 +223,7 @@ COBJS-$(CONFIG_BOUNCE_BUFFER) += bouncebuf.o
 COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += image.o
+COBJS-$(CONFIG_FIT) += image-fit.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
 
common/image-fit.c new file +1645 -0

1,645 lines not on this page · raw message

common/image.c +0 -1602

1,348 lines not on this page · raw message

tools/Makefile +2 -0
index 686840a..292758e 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
1.7.7.3

Part of the diff is not shown here. View the raw message.

#12 lore raw

RFC PATCH 8/44 image: Move HOSTCC image code to tools/

In reply to Simon Glass

This code is never compiled into U-Boot, so move it into a separate file in tools/ to avoid the large #ifdef.

---
 common/image-fit.c |  175 +--------------------------------------------
 include/image.h    |    3 +
 tools/Makefile     |    2 +
 tools/image-host.c |  205 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 211 insertions(+), 174 deletions(-)
 create mode 100644 tools/image-host.c
common/image-fit.c +1 -174
index 6f2ecd2..d75ec3a 100644
@@ -830,7 +830,7 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
  *     0, on success
  *    -1, when algo is unsupported
  */
-static int calculate_hash(const void *data, int data_len, const char *algo,
+int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len)
 {
 	if (strcmp(algo, "crc32") == 0) {
@@ -852,179 +852,6 @@ static int calculate_hash(const void *data, int data_len, const char *algo,
 	return 0;
 }
 
-#ifdef USE_HOSTCC
-/**
- * fit_set_hashes - process FIT component image nodes and calculate hashes
- * @fit: pointer to the FIT format image header
- *
- * fit_set_hashes() adds hash values for all component images in the FIT blob.
- * Hashes are calculated for all component images which have hash subnodes
- * with algorithm property set to one of the supported hash algorithms.
- *
- * returns
- *     0, on success
- *     libfdt error code, on failure
- */
-int fit_set_hashes(void *fit)
-{
-	int images_noffset;
-	int noffset;
-	int ndepth;
-	int ret;
-
-	/* Find images parent node offset */
-	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
-	if (images_noffset < 0) {
-		printf("Can't find images parent node '%s' (%s)\n",
-			FIT_IMAGES_PATH, fdt_strerror(images_noffset));
-		return images_noffset;
-	}
-
-	/* Process its subnodes, print out component images details */
-	for (ndepth = 0, noffset = fdt_next_node(fit, images_noffset, &ndepth);
-	     (noffset >= 0) && (ndepth > 0);
-	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		if (ndepth == 1) {
-			/*
-			 * Direct child node of the images parent node,
-			 * i.e. component image node.
-			 */
-			ret = fit_image_set_hashes(fit, noffset);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * fit_image_set_hashes - calculate/set hashes for given component image node
- * @fit: pointer to the FIT format image header
- * @image_noffset: requested component image node
- *
- * fit_image_set_hashes() adds hash values for an component image node. All
- * existing hash subnodes are checked, if algorithm property is set to one of
- * the supported hash algorithms, hash value is computed and corresponding
- * hash node property is set, for example:
- *
- * Input component image node structure:
- *
- * o image at 1 (at image_noffset)
- *   | - data = [binary data]
- *   o hash at 1
- *     |- algo = "sha1"
- *
- * Output component image node structure:
- *
- * o image at 1 (at image_noffset)
- *   | - data = [binary data]
- *   o hash at 1
- *     |- algo = "sha1"
- *     |- value = sha1(data)
- *
- * returns:
- *     0 on sucess
- *    <0 on failure
- */
-int fit_image_set_hashes(void *fit, int image_noffset)
-{
-	const void *data;
-	size_t size;
-	char *algo;
-	uint8_t value[FIT_MAX_HASH_LEN];
-	int value_len;
-	int noffset;
-	int ndepth;
-
-	/* Get image data and data length */
-	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
-		printf("Can't get image data/size\n");
-		return -1;
-	}
-
-	/* Process all hash subnodes of the component image node */
-	for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
-	     (noffset >= 0) && (ndepth > 0);
-	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		if (ndepth == 1) {
-			/* Direct child node of the component image node */
-
-			/*
-			 * Check subnode name, must be equal to "hash".
-			 * Multiple hash nodes require unique unit node
-			 * names, e.g. hash at 1, hash at 2, etc.
-			 */
-			if (strncmp(fit_get_name(fit, noffset, NULL),
-					FIT_HASH_NODENAME,
-					strlen(FIT_HASH_NODENAME)) != 0) {
-				/* Not a hash subnode, skip it */
-				continue;
-			}
-
-			if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-				printf("Can't get hash algo property for "
-					"'%s' hash node in '%s' image node\n",
-					fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset, NULL));
-				return -1;
-			}
-
-			if (calculate_hash(data, size, algo, value,
-						&value_len)) {
-				printf("Unsupported hash algorithm (%s) for "
-					"'%s' hash node in '%s' image node\n",
-					algo, fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset,
-							NULL));
-				return -1;
-			}
-
-			if (fit_image_hash_set_value(fit, noffset, value,
-							value_len)) {
-				printf("Can't set hash value for "
-					"'%s' hash node in '%s' image node\n",
-					fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset, NULL));
-				return -1;
-			}
-		}
-	}
-
-	return 0;
-}
-
-/**
- * fit_image_hash_set_value - set hash value in requested has node
- * @fit: pointer to the FIT format image header
- * @noffset: hash node offset
- * @value: hash value to be set
- * @value_len: hash value length
- *
- * fit_image_hash_set_value() attempts to set hash value in a node at offset
- * given and returns operation status to the caller.
- *
- * returns
- *     0, on success
- *     -1, on failure
- */
-int fit_image_hash_set_value(void *fit, int noffset, uint8_t *value,
-				int value_len)
-{
-	int ret;
-
-	ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
-	if (ret) {
-		printf("Can't set hash '%s' property for '%s' node(%s)\n",
-			FIT_VALUE_PROP, fit_get_name(fit, noffset, NULL),
-			fdt_strerror(ret));
-		return -1;
-	}
-
-	return 0;
-}
-#endif /* USE_HOSTCC */
-
 /**
  * fit_image_check_hashes - verify data intergity
  * @fit: pointer to the FIT format image header
include/image.h +3 -0
index 7543512..819b131 100644
@@ -633,6 +633,9 @@ void fit_conf_print(const void *fit, int noffset, const char *p);
 int fit_check_ramdisk(const void *fit, int os_noffset,
 		uint8_t arch, int verify);
 
+int calculate_hash(const void *data, int data_len, const char *algo,
+			uint8_t *value, int *value_len);
+
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
tools/Makefile +2 -0
index 292758e..eb10ae9 100644
@@ -95,6 +95,7 @@ NOPED_OBJ_FILES-y += aisimage.o
 NOPED_OBJ_FILES-y += kwbimage.o
 NOPED_OBJ_FILES-y += pblimage.o
 NOPED_OBJ_FILES-y += imximage.o
+NOPED_OBJ_FILES-y += image-host.o
 NOPED_OBJ_FILES-y += omapimage.o
 NOPED_OBJ_FILES-y += mkenvimage.o
 NOPED_OBJ_FILES-y += mkimage.o
@@ -209,6 +210,7 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)fit_image.o \
 			$(obj)image-fit.o \
 			$(obj)image.o \
+			$(obj)image-host.o \
 			$(obj)imximage.o \
 			$(obj)kwbimage.o \
 			$(obj)pblimage.o \
tools/image-host.c new file +205 -0

205 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#14 lore raw

RFC PATCH 9/44 image: Split hash node processing into its own function

In reply to Simon Glass

This function has become quite long and much of the body is indented quite a bit. Move it into a separate function to make it easier to work with.

---
 tools/image-host.c |  106 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 63 insertions(+), 43 deletions(-)
tools/image-host.c +63 -43
index 8c9b645..da96ab1 100644
@@ -79,6 +79,62 @@ int fit_set_hashes(void *fit)
 }
 
 /**
+ * fit_image_process_hash - Process a single subnode of the images/ node
+ *
+ * Check each subnode and process accordingly. For hash nodes we generate
+ * a hash of the supplised data and store it in the node.
+ *
+ * @fit:	pointer to the FIT format image header
+ * @image_name:	name of image being processes (used to display errors)
+ * @noffset:	subnode offset
+ * @data:	data to process
+ * @size:	size of data in bytes
+ * @return 0 if ok, -1 on error
+ */
+static int fit_image_process_hash(void *fit, const char *image_name,
+		int noffset, const void *data, size_t size)
+{
+	uint8_t value[FIT_MAX_HASH_LEN];
+	int value_len;
+	char *algo;
+
+	/*
+	 * Check subnode name, must be equal to "hash".
+	 * Multiple hash nodes require unique unit node
+	 * names, e.g. hash at 1, hash at 2, etc.
+	 */
+	if (strncmp(fit_get_name(fit, noffset, NULL),
+				FIT_HASH_NODENAME,
+				strlen(FIT_HASH_NODENAME)) != 0)
+		return 0;
+
+	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
+		printf("Can't get hash algo property for "
+			"'%s' hash node in '%s' image node\n",
+			fit_get_name(fit, noffset, NULL), image_name);
+		return -1;
+	}
+
+	if (calculate_hash(data, size, algo, value,
+				&value_len)) {
+		printf("Unsupported hash algorithm (%s) for "
+			"'%s' hash node in '%s' image node\n",
+			algo, fit_get_name(fit, noffset, NULL), image_name);
+		return -1;
+	}
+
+	if (fit_image_hash_set_value(fit, noffset, value,
+					value_len)) {
+		printf("Can't set hash value for "
+			"'%s' hash node in '%s' image node\n",
+			fit_get_name(fit, noffset, NULL), image_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
  * fit_image_set_hashes - calculate/set hashes for given component image node
  * @fit: pointer to the FIT format image header
  * @image_noffset: requested component image node
@@ -111,11 +167,9 @@ int fit_image_set_hashes(void *fit, int image_noffset)
 {
 	const void *data;
 	size_t size;
-	char *algo;
-	uint8_t value[FIT_MAX_HASH_LEN];
-	int value_len;
 	int noffset;
 	int ndepth;
+	const char *image_name;
 
 	/* Get image data and data length */
 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
@@ -123,51 +177,17 @@ int fit_image_set_hashes(void *fit, int image_noffset)
 		return -1;
 	}
 
+	image_name = fit_get_name(fit, image_noffset, NULL);
+
 	/* Process all hash subnodes of the component image node */
 	for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
-	     (noffset >= 0) && (ndepth > 0);
-	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
+			(noffset >= 0) && (ndepth > 0);
+			noffset = fdt_next_node(fit, noffset, &ndepth)) {
 		if (ndepth == 1) {
 			/* Direct child node of the component image node */
-
-			/*
-			 * Check subnode name, must be equal to "hash".
-			 * Multiple hash nodes require unique unit node
-			 * names, e.g. hash at 1, hash at 2, etc.
-			 */
-			if (strncmp(fit_get_name(fit, noffset, NULL),
-					FIT_HASH_NODENAME,
-					strlen(FIT_HASH_NODENAME)) != 0) {
-				/* Not a hash subnode, skip it */
-				continue;
-			}
-
-			if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-				printf("Can't get hash algo property for "
-					"'%s' hash node in '%s' image node\n",
-					fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset, NULL));
-				return -1;
-			}
-
-			if (calculate_hash(data, size, algo, value,
-						&value_len)) {
-				printf("Unsupported hash algorithm (%s) for "
-					"'%s' hash node in '%s' image node\n",
-					algo, fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset,
-							NULL));
-				return -1;
-			}
-
-			if (fit_image_hash_set_value(fit, noffset, value,
-							value_len)) {
-				printf("Can't set hash value for "
-					"'%s' hash node in '%s' image node\n",
-					fit_get_name(fit, noffset, NULL),
-					fit_get_name(fit, image_noffset, NULL));
+			if (fit_image_process_hash(fit, image_name, noffset,
+					data, size))
 				return -1;
-			}
 		}
 	}
 
Signature · 1 line
1.7.7.3
#16 lore raw

RFC PATCH 10/44 image: Convert fit_image_hash_set_value() to static, and rename

In reply to Simon Glass

This function doesn't need to be exported, and with verification we want to use it for setting the 'value' property in any node, so rename it.

---
 include/image.h    |    2 -
 tools/image-host.c |   62 ++++++++++++++++++++++++++--------------------------
 2 files changed, 31 insertions(+), 33 deletions(-)
include/image.h +0 -2
index 819b131..f723b62 100644
@@ -611,8 +611,6 @@ int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore);
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
 int fit_set_hashes(void *fit);
 int fit_image_set_hashes(void *fit, int image_noffset);
-int fit_image_hash_set_value(void *fit, int noffset, uint8_t *value,
-				int value_len);
 
 int fit_image_check_hashes(const void *fit, int noffset);
 int fit_all_image_check_hashes(const void *fit);
tools/image-host.c +31 -31

77 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#18 lore raw

RFC PATCH 11/44 image: Rename fit_image_check_hashes() to fit_image_verify()

In reply to Simon Glass

This is the main entry point to the FIT image verification code. We will be using it to handle image verification with signatures, so rename the function.

---
 common/cmd_bootm.c  |    4 ++--
 common/cmd_fpga.c   |    2 +-
 common/cmd_source.c |    2 +-
 common/cmd_ximg.c   |    2 +-
 common/image-fit.c  |   16 ++++++++--------
 common/image.c      |    2 +-
 common/update.c     |    2 +-
 include/image.h     |    4 ++--
 8 files changed, 17 insertions(+), 17 deletions(-)
common/cmd_bootm.c +2 -2
index 2debfe3..7b07393 100644
@@ -797,7 +797,7 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify)
 
 	if (verify) {
 		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_check_hashes(fit, os_noffset)) {
+		if (!fit_image_verify(fit, os_noffset)) {
 			puts("Bad Data Hash\n");
 			bootstage_error(BOOTSTAGE_ID_FIT_CHECK_HASH);
 			return 0;
@@ -1151,7 +1151,7 @@ static int image_info(ulong addr)
 
 		fit_print_contents(hdr);
 
-		if (!fit_all_image_check_hashes(hdr)) {
+		if (!fit_all_image_verify(hdr)) {
 			puts("Bad hash in FIT image!\n");
 			return 1;
 		}
common/cmd_fpga.c +1 -1
index 1834246..1341604 100644
@@ -306,7 +306,7 @@ int do_fpga (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 				}
 
 				/* verify integrity */
-				if (!fit_image_check_hashes (fit_hdr, noffset)) {
+				if (!fit_image_verify(fit_hdr, noffset)) {
 					puts ("Bad Data Hash\n");
 					return 1;
 				}
common/cmd_source.c +1 -1
index 02a862c..6a82fb2 100644
@@ -124,7 +124,7 @@ source (ulong addr, const char *fit_uname)
 
 		/* verify integrity */
 		if (verify) {
-			if (!fit_image_check_hashes (fit_hdr, noffset)) {
+			if (!fit_image_verify(fit_hdr, noffset)) {
 				puts ("Bad Data Hash\n");
 				return 1;
 			}
common/cmd_ximg.c +1 -1
index ea0a26e..f8722a0 100644
@@ -160,7 +160,7 @@ do_imgextract(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
 
 		/* verify integrity */
 		if (verify) {
-			if (!fit_image_check_hashes(fit_hdr, noffset)) {
+			if (!fit_image_verify(fit_hdr, noffset)) {
 				puts("Bad Data Hash\n");
 				return 1;
 			}
common/image-fit.c +8 -8
index d75ec3a..7fab682 100644
@@ -853,11 +853,11 @@ int calculate_hash(const void *data, int data_len, const char *algo,
 }
 
 /**
- * fit_image_check_hashes - verify data intergity
+ * fit_image_verify - verify data intergity
  * @fit: pointer to the FIT format image header
  * @image_noffset: component image node offset
  *
- * fit_image_check_hashes() goes over component image hash nodes,
+ * fit_image_verify() goes over component image hash nodes,
  * re-calculates each data hash and compares with the value stored in hash
  * node.
  *
@@ -865,7 +865,7 @@ int calculate_hash(const void *data, int data_len, const char *algo,
  *     1, if all hashes are valid
  *     0, otherwise (or on error)
  */
-int fit_image_check_hashes(const void *fit, int image_noffset)
+int fit_image_verify(const void *fit, int image_noffset)
 {
 	const void	*data;
 	size_t		size;
@@ -959,17 +959,17 @@ error:
 }
 
 /**
- * fit_all_image_check_hashes - verify data intergity for all images
+ * fit_all_image_verify - verify data intergity for all images
  * @fit: pointer to the FIT format image header
  *
- * fit_all_image_check_hashes() goes over all images in the FIT and
+ * fit_all_image_verify() goes over all images in the FIT and
  * for every images checks if all it's hashes are valid.
  *
  * returns:
  *     1, if all hashes of all images are valid
  *     0, otherwise (or on error)
  */
-int fit_all_image_check_hashes(const void *fit)
+int fit_all_image_verify(const void *fit)
 {
 	int images_noffset;
 	int noffset;
@@ -999,7 +999,7 @@ int fit_all_image_check_hashes(const void *fit)
 			printf("   Hash(es) for Image %u (%s): ", count++,
 					fit_get_name(fit, noffset, NULL));
 
-			if (!fit_image_check_hashes(fit, noffset))
+			if (!fit_image_verify(fit, noffset))
 				return 0;
 			printf("\n");
 		}
@@ -1448,7 +1448,7 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
 
 	if (verify) {
 		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_check_hashes(fit, rd_noffset)) {
+		if (!fit_image_verify(fit, rd_noffset)) {
 			puts("Bad Data Hash\n");
 			bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
 			return 0;
common/image.c +1 -1
index 27f6f5b..554f269 100644
@@ -1210,7 +1210,7 @@ static int fit_check_fdt(const void *fit, int fdt_noffset, int verify)
 
 	if (verify) {
 		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_check_hashes(fit, fdt_noffset)) {
+		if (!fit_image_verify(fit, fdt_noffset)) {
 			fdt_error("Bad Data Hash");
 			return 0;
 		}
common/update.c +1 -1
index 94d6a82..87941ec 100644
@@ -297,7 +297,7 @@ got_update_file:
 		printf("Processing update '%s' :",
 			fit_get_name(fit, noffset, NULL));
 
-		if (!fit_image_check_hashes(fit, noffset)) {
+		if (!fit_image_verify(fit, noffset)) {
 			printf("Error: invalid update hash, aborting\n");
 			ret = 1;
 			goto next_node;
include/image.h +2 -2
index f723b62..ed351ef 100644
@@ -612,8 +612,8 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
 int fit_set_hashes(void *fit);
 int fit_image_set_hashes(void *fit, int image_noffset);
 
-int fit_image_check_hashes(const void *fit, int noffset);
-int fit_all_image_check_hashes(const void *fit);
+int fit_image_verify(const void *fit, int noffset);
+int fit_all_image_verify(const void *fit);
 int fit_image_check_os(const void *fit, int noffset, uint8_t os);
 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch);
 int fit_image_check_type(const void *fit, int noffset, uint8_t type);
Signature · 1 line
1.7.7.3
#19 lore raw

RFC PATCH 11/44 image: Rename fit_image_check_hashes() to fit_image_verify()

Dear Simon Glass,

Quoted 5 lines

This is the main entry point to the FIT image verification code. We will be using it to handle image verification with signatures, so rename the function.

Best regards,
Marek Vasut

#20 lore raw

RFC PATCH 12/44 image: Move hash checking into its own functions

In reply to Simon Glass

The existing function is long and most of the code is indented a long way. Before adding yet more code, split this out into its own function.

---
 common/image-fit.c |  128 ++++++++++++++++++++++++++++------------------------
 1 files changed, 69 insertions(+), 59 deletions(-)
common/image-fit.c +69 -59
index 7fab682..4a78a5c 100644
@@ -852,6 +852,60 @@ int calculate_hash(const void *data, int data_len, const char *algo,
 	return 0;
 }
 
+static int fit_image_check_hash(const void *fit, int noffset, const void *data,
+				size_t size, char **err_msgp)
+{
+	uint8_t value[FIT_MAX_HASH_LEN];
+	int value_len;
+	char *algo;
+	uint8_t *fit_value;
+	int fit_value_len;
+#ifndef USE_HOSTCC
+	int ignore;
+#endif
+
+	*err_msgp = NULL;
+
+	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
+		*err_msgp = " error!\nCan't get hash algo "
+				"property";
+		return -1;
+	}
+	printf("%s", algo);
+
+#ifndef USE_HOSTCC
+	fit_image_hash_get_ignore(fit, noffset, &ignore);
+	if (ignore) {
+		printf("-skipped ");
+		return 0;
+	}
+#endif
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+					&fit_value_len)) {
+		*err_msgp = " error!\nCan't get hash value "
+				"property";
+		return -1;
+	}
+
+	if (calculate_hash(data, size, algo, value,
+				&value_len)) {
+		*err_msgp = " error!\n"
+				"Unsupported hash algorithm";
+		return -1;
+	}
+
+	if (value_len != fit_value_len) {
+		*err_msgp = " error !\nBad hash value len";
+		return -1;
+	} else if (memcmp(value, fit_value, value_len) != 0) {
+		*err_msgp = " error!\nBad hash value";
+		return -1;
+	}
+
+	return 0;
+}
+
 /**
  * fit_image_verify - verify data intergity
  * @fit: pointer to the FIT format image header
@@ -869,14 +923,6 @@ int fit_image_verify(const void *fit, int image_noffset)
 {
 	const void	*data;
 	size_t		size;
-	char		*algo;
-	uint8_t		*fit_value;
-	int		fit_value_len;
-#ifndef USE_HOSTCC
-	int		ignore;
-#endif
-	uint8_t		value[FIT_MAX_HASH_LEN];
-	int		value_len;
 	int		noffset;
 	int		ndepth;
 	char		*err_msg = "";
@@ -888,59 +934,23 @@ int fit_image_verify(const void *fit, int image_noffset)
 	}
 
 	/* Process all hash subnodes of the component image node */
-	for (ndepth = 0, noffset = fdt_next_node(fit, image_noffset, &ndepth);
-	     (noffset >= 0) && (ndepth > 0);
-	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		if (ndepth == 1) {
-			/* Direct child node of the component image node */
+	for (ndepth = 0,
+			noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		const char *name = fit_get_name(fit, noffset, NULL);
 
-			/*
-			 * Check subnode name, must be equal to "hash".
-			 * Multiple hash nodes require unique unit node
-			 * names, e.g. hash at 1, hash at 2, etc.
-			 */
-			if (strncmp(fit_get_name(fit, noffset, NULL),
-					FIT_HASH_NODENAME,
-					strlen(FIT_HASH_NODENAME)) != 0)
-				continue;
-
-			if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-				err_msg = " error!\nCan't get hash algo "
-						"property";
-				goto error;
-			}
-			printf("%s", algo);
-
-#ifndef USE_HOSTCC
-			fit_image_hash_get_ignore(fit, noffset, &ignore);
-			if (ignore) {
-				printf("-skipped ");
-				continue;
-			}
-#endif
-
-			if (fit_image_hash_get_value(fit, noffset, &fit_value,
-							&fit_value_len)) {
-				err_msg = " error!\nCan't get hash value "
-						"property";
-				goto error;
-			}
-
-			if (calculate_hash(data, size, algo, value,
-						&value_len)) {
-				err_msg = " error!\n"
-						"Unsupported hash algorithm";
-				goto error;
-			}
-
-			if (value_len != fit_value_len) {
-				err_msg = " error !\nBad hash value len";
-				goto error;
-			} else if (memcmp(value, fit_value, value_len) != 0) {
-				err_msg = " error!\nBad hash value";
+		/*
+		 * Check subnode name, must be equal to "hash".
+		 * Multiple hash nodes require unique unit node
+		 * names, e.g. hash at 1, hash at 2, etc.
+		 */
+		if (!strncmp(name, FIT_HASH_NODENAME,
+				strlen(FIT_HASH_NODENAME))) {
+			if (fit_image_check_hash(fit, noffset, data,
+					size, &err_msg))
 				goto error;
-			}
-			printf("+ ");
+			puts("+ ");
 		}
 	}
 
Signature · 1 line
1.7.7.3
#21 lore raw

RFC PATCH 12/44 image: Move hash checking into its own functions

Dear Simon Glass,

Quoted 18 lines

The existing function is long and most of the code is indented a long way. Before adding yet more code, split this out into its own function.

---
 common/image-fit.c |  128

++++++++++++++++++++++++++++------------------------ 1 files changed, 69 insertions(+), 59 deletions(-)

common/image-fit.c +1 -0
index 7fab682..4a78a5c 100644
@@ -852,6 +852,60 @@ int calculate_hash(const void *data, int data_len,
 const char *algo, return 0;
 }
 
+static int fit_image_check_hash(const void *fit, int noffset, const void

common/image-fit.c int calculate_hash(const void *data, int data_len, · line 865

Quoted 10 lines
common/image-fit.c +9 -0
 *data, +				size_t size, char **err_msgp)
+{
+	uint8_t value[FIT_MAX_HASH_LEN];
+	int value_len;
+	char *algo;
+	uint8_t *fit_value;
+	int fit_value_len;
+#ifndef USE_HOSTCC
+	int ignore;
+#endif

You can fix this with __maybe_unused, but otherwise

Best regards,
Marek Vasut

#22 lore raw

RFC PATCH 13/44 image: Move error! string to common place

In reply to Simon Glass

The string " error\n" appears in each error string. Move it out to a common place.

---
 common/image-fit.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)
common/image-fit.c +8 -8
index 4a78a5c..19942e2 100644
@@ -867,7 +867,7 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
 	*err_msgp = NULL;
 
 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-		*err_msgp = " error!\nCan't get hash algo "
+		*err_msgp = "Can't get hash algo "
 				"property";
 		return -1;
 	}
@@ -883,23 +883,23 @@ static int fit_image_check_hash(const void *fit, int noffset, const void *data,
 
 	if (fit_image_hash_get_value(fit, noffset, &fit_value,
 					&fit_value_len)) {
-		*err_msgp = " error!\nCan't get hash value "
+		*err_msgp = "Can't get hash value "
 				"property";
 		return -1;
 	}
 
 	if (calculate_hash(data, size, algo, value,
 				&value_len)) {
-		*err_msgp = " error!\n"
+		*err_msgp = ""
 				"Unsupported hash algorithm";
 		return -1;
 	}
 
 	if (value_len != fit_value_len) {
-		*err_msgp = " error !\nBad hash value len";
+		*err_msgp = "Bad hash value len";
 		return -1;
 	} else if (memcmp(value, fit_value, value_len) != 0) {
-		*err_msgp = " error!\nBad hash value";
+		*err_msgp = "Bad hash value";
 		return -1;
 	}
 
@@ -929,7 +929,7 @@ int fit_image_verify(const void *fit, int image_noffset)
 
 	/* Get image data and data length */
 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
-		printf("Can't get image data/size\n");
+		err_msg = "Can't get image data/size";
 		return 0;
 	}
 
@@ -955,14 +955,14 @@ int fit_image_verify(const void *fit, int image_noffset)
 	}
 
 	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-		err_msg = " error!\nCorrupted or truncated tree";
+		err_msg = "Corrupted or truncated tree";
 		goto error;
 	}
 
 	return 1;
 
 error:
-	printf("%s for '%s' hash node in '%s' image node\n",
+	printf(" error!\n%s for '%s' hash node in '%s' image node\n",
 			err_msg, fit_get_name(fit, noffset, NULL),
 			fit_get_name(fit, image_noffset, NULL));
 	return 0;
Signature · 1 line
1.7.7.3
#23 lore raw

RFC PATCH 13/44 image: Move error! string to common place

Dear Simon Glass,

Quoted 13 lines

The string " error\n" appears in each error string. Move it out to a common place.

---
 common/image-fit.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)
common/image-fit.c +0 -0
index 4a78a5c..19942e2 100644

common/image-fit.c static int fit_image_check_hash(const void *fit, int · line 871

Quoted 6 lines
common/image-fit.c +1 -1
@@ -867,7 +867,7 @@ static int fit_image_check_hash(const void *fit, int
 noffset, const void *data, *err_msgp = NULL;
 
 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-		*err_msgp = " error!\nCan't get hash algo "
+		*err_msgp = "Can't get hash algo "
 				"property";

Maybe you can fix how the strings are broken here and all around in half now? Otherwise

Best regards,
Marek Vasut

#24 lore raw

RFC PATCH 14/44 image: Export fit_conf_get_prop_node()

In reply to Simon Glass

This function will be needed by signature checking code, so export it, and also add docs.

---
 common/image-fit.c |    8 ++++----
 include/image.h    |   15 +++++++++++++++
 2 files changed, 19 insertions(+), 4 deletions(-)
common/image-fit.c +4 -4
index 19942e2..db5382d 100644
@@ -1322,7 +1322,7 @@ int fit_conf_get_node(const void *fit, const char *conf_uname)
 	return noffset;
 }
 
-static int __fit_conf_get_prop_node(const void *fit, int noffset,
+int fit_conf_get_prop_node(const void *fit, int noffset,
 		const char *prop_name)
 {
 	char *uname;
@@ -1352,7 +1352,7 @@ static int __fit_conf_get_prop_node(const void *fit, int noffset,
  */
 int fit_conf_get_kernel_node(const void *fit, int noffset)
 {
-	return __fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
+	return fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
 }
 
 /**
@@ -1371,7 +1371,7 @@ int fit_conf_get_kernel_node(const void *fit, int noffset)
  */
 int fit_conf_get_ramdisk_node(const void *fit, int noffset)
 {
-	return __fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
+	return fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
 }
 
 /**
@@ -1390,7 +1390,7 @@ int fit_conf_get_ramdisk_node(const void *fit, int noffset)
  */
 int fit_conf_get_fdt_node(const void *fit, int noffset)
 {
-	return __fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
+	return fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
 }
 
 /**
include/image.h +15 -0
index ed351ef..d933bad 100644
@@ -626,6 +626,21 @@ int fit_conf_get_kernel_node(const void *fit, int noffset);
 int fit_conf_get_ramdisk_node(const void *fit, int noffset);
 int fit_conf_get_fdt_node(const void *fit, int noffset);
 
+/**
+ * fit_conf_get_prop_node() - Get node refered to by a configuration
+ *
+ * The conf@ nodes contain references to other nodes, using properties
+ * like 'kernel = "kernel at 1"'. Given such a property name (e.g. "kernel"),
+ * return the offset of the node referred to (e.g. offset of node
+ * "/images/kernel at 1".
+ *
+ * @fit:	FIT to check
+ * @noffset:	Offset of conf at xxx node to check
+ * @prop_name:	Property to read from the conf node
+ */
+int fit_conf_get_prop_node(const void *fit, int noffset,
+		const char *prop_name);
+
 void fit_conf_print(const void *fit, int noffset, const char *p);
 
 int fit_check_ramdisk(const void *fit, int os_noffset,
Signature · 1 line
1.7.7.3
#25 lore raw

RFC PATCH 14/44 image: Export fit_conf_get_prop_node()

Dear Simon Glass,

Quoted 4 lines

This function will be needed by signature checking code, so export it, and also add docs.

[...]

Quoted 11 lines

+/**
+ * fit_conf_get_prop_node() - Get node refered to by a configuration
+ *
+ * The conf@ nodes contain references to other nodes, using properties
+ * like 'kernel = "kernel at 1"'. Given such a property name (e.g. "kernel"),
+ * return the offset of the node referred to (e.g. offset of node
+ * "/images/kernel at 1".
+ *
+ * @fit: FIT to check
+ * @noffset: Offset of conf at xxx node to check
+ * @prop_name: Property to read from the conf node

This parameter list is swapped with the description.

include/image.h int fit_conf_get_kernel_node(const void *fit, int noffset); · line 646

Quoted 7 lines

+ */

include/image.h +3 -0
+int fit_conf_get_prop_node(const void *fit, int noffset,
+		const char *prop_name);
+
 void fit_conf_print(const void *fit, int noffset, const char *p);
 
 int fit_check_ramdisk(const void *fit, int os_noffset,

Best regards,
Marek Vasut

#26 lore raw

RFC PATCH 14/44 image: Export fit_conf_get_prop_node()

Hi Marek,

Quoted 20 lines · Marek Vasut

Dear Simon Glass,

Quoted 4 lines

This function will be needed by signature checking code, so export it, and also add docs.

[...]

Quoted 11 lines

+/**
+ * fit_conf_get_prop_node() - Get node refered to by a configuration
+ *
+ * The conf@ nodes contain references to other nodes, using properties
+ * like 'kernel = "kernel at 1"'. Given such a property name (e.g. "kernel"),
+ * return the offset of the node referred to (e.g. offset of node
+ * "/images/kernel at 1".
+ *
+ * @fit: FIT to check
+ * @noffset: Offset of conf at xxx node to check
+ * @prop_name: Property to read from the conf node

Quoted 1 line

This parameter list is swapped with the description.

Sorry, can you please explain that a bit more. I'm not sure what you are pointing to.

Quoted 11 lines

include/image.h int fit_conf_get_kernel_node(const void *fit, int noffset); · line 646

Quoted 8 lines

+ */

include/image.h +3 -0
+int fit_conf_get_prop_node(const void *fit, int noffset,
+             const char *prop_name);
+
 void fit_conf_print(const void *fit, int noffset, const char *p);
 
 int fit_check_ramdisk(const void *fit, int os_noffset,

Best regards,
Marek Vasut

Regards,
Simon

#27 lore raw

RFC PATCH 14/44 image: Export fit_conf_get_prop_node()

Dear Simon Glass,

Quoted 24 lines

Hi Marek,

Quoted 21 lines · Marek Vasut

Dear Simon Glass,

Quoted 4 lines

This function will be needed by signature checking code, so export it, and also add docs.

[...]

Quoted 11 lines

+/**
+ * fit_conf_get_prop_node() - Get node refered to by a configuration
+ *
+ * The conf@ nodes contain references to other nodes, using properties
+ * like 'kernel = "kernel at 1"'. Given such a property name (e.g. "kernel"), + * return the offset of the node referred to (e.g. offset of node + * "/images/kernel at 1".
+ *
+ * @fit: FIT to check
+ * @noffset: Offset of conf at xxx node to check
+ * @prop_name: Property to read from the conf node

Quoted 4 lines
Quoted 1 line

This parameter list is swapped with the description.

Sorry, can you please explain that a bit more. I'm not sure what you are pointing to.

Tough question, especially if asked after such time ;-) I believe I meant the form of the comment should be like this:

/*
* foo() - Do baz and bar
* @parm1: Number of sharks with lasers
* @parm2: Make the result even cooler
*
* Long boring description of the function doing baz and bar. */

I think it makes more sense to stick the function param explanation just underneath the function name, no?

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

+ */

include/image.h +3 -0
+int fit_conf_get_prop_node(const void *fit, int noffset,
+             const char *prop_name);
+
 
 void fit_conf_print(const void *fit, int noffset, const char *p);
Quoted 7 lines
Quoted 4 lines
Quoted 1 line

int fit_check_ramdisk(const void *fit, int os_noffset,

Best regards,
Marek Vasut

Regards,
Simon

Best regards,
Marek Vasut

#28 lore raw

RFC PATCH 14/44 image: Export fit_conf_get_prop_node()

Hi Marek,

Quoted 42 lines · Marek Vasut

Dear Simon Glass,

Quoted 24 lines

Hi Marek,

Quoted 21 lines · Marek Vasut

Dear Simon Glass,

Quoted 4 lines

This function will be needed by signature checking code, so export it, and also add docs.

[...]

Quoted 11 lines

+/**
+ * fit_conf_get_prop_node() - Get node refered to by a configuration
+ *
+ * The conf@ nodes contain references to other nodes, using properties
+ * like 'kernel = "kernel at 1"'. Given such a property name (e.g. "kernel"), + * return the offset of the node referred to (e.g. offset of node + * "/images/kernel at 1".
+ *
+ * @fit: FIT to check
+ * @noffset: Offset of conf at xxx node to check
+ * @prop_name: Property to read from the conf node

Quoted 4 lines
Quoted 1 line

This parameter list is swapped with the description.

Sorry, can you please explain that a bit more. I'm not sure what you are pointing to.

Tough question, especially if asked after such time ;-) I believe I meant the form of the comment should be like this:

/*
* foo() - Do baz and bar
* @parm1: Number of sharks with lasers
* @parm2: Make the result even cooler
*
* Long boring description of the function doing baz and bar. */

Quoted 2 lines

I think it makes more sense to stick the function param explanation just underneath the function name, no?

Aha I see, thank you.

Yes it has been a while - I feel people have had enough time to take a look and raise questions and it is time for v2.

Regards,
Simon

#29 lore raw

RFC PATCH 15/44 image: Rename fit_add_hashes() to fit_add_verification_data()

In reply to Simon Glass

We intend to add signatures to FITs also, so rename this function so that it is not specific to hashing. Also rename fit_image_set_hashes() and make it static since it is not used outside this file.

---
 include/image.h    |   10 +++-
 tools/fit_image.c  |    2 +-
 tools/image-host.c |  147 +++++++++++++++++++++++++---------------------------
 3 files changed, 79 insertions(+), 80 deletions(-)
include/image.h +8 -2
index d933bad..ca612f3 100644
@@ -609,8 +609,14 @@ int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore);
 #endif
 
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
-int fit_set_hashes(void *fit);
-int fit_image_set_hashes(void *fit, int image_noffset);
+
+/**
+ * fit_add_verification_data() - Calculate and add hashes to FIT
+ *
+ * @fit:	Fit image to process
+ * @return 0 if ok, <0 for error
+ */
+int fit_add_verification_data(void *fit);
 
 int fit_image_verify(const void *fit, int noffset);
 int fit_all_image_verify(const void *fit);
tools/fit_image.c +1 -1
index 76bbba1..8f51159 100644
@@ -125,7 +125,7 @@ static int fit_handle_file (struct mkimage_params *params)
 	}
 
 	/* set hashes for images in the blob */
-	if (fit_set_hashes (ptr)) {
+	if (fit_add_verification_data(ptr)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
 		unlink (tmpfile);
tools/image-host.c +70 -77

204 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#30 lore raw

RFC PATCH 16/44 image: Rename hash printing to fit_image_print_verification_data()

In reply to Simon Glass

This function will be used to print signatures as well as hashes, so rename it. Also make it static since it is not used outside this file.

---
 common/image-fit.c |  132 +++++++++++++++++++++++++++++++---------------------
 include/image.h    |    1 -
 2 files changed, 79 insertions(+), 54 deletions(-)
common/image-fit.c +79 -53
index db5382d..ed98460 100644
@@ -231,6 +231,84 @@ void fit_print_contents(const void *fit)
 }
 
 /**
+ * fit_image_print_data() - prints out the hash node details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the hash node
+ * @p: pointer to prefix string
+ *
+ * fit_image_print_data() lists properies for the processed hash node
+ *
+ * returns:
+ *     no returned results
+ */
+static void fit_image_print_data(const void *fit, int noffset, const char *p)
+{
+	char *algo;
+	uint8_t *value;
+	int value_len;
+	int i, ret;
+
+	/*
+	 * Check subnode name, must be equal to "hash".
+	 * Multiple hash nodes require unique unit node
+	 * names, e.g. hash at 1, hash at 2, etc.
+	 */
+	if (strncmp(fit_get_name(fit, noffset, NULL),
+			FIT_HASH_NODENAME,
+			strlen(FIT_HASH_NODENAME)) != 0)
+		return;
+
+	debug("%s  Hash node:    '%s'\n", p,
+			fit_get_name(fit, noffset, NULL));
+
+	printf("%s  Hash algo:    ", p);
+	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
+		printf("invalid/unsupported\n");
+		return;
+	}
+	printf("%s\n", algo);
+
+	ret = fit_image_hash_get_value(fit, noffset, &value,
+					&value_len);
+	printf("%s  Hash value:   ", p);
+	if (ret) {
+		printf("unavailable\n");
+	} else {
+		for (i = 0; i < value_len; i++)
+			printf("%02x", value[i]);
+		printf("\n");
+	}
+
+	debug("%s  Hash len:     %d\n", p, value_len);
+}
+
+/**
+ * fit_image_print_verification_data() - prints out the hash/signature details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the hash or signature node
+ * @p: pointer to prefix string
+ *
+ * This lists properies for the processed hash node
+ *
+ * returns:
+ *     no returned results
+ */
+static void fit_image_print_verification_data(const void *fit, int noffset,
+				       const char *p)
+{
+	const char *name;
+
+	/*
+	 * Check subnode name, must be equal to "hash" or "signature".
+	 * Multiple hash/signature nodes require unique unit node
+	 * names, e.g. hash at 1, hash at 2, signature at 1, signature at 2, etc.
+	 */
+	name = fit_get_name(fit, noffset, NULL);
+	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
+		fit_image_print_data(fit, noffset, p);
+}
+
+/**
  * fit_image_print - prints out the FIT component image details
  * @fit: pointer to the FIT format image header
  * @image_noffset: offset of the component image node
@@ -325,64 +403,12 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
 	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
 		if (ndepth == 1) {
 			/* Direct child node of the component image node */
-			fit_image_print_hash(fit, noffset, p);
+			fit_image_print_verification_data(fit, noffset, p);
 		}
 	}
 }
 
 /**
- * fit_image_print_hash - prints out the hash node details
- * @fit: pointer to the FIT format image header
- * @noffset: offset of the hash node
- * @p: pointer to prefix string
- *
- * fit_image_print_hash() lists properies for the processed hash node
- *
- * returns:
- *     no returned results
- */
-void fit_image_print_hash(const void *fit, int noffset, const char *p)
-{
-	char *algo;
-	uint8_t *value;
-	int value_len;
-	int i, ret;
-
-	/*
-	 * Check subnode name, must be equal to "hash".
-	 * Multiple hash nodes require unique unit node
-	 * names, e.g. hash at 1, hash@2, etc.
-	 */
-	if (strncmp(fit_get_name(fit, noffset, NULL),
-			FIT_HASH_NODENAME,
-			strlen(FIT_HASH_NODENAME)) != 0)
-		return;
-
-	debug("%s  Hash node:    '%s'\n", p,
-			fit_get_name(fit, noffset, NULL));
-
-	printf("%s  Hash algo:    ", p);
-	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
-		printf("invalid/unsupported\n");
-		return;
-	}
-	printf("%s\n", algo);
-
-	ret = fit_image_hash_get_value(fit, noffset, &value,
-					&value_len);
-	printf("%s  Hash value:   ", p);
-	if (ret) {
-		printf("unavailable\n");
-	} else {
-		for (i = 0; i < value_len; i++)
-			printf("%02x", value[i]);
-		printf("\n");
-	}
-
-	debug("%s  Hash len:     %d\n", p, value_len);
-}
-
-/**
  * fit_get_desc - get node description property
  * @fit: pointer to the FIT format image header
  * @noffset: node offset
include/image.h +0 -1
index ca612f3..d6993d4 100644
@@ -548,7 +548,6 @@ int fit_parse_subimage(const char *spec, ulong addr_curr,
 
 void fit_print_contents(const void *fit);
 void fit_image_print(const void *fit, int noffset, const char *p);
-void fit_image_print_hash(const void *fit, int noffset, const char *p);
 
 /**
  * fit_get_end - get FIT image size
Signature · 1 line
1.7.7.3
#32 lore raw

RFC PATCH 17/44 sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file

In reply to Simon Glass

With sandbox it is tricky to add an FDT to the image at build time (or later) since we build an ELF file, not a plain binary, and the address space of the whole U-Boot is not accessible in the emulated memory map of sandbox.

Sandbox can read files directly from the host, though, so add an option to read an FDT from a host file on start-up.

---
 arch/sandbox/cpu/start.c         |    7 ++++++
 arch/sandbox/include/asm/state.h |    1 +
 arch/sandbox/lib/board.c         |   42 ++++++++++++++++++++++++++++++++-----
 doc/README.fdt-control           |    6 ++++-
 include/configs/sandbox.h        |    2 +
 5 files changed, 51 insertions(+), 7 deletions(-)
arch/sandbox/cpu/start.c +7 -0
index 7603bf9..8589da2 100644
@@ -104,6 +104,13 @@ static int sb_cmdline_cb_command(struct sandbox_state *state, const char *arg)
 }
 SB_CMDLINE_OPT_SHORT(command, 'c', 1, "Execute U-Boot command");
 
+static int sb_cmdline_cb_fdt(struct sandbox_state *state, const char *arg)
+{
+	state->fdt_fname = arg;
+	return 0;
+}
+SB_CMDLINE_OPT_SHORT(fdt, 'd', 1, "Specify U-Boot's control FDT");
+
 int main(int argc, char *argv[])
 {
 	struct sandbox_state *state;
arch/sandbox/include/asm/state.h +1 -0
index 2b62b46..9552708 100644
@@ -34,6 +34,7 @@ enum exit_type_id {
 /* The complete state of the test system */
 struct sandbox_state {
 	const char *cmd;		/* Command to execute */
+	const char *fdt_fname;		/* Filename of FDT binary */
 	enum exit_type_id exit_type;	/* How we exited U-Boot */
 	const char *parse_err;		/* Error to report from parsing */
 	int argc;			/* Program arguments */
arch/sandbox/lib/board.c +36 -6

84 lines not on this page · raw message

doc/README.fdt-control +5 -1
index 85bda03..69c69de 100644
@@ -142,7 +142,11 @@ join the two:
 
 and then flash image.bin onto your board.
 
-You cannot use both of these options at the same time.
+If CONFIG_OF_HOSTFILE os defined, then it will be read from a file on
+startup. This is only useful for sandbox. Use the -d flag to U-Boot to
+specify the file to read.
+
+You cannot use more than one of these options at the same time.
 
 If you wish to put the fdt at a different address in memory, you can
 define the "fdtcontroladdr" environment variable. This is the hex
include/configs/sandbox.h +2 -0
index 67d788a..1c7bbe1 100644
@@ -29,6 +29,7 @@
 #define CONFIG_SANDBOX_BITS_PER_LONG	64
 
 #define CONFIG_OF_CONTROL
+#define CONFIG_OF_HOSTFILE
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
 #define CONFIG_FIT
@@ -76,6 +77,7 @@
 #define CONFIG_SYS_MEMTEST_START	0x00100000
 #define CONFIG_SYS_MEMTEST_END		(CONFIG_SYS_MEMTEST_START + 0x1000)
 #define CONFIG_PHYS_64BIT
+#define CONFIG_SYS_FDT_LOAD_ADDR	0x1000000
 
 /* Size of our emulated memory */
 #define CONFIG_SYS_SDRAM_SIZE		(128 << 20)
Signature · 1 line
1.7.7.3
#33 lore raw

RFC PATCH 18/44 fdt: Add a parameter to fdt_valid()

In reply to Simon Glass

At present this only checks working_fdt, but we want to check other FDTs also. So add the FDT to check as a parameter to fdt_valid().

---
 common/cmd_fdt.c |   27 ++++++++++++++-------------
 1 files changed, 14 insertions(+), 13 deletions(-)
common/cmd_fdt.c +14 -13
index 0bdf7b6..0adebf1 100644
@@ -44,7 +44,7 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
-static int fdt_valid(void);
+static int fdt_valid(const void *blob);
 static int fdt_parse_prop(char *const*newval, int count, char *data, int *len);
 static int fdt_print(const char *pathp, char *prop, int depth);
 static int is_printable_string(const void *data, int len);
@@ -105,7 +105,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		 * Set the address [and length] of the fdt.
 		 */
 		if (argc == 2) {
-			if (!fdt_valid()) {
+			if (!fdt_valid(working_fdt)) {
+				working_fdt = NULL;
 				return 1;
 			}
 			printf("The address of the fdt is %p\n", working_fdt);
@@ -115,7 +116,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		addr = simple_strtoul(argv[2], NULL, 16);
 		set_working_fdt_addr((void *)addr);
 
-		if (!fdt_valid()) {
+		if (!fdt_valid(working_fdt)) {
+			working_fdt = NULL;
 			return 1;
 		}
 
@@ -168,7 +170,8 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		 * Set the address and length of the fdt.
 		 */
 		working_fdt = (struct fdt_header *)simple_strtoul(argv[2], NULL, 16);
-		if (!fdt_valid()) {
+		if (!fdt_valid(working_fdt)) {
+			working_fdt = NULL;
 			return 1;
 		}
 
@@ -593,16 +596,16 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 /****************************************************************************/
 
-static int fdt_valid(void)
+static int fdt_valid(const void *blob)
 {
 	int  err;
 
-	if (working_fdt == NULL) {
+	if (blob == NULL) {
 		printf ("The address of the fdt is invalid (NULL).\n");
 		return 0;
 	}
 
-	err = fdt_check_header(working_fdt);
+	err = fdt_check_header(blob);
 	if (err == 0)
 		return 1;	/* valid */
 
@@ -612,19 +615,17 @@ static int fdt_valid(void)
 		 * Be more informative on bad version.
 		 */
 		if (err == -FDT_ERR_BADVERSION) {
-			if (fdt_version(working_fdt) <
+			if (fdt_version(blob) <
 			    FDT_FIRST_SUPPORTED_VERSION) {
 				printf (" - too old, fdt %d < %d",
-					fdt_version(working_fdt),
+					fdt_version(blob),
 					FDT_FIRST_SUPPORTED_VERSION);
-				working_fdt = NULL;
 			}
-			if (fdt_last_comp_version(working_fdt) >
+			if (fdt_last_comp_version(blob) >
 			    FDT_LAST_SUPPORTED_VERSION) {
 				printf (" - too new, fdt %d > %d",
-					fdt_version(working_fdt),
+					fdt_version(blob),
 					FDT_LAST_SUPPORTED_VERSION);
-				working_fdt = NULL;
 			}
 			return 0;
 		}
Signature · 1 line
1.7.7.3
#34 lore raw

RFC PATCH 19/44 Add getenv_hex() to return an environment variable as hex

In reply to Simon Glass

This conversion is required in a number of places in U-Boot. Add a standard function to provide this feature, so we avoid all the different variations in the way it is coded.

---
 common/cmd_nvedit.c |   15 +++++++++++++++
 include/common.h    |   13 +++++++++++++
 2 files changed, 28 insertions(+), 0 deletions(-)
common/cmd_nvedit.c +15 -0
index d646d90..d6d5eea 100644
@@ -309,6 +309,21 @@ int setenv_hex(const char *varname, ulong value)
 	return setenv(varname, str);
 }
 
+ulong getenv_hex(const char *varname, ulong default_val)
+{
+	const char *s;
+	ulong value;
+	char *endp;
+
+	s = getenv(varname);
+	if (s)
+		value = simple_strtoul(s, &endp, 16);
+	if (!s || endp == s)
+		return default_val;
+
+	return value;
+}
+
 #ifndef CONFIG_SPL_BUILD
 static int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
include/common.h +13 -0
index 8ecaf56..cc6bf5e 100644
@@ -341,6 +341,19 @@ int	envmatch     (uchar *, int);
 char	*getenv	     (const char *);
 int	getenv_f     (const char *name, char *buf, unsigned len);
 ulong getenv_ulong(const char *name, int base, ulong default_val);
+
+/**
+ * getenv_hex() - Return an environment variable as a hex value
+ *
+ * Decode an environment as a hex number (it may or may not have a 0x
+ * prefix). If the environment variable cannot be found, or does not start
+ * with hex digits, the default value is returned.
+ *
+ * @varname:		Variable to decode
+ * @default_val:	Value to return on error
+ */
+ulong getenv_hex(const char *varname, ulong default_val);
+
 /*
  * Read an environment variable as a boolean
  * Return -1 if variable does not exist (default to true)
Signature · 1 line
1.7.7.3
#35 lore raw

RFC PATCH 20/44 fdt: Allow fdt command to check and update control FDT

In reply to Simon Glass

There is an existing fdt command to deal with the working FDT. Enhance this to support the control FDT also (CONFIG_OF_CONTROL).

Some nasty #ifdefs are added here - they are required until we move to generic board and every arch has an fdt_blob.

---
 common/cmd_fdt.c |   58 ++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 41 insertions(+), 17 deletions(-)
common/cmd_fdt.c +41 -17
index 0adebf1..a193cc3 100644
@@ -101,42 +101,66 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	 */
 	if (argv[1][0] == 'a') {
 		unsigned long addr;
+		int control = 0;
+		void *blob;
 		/*
 		 * Set the address [and length] of the fdt.
 		 */
-		if (argc == 2) {
-			if (!fdt_valid(working_fdt)) {
-				working_fdt = NULL;
+		argc -= 2;
+		argv += 2;
+/* Temporary #ifdef - some archs don't have fdt_blob yet */
+#ifdef CONFIG_OF_CONTROL
+		if (argc && !strcmp(*argv, "-c")) {
+			control = 1;
+			argc--;
+			argv++;
+		}
+#endif
+		if (argc == 0) {
+#ifdef CONFIG_OF_CONTROL
+			if (control)
+				blob = (void *)gd->fdt_blob;
+			else
+#endif
+				blob = working_fdt;
+			if (!blob || !fdt_valid(blob))
 				return 1;
-			}
-			printf("The address of the fdt is %p\n", working_fdt);
+			printf("The address of the fdt is %#08lx\n",
+				control ? (ulong)blob :
+					getenv_hex("fdtaddr", 0));
 			return 0;
 		}
 
-		addr = simple_strtoul(argv[2], NULL, 16);
-		set_working_fdt_addr((void *)addr);
-
-		if (!fdt_valid(working_fdt)) {
-			working_fdt = NULL;
-			return 1;
+		addr = simple_strtoul(argv[0], NULL, 16);
+		blob = (void *)addr;
+		if (control) {
+#ifdef CONFIG_OF_CONTROL
+			if (!fdt_valid(gd->fdt_blob))
+				return 1;
+			gd->fdt_blob = blob;
+#endif
+		} else {
+			if (!fdt_valid(blob))
+				return 1;
+			set_working_fdt_addr((void *)addr);
 		}
 
-		if (argc >= 4) {
+		if (argc >= 2) {
 			int  len;
 			int  err;
 			/*
 			 * Optional new length
 			 */
-			len = simple_strtoul(argv[3], NULL, 16);
-			if (len < fdt_totalsize(working_fdt)) {
+			len = simple_strtoul(argv[1], NULL, 16);
+			if (len < fdt_totalsize(blob)) {
 				printf ("New length %d < existing length %d, "
 					"ignoring.\n",
-					len, fdt_totalsize(working_fdt));
+					len, fdt_totalsize(blob));
 			} else {
 				/*
 				 * Open in place with a new length.
 				 */
-				err = fdt_open_into(working_fdt, working_fdt, len);
+				err = fdt_open_into(blob, blob, len);
 				if (err != 0) {
 					printf ("libfdt fdt_open_into(): %s\n",
 						fdt_strerror(err));
@@ -960,7 +984,7 @@ static int fdt_print(const char *pathp, char *prop, int depth)
 /********************************************************************/
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
-	"addr   <addr> [<length>]        - Set the fdt location to <addr>\n"
+	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
 #ifdef CONFIG_OF_BOARD_SETUP
 	"fdt boardsetup                      - Do board-specific set up\n"
 #endif
Signature · 1 line
1.7.7.3
#36 lore raw

RFC PATCH 21/44 sandbox: fdt: Support fdt command for sandbox

In reply to Simon Glass

By using map_sysmem() we can get the fdt command to work correctly with sandbox.

---
 common/cmd_fdt.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)
common/cmd_fdt.c +8 -2
index a193cc3..3d5ff0f 100644
@@ -29,6 +29,7 @@
 #include <linux/ctype.h>
 #include <linux/types.h>
 #include <asm/global_data.h>
+#include <asm/io.h>
 #include <fdt.h>
 #include <libfdt.h>
 #include <fdt_support.h>
@@ -56,7 +57,10 @@ struct fdt_header *working_fdt;
 
 void set_working_fdt_addr(void *addr)
 {
-	working_fdt = addr;
+	void *buf;
+
+	buf = map_sysmem((ulong)addr, 0);
+	working_fdt = buf;
 	setenv_addr("fdtaddr", addr);
 }
 
@@ -132,14 +136,16 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		}
 
 		addr = simple_strtoul(argv[0], NULL, 16);
-		blob = (void *)addr;
 		if (control) {
 #ifdef CONFIG_OF_CONTROL
+			blob = map_sysmem(addr, 0);
 			if (!fdt_valid(gd->fdt_blob))
 				return 1;
 			gd->fdt_blob = blob;
 #endif
 		} else {
+			blob = map_sysmem(addr, 0);
+
 			if (!fdt_valid(blob))
 				return 1;
 			set_working_fdt_addr((void *)addr);
Signature · 1 line
1.7.7.3
#37 lore raw

RFC PATCH 22/44 env: Fix minor comment typos in cmd_nvedit

In reply to Simon Glass

This should say 'environmnent'.

---
 common/cmd_nvedit.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)
common/cmd_nvedit.c +2 -2
index d6d5eea..7685a19 100644
@@ -282,7 +282,7 @@ int setenv(const char *varname, const char *varvalue)
 /**
  * Set an environment variable to an integer value
  *
- * @param varname	Environmet variable to set
+ * @param varname	Environment variable to set
  * @param value		Value to set it to
  * @return 0 if ok, 1 on error
  */
@@ -297,7 +297,7 @@ int setenv_ulong(const char *varname, ulong value)
 /**
  * Set an environment variable to an value in hex
  *
- * @param varname	Environmet variable to set
+ * @param varname	Environment variable to set
  * @param value		Value to set it to
  * @return 0 if ok, 1 on error
  */
Signature · 1 line
1.7.7.3
#38 lore raw

RFC PATCH 23/44 fdt: Skip checking FDT if the pointer is NULL

In reply to Simon Glass

If we have no FDT, don't attempt to read from it. This allows sandbox to run without an FDT if required.

---
 lib/fdtdec.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
lib/fdtdec.c +2 -1
index 6dba438..740bd56 100644
@@ -318,7 +318,8 @@ int fdtdec_check_fdt(void)
  */
 int fdtdec_prepare_fdt(void)
 {
-	if (((uintptr_t)gd->fdt_blob & 3) || fdt_check_header(gd->fdt_blob)) {
+	if (!gd->fdt_blob || ((uintptr_t)gd->fdt_blob & 3) ||
+			fdt_check_header(gd->fdt_blob)) {
 		printf("No valid FDT found - please append one to U-Boot "
 			"binary, use u-boot-dtb.bin or define "
 			"CONFIG_OF_EMBED\n");
Signature · 1 line
1.7.7.3
#39 lore raw

RFC PATCH 24/44 Revert "fdt- Tell the FDT library where the device tree is"

In reply to Simon Glass

This reverts commit 3b73459ea3421e9f8c6c8c62e1d3fe458ca5bc56.

In practice it doesn't seem like a good idea to make the the working FDT point to the control FDT. Now that we can access the control FDT using the 'fdt' command, there is no need for this feature. Remove it.

---
 common/main.c |    8 --------
 1 files changed, 0 insertions(+), 8 deletions(-)
common/main.c +0 -8
index 5d8454e..bbc3be6 100644
@@ -45,10 +45,6 @@
 #include <fdtdec.h>
 #endif
 
-#ifdef CONFIG_OF_LIBFDT
-#include <fdt_support.h>
-#endif /* CONFIG_OF_LIBFDT */
-
 #include <post.h>
 #include <linux/ctype.h>
 #include <menu.h>
@@ -500,10 +496,6 @@ void main_loop (void)
 #endif /* CONFIG_MENUKEY */
 #endif /* CONFIG_BOOTDELAY */
 
-#if defined CONFIG_OF_CONTROL
-	set_working_fdt_addr((void *)gd->fdt_blob);
-#endif /* CONFIG_OF_CONTROL */
-
 	/*
 	 * Main Loop for Monitor Command Processing
 	 */
Signature · 1 line
1.7.7.3
#40 lore raw

RFC PATCH 25/44 Add stdarg to vsprintf.h

In reply to Simon Glass

This file uses varargs, so add the header file so that it can be used when common has not been included.

TODO: Probably should drop this patch?

---
 include/vsprintf.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/vsprintf.h +2 -0
index 651077c..704b8cd 100644
@@ -24,6 +24,8 @@
 #ifndef __VSPRINTF_H
 #define __VSPRINTF_H
 
+#include <stdarg.h>
+
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
 /**
Signature · 1 line
1.7.7.3
#41 lore raw

RFC PATCH 26/44 Add minor updates to README.fdt-control

In reply to Simon Glass

A few things have changed since this doc was written, so update it to match the current state of things.

---
 doc/README.fdt-control |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)
doc/README.fdt-control +6 -1
index 69c69de..ba17879 100644
@@ -49,6 +49,10 @@ the features of each board in the device tree file, and have a single
 generic source base.
 
 To enable this feature, add CONFIG_OF_CONTROL to your board config file.
+It is currently supported on ARM, x86 and Microblaze - other architectures
+will need to add code to their arch/xxx/lib/board.c file to locate the
+FDT, at least until generic board support is complete. For ARM, Tegra and
+Exynos5 have device trees available for common devices.
 
 
 What is a Flat Device Tree?
@@ -99,7 +103,8 @@ Then run the compiler (your version will vary):
 	*   Bad configuration:	0
 	* Strange test result:	0
 
-You will also find a useful ftdump utility for decoding a binary file.
+You will also find a useful fdtdump utility for decoding a binary file, as
+well as fdtget/fdtput for reading and writing properties in a binary file.
 
 
 Where do I get an fdt file for my board?
Signature · 1 line
1.7.7.3
#42 lore raw

RFC PATCH 27/44 hash: Add a way to calculate a hash for any algortihm

In reply to Simon Glass

Rather than needing to call one of many hashing algorithms in U-Boot, provide a function hash_block() which handles this, and can support all available hash algorithms.

Once we have md5 supported within hashing, we can use this function in the FIT image code.

---
 common/hash.c  |   22 ++++++++++++++++++++++
 include/hash.h |   15 +++++++++++++++
 2 files changed, 37 insertions(+), 0 deletions(-)
common/hash.c +22 -0
index 2e0a67b..897b9a3 100644
@@ -29,6 +29,7 @@
 #include <sha1.h>
 #include <sha256.h>
 #include <asm/io.h>
+#include <asm/errno.h>
 
 /*
  * These are the hash algorithms we support. Chips which support accelerated
@@ -171,6 +172,27 @@ static void show_hash(struct hash_algo *algo, ulong addr, ulong len,
 		printf("%02x", output[i]);
 }
 
+int hash_block(const char *algo_name, const void *data, int len,
+	       uint8_t *output, int *output_size)
+{
+	struct hash_algo *algo;
+
+	algo = find_hash_algo(algo_name);
+	if (!algo) {
+		debug("Unknown hash algorithm '%s'\n", algo_name);
+		return -EPROTONOSUPPORT;
+	}
+	if (output_size && *output_size < algo->digest_size) {
+		debug("Output buffer size %d too small (need %d bytes)",
+		      *output_size, algo->digest_size);
+		return -ENOSPC;
+	}
+	*output_size = algo->digest_size;
+	algo->hash_func_ws(data, len, output, algo->chunk_size);
+
+	return 0;
+}
+
 int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[])
 {
include/hash.h +15 -0
index ba2ba65..dda6f79 100644
@@ -66,4 +66,19 @@ struct hash_algo {
 int hash_command(const char *algo_name, int verify, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[]);
 
+/**
+ * hash_block() - Hash a block according to the requested algorithm
+ *
+ * @algo_name:		Hash algorithm to use
+ * @data:		Data to hash
+ * @len:		Lengh of data to hash in bytes
+ * @output:		Place to put hash value
+ * @output_size:	On entry, the number of bytes available in output,
+ *			On exit, the number of bytes used
+ * @return 0 if ok, -ve on error: -EPROTONOSUPPORT for an unknown algorithm,
+ * -ENOSPC if the output buffer is not large enough.
+ */
+int hash_block(const char *algo_name, const void *data, int len,
+	       uint8_t *output, int *output_size);
+
 #endif
Signature · 1 line
1.7.7.3
#43 lore raw

RFC PATCH 28/44 sandbox: config: Enable FIT signatures with RSA

In reply to Simon Glass

We want to sign and verify images using sandbox, so enable these options.

---
 include/configs/sandbox.h |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)
include/configs/sandbox.h +2 -0
index 1c7bbe1..fb1c583 100644
@@ -33,6 +33,8 @@
 #define CONFIG_OF_LIBFDT
 #define CONFIG_LMB
 #define CONFIG_FIT
+#define CONFIG_FIT_SIGNATURE
+#define CONFIG_RSA
 #define CONFIG_CMD_FDT
 
 #define CONFIG_FS_FAT
Signature · 1 line
1.7.7.3
#44 lore raw

RFC PATCH 29/44 sandbox: Provide a way to map from host RAM to U-Boot RAM

In reply to Simon Glass

In many cases, pointers to memory are passed around, and these pointers refer to U-Boot memory, not host memory. This in itself is not a problem.

However, in a few places, we cast that pointer back to a ulong (being a U-Boot memory address). It is possible to convert many of these cases to avoid this. However there are data structures (e.g. struct bootm_headers) which use pointers. We could with a lot of effort adjust the structs and all code that uses them to use ulong instead of pointers.

This seems like an unacceptable cost, since our objective with sandbox is to minimise the impact on U-Boot code while maximising the features available to sandbox.

Therefore, create a map_to_sysmem() function which converts from a pointer to a U-Boot address. This can be used sparingly when needed.

---
 arch/sandbox/cpu/cpu.c        |    5 +++++
 arch/sandbox/include/asm/io.h |    2 ++
 include/common.h              |    5 +++++
 3 files changed, 12 insertions(+), 0 deletions(-)
arch/sandbox/cpu/cpu.c +5 -0
index d7684d3..6459b01 100644
@@ -57,6 +57,11 @@ void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
 	return (void *)(gd->ram_buf + paddr);
 }
 
+phys_addr_t map_to_sysmem(void *ptr)
+{
+	return (u8 *)ptr - gd->ram_buf;
+}
+
 void flush_dcache_range(unsigned long start, unsigned long stop)
 {
 }
arch/sandbox/include/asm/io.h +2 -0
index d8c0236..4ce7a84 100644
@@ -49,3 +49,5 @@ static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
 static inline void unmap_sysmem(const void *vaddr)
 {
 }
+
+phys_addr_t map_to_sysmem(void *ptr);
include/common.h +5 -0
index cc6bf5e..d2249b1 100644
@@ -896,6 +896,11 @@ static inline void *map_sysmem(phys_addr_t paddr, unsigned long len)
 static inline void unmap_sysmem(const void *vaddr)
 {
 }
+
+static inline phys_addr_t map_to_sysmem(void *ptr)
+{
+	return (phys_addr_t)ptr;
+}
 # endif
 
 #endif /* __ASSEMBLY__ */
Signature · 1 line
1.7.7.3
#45 lore raw

RFC PATCH 30/44 sandbox: image: Add support for booting images in sandbox

In reply to Simon Glass

Much of the image code uses addresses as ulongs and pointers interchangeably, casting between the two forms as needed.

This doesn't work with sandbox, which has a U-Boot RAM buffer which is separate from the host machine's memory.

Adjust the cost so that translating from a U-Boot address to a pointer uses map_sysmem(). This allows bootm to work correctly on sandbox.

Note that there are no exhaustive tests for this code on sandbox, so it is possible that some dark corners remain.

---
 common/cmd_bootm.c |   21 ++++++++++++---------
 common/image.c     |   46 +++++++++++++++++++++++++++-------------------
 include/image.h    |    2 +-
 3 files changed, 40 insertions(+), 29 deletions(-)
common/cmd_bootm.c +12 -9
index 7b07393..cac9e53 100644
@@ -36,6 +36,7 @@
 #include <lmb.h>
 #include <linux/ctype.h>
 #include <asm/byteorder.h>
+#include <asm/io.h>
 #include <linux/compiler.h>
 
 #if defined(CONFIG_CMD_USB)
@@ -92,7 +93,7 @@ static image_header_t *image_get_kernel(ulong img_addr, int verify);
 static int fit_check_kernel(const void *fit, int os_noffset, int verify);
 #endif
 
-static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
+static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 				char * const argv[], bootm_headers_t *images,
 				ulong *os_data, ulong *os_len);
 
@@ -192,8 +193,8 @@ static inline void boot_start_lmb(bootm_headers_t *images) { }
 
 static int bootm_start(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 {
-	void		*os_hdr;
-	int		ret;
+	const void *os_hdr;
+	int ret;
 
 	memset((void *)&images, 0, sizeof(images));
 	images.verify = getenv_yesno("verify");
@@ -837,14 +838,15 @@ static int fit_check_kernel(const void *fit, int os_noffset, int verify)
  *     pointer to image header if valid image was found, plus kernel start
  *     address and length, otherwise NULL
  */
-static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
+static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 		char * const argv[], bootm_headers_t *images, ulong *os_data,
 		ulong *os_len)
 {
 	image_header_t	*hdr;
 	ulong		img_addr;
+	const void *buf;
 #if defined(CONFIG_FIT)
-	void		*fit_hdr;
+	const void	*fit_hdr;
 	const char	*fit_uname_config = NULL;
 	const char	*fit_uname_kernel = NULL;
 	const void	*data;
@@ -880,7 +882,8 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 
 	/* check image type, for FIT images get FIT kernel node */
 	*os_data = *os_len = 0;
-	switch (genimg_get_format((void *)img_addr)) {
+	buf = map_sysmem(img_addr, 0);
+	switch (genimg_get_format(buf)) {
 	case IMAGE_FORMAT_LEGACY:
 		printf("## Booting kernel from Legacy Image at %08lx ...\n",
 				img_addr);
@@ -925,7 +928,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 		break;
 #if defined(CONFIG_FIT)
 	case IMAGE_FORMAT_FIT:
-		fit_hdr = (void *)img_addr;
+		fit_hdr = buf;
 		printf("## Booting kernel from FIT Image at %08lx ...\n",
 				img_addr);
 
@@ -1002,7 +1005,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 
 		*os_len = len;
 		*os_data = (ulong)data;
-		images->fit_hdr_os = fit_hdr;
+		images->fit_hdr_os = (void *)fit_hdr;
 		images->fit_uname_os = fit_uname_kernel;
 		images->fit_noffset_os = os_noffset;
 		break;
@@ -1016,7 +1019,7 @@ static void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 	debug("   kernel data at 0x%08lx, len = 0x%08lx (%ld)\n",
 			*os_data, *os_len, *os_len);
 
-	return (void *)img_addr;
+	return buf;
 }
 
 #ifdef CONFIG_SYS_LONGHELP
common/image.c +27 -19

168 lines not on this page · raw message

include/image.h +1 -1
index d6993d4..bf734db 100644
@@ -344,7 +344,7 @@ void genimg_print_time(time_t timestamp);
 #define IMAGE_FORMAT_LEGACY	0x01	/* legacy image_header based format */
 #define IMAGE_FORMAT_FIT	0x02	/* new, libfdt based format */
 
-int genimg_get_format(void *img_addr);
+int genimg_get_format(const void *img_addr);
 int genimg_has_config(bootm_headers_t *images);
 ulong genimg_get_image(ulong img_addr);
 
Signature · 1 line
1.7.7.3
#46 lore raw

RFC PATCH 30/44 sandbox: image: Add support for booting images in sandbox

Dear Simon Glass,

Quoted 6 lines

Much of the image code uses addresses as ulongs and pointers interchangeably, casting between the two forms as needed.

This doesn't work with sandbox, which has a U-Boot RAM buffer which is separate from the host machine's memory.

Quoted 7 lines

Adjust the cost so that translating from a U-Boot address to a pointer uses map_sysmem(). This allows bootm to work correctly on sandbox.

Note that there are no exhaustive tests for this code on sandbox, so it is possible that some dark corners remain.

Code looks reasonable overall

Best regards,
Marek Vasut

#47 lore raw

RFC PATCH 31/44 image: Add signing infrastructure

In reply to Simon Glass

Add a structure to describe an algorithm which can sign and (later) verify images.

---
 README                       |    5 +
 common/Makefile              |    1 +
 common/image-sig.c           |   42 +++++++++
 doc/uImage.FIT/signature.txt |  211 ++++++++++++++++++++++++++++++++++++++++++
 include/image.h              |   99 +++++++++++++++++++-
 tools/Makefile               |    2 +
 6 files changed, 359 insertions(+), 1 deletions(-)
 create mode 100644 common/image-sig.c
 create mode 100644 doc/uImage.FIT/signature.txt
README +5 -0
index e54279e..46918c4 100644
@@ -2685,6 +2685,11 @@ FIT uImage format:
 		most specific compatibility entry of U-Boot's fdt's root node.
 		The order of entries in the configuration's fdt is ignored.
 
+		CONFIG_FIT_SIGNATURE
+		This option enables signature verification of FIT uImages,
+		using a hash signed and verified using RSA. See
+		doc/uImage.FIT/signature.txt for more details.
+
 - Standalone program support:
 		CONFIG_STANDALONE_LOAD_ADDR
 
common/Makefile +1 -0
index f945911..8208b0b 100644
@@ -224,6 +224,7 @@ COBJS-y += console.o
 COBJS-y += dlmalloc.o
 COBJS-y += image.o
 COBJS-$(CONFIG_FIT) += image-fit.o
+COBJS-$(CONFIG_FIT_SIGNATURE) += image-sig.o
 COBJS-y += memsize.o
 COBJS-y += stdio.o
 
common/image-sig.c new file +42 -0

42 lines not on this page · raw message

doc/uImage.FIT/signature.txt new file +211 -0

211 lines not on this page · raw message

include/image.h +98 -1

115 lines not on this page · raw message

tools/Makefile +2 -0
index eb10ae9..0dae54d 100644
@@ -78,6 +78,7 @@ BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
 EXT_OBJ_FILES-$(CONFIG_BUILD_ENVCRC) += common/env_embedded.o
 EXT_OBJ_FILES-y += common/image.o
 EXT_OBJ_FILES-$(CONFIG_FIT) += common/image-fit.o
+EXT_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += common/image-sig.o
 EXT_OBJ_FILES-y += lib/crc32.o
 EXT_OBJ_FILES-y += lib/md5.o
 EXT_OBJ_FILES-y += lib/sha1.o
@@ -211,6 +212,7 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)image-fit.o \
 			$(obj)image.o \
 			$(obj)image-host.o \
+			$(obj)image-sig.o \
 			$(obj)imximage.o \
 			$(obj)kwbimage.o \
 			$(obj)pblimage.o \
Signature · 1 line
1.7.7.3
#48 lore raw

RFC PATCH 32/44 image: Support signing of images

In reply to Simon Glass

Add support for signing images using a new signature node. The process is handled by fdt_add_verification_data() which now takes parameters to provide the keys and related information.

---
 doc/uImage.FIT/sign-images.its |   42 +++++++++
 include/image.h                |   22 ++++-
 tools/fit_image.c              |    2 +-
 tools/image-host.c             |  181 +++++++++++++++++++++++++++++++++++++--
 4 files changed, 232 insertions(+), 15 deletions(-)
 create mode 100644 doc/uImage.FIT/sign-images.its
doc/uImage.FIT/sign-images.its new file +42 -0
new file mode 100644
index 0000000..f69326a
@@ -0,0 +1,42 @@
+/dts-v1/;
+
+/ {
+	description = "Chrome OS kernel image with one or more FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel at 1 {
+			data = /incbin/("test-kernel.bin");
+			type = "kernel_noload";
+			arch = "sandbox";
+			os = "linux";
+			compression = "none";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+		fdt at 1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+			};
+		};
+	};
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+		};
+	};
+};
include/image.h +18 -4
index 8c648dc..a1072c0 100644
@@ -611,12 +611,26 @@ int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore);
 int fit_set_timestamp(void *fit, int noffset, time_t timestamp);
 
 /**
- * fit_add_verification_data() - Calculate and add hashes to FIT
+ * fit_add_verification_data() - add verification data to FIT image nodes
  *
- * @fit:	Fit image to process
- * @return 0 if ok, <0 for error
+ * @keydir:	Directory containing keys
+ * @kwydest:	FDT blob to write public key information to
+ * @fit:	Pointer to the FIT format image header
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ *
+ * Adds hash values for all component images in the FIT blob.
+ * Hashes are calculated for all component images which have hash subnodes
+ * with algorithm property set to one of the supported hash algorithms.
+ *
+ * Also add signatures if signature nodes are present.
+ *
+ * returns
+ *     0, on success
+ *     libfdt error code, on failure
  */
-int fit_add_verification_data(void *fit);
+int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
+			      const char *comment, int require_keys);
 
 int fit_image_verify(const void *fit, int noffset);
 int fit_all_image_verify(const void *fit);
tools/fit_image.c +1 -1
index 8f51159..e0675d7 100644
@@ -125,7 +125,7 @@ static int fit_handle_file (struct mkimage_params *params)
 	}
 
 	/* set hashes for images in the blob */
-	if (fit_add_verification_data(ptr)) {
+	if (fit_add_verification_data(NULL, NULL, ptr, NULL, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
 		unlink (tmpfile);
tools/image-host.c +171 -10

223 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#49 lore raw

RFC PATCH 32/44 image: Support signing of images

Dear Simon Glass,

[...]

tools/image-host.c static int fit_image_process_hash(void *fit, const char *image_name, · line 142

Quoted 13 lines
tools/image-host.c +13 -0
+	int string_size;
+	int ret;
+
+	/*
+	 * Get the current string size, before we update the FIT and add
+	 * more
+	 */
+	string_size = fdt_size_dt_strings(fit);
+
+	ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
+	ret |= fdt_setprop_string(fit, noffset, "signer-name", "mkimage");
+	ret |= fdt_setprop_string(fit, noffset, "signer-version",
+				  PLAIN_VERSION);

Can you really be ORR'ing a signed variable such as "ret" ? [...]
Best regards,
Marek Vasut

#50 lore raw

RFC PATCH 32/44 image: Support signing of images

Hi Marek,

Quoted 4 lines · Marek Vasut

Dear Simon Glass,

[...]

Quoted 15 lines

tools/image-host.c static int fit_image_process_hash(void *fit, const char *image_name, · line 142

Quoted 13 lines
tools/image-host.c +13 -0
+     int string_size;
+     int ret;
+
+     /*
+      * Get the current string size, before we update the FIT and add
+      * more
+      */
+     string_size = fdt_size_dt_strings(fit);
+
+     ret = fdt_setprop(fit, noffset, FIT_VALUE_PROP, value, value_len);
+     ret |= fdt_setprop_string(fit, noffset, "signer-name", "mkimage");
+     ret |= fdt_setprop_string(fit, noffset, "signer-version",
+                               PLAIN_VERSION);

Can you really be ORR'ing a signed variable such as "ret" ?

It's pretty ugly, and it means that I don't get a proper error message, so I will change it, particularly as this is only used by mkimage and code size is not a concern.

Thanks very much for reviewing these patches, and for comments. The image code is actually mostly pretty nice so it hasn't been difficult to work with.

Regards,
Simon

Quoted 3 lines

[...]
Best regards,
Marek Vasut

#51 lore raw

RFC PATCH 33/44 image: Verify signatures in FIT images

In reply to Simon Glass

After checking hashes, also check signatures of FIT images.

---
 common/image-fit.c |   80 ++++++++++++++++++++--------
 common/image-sig.c |  148 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/image.h    |   37 +++++++++++++
 3 files changed, 243 insertions(+), 22 deletions(-)
common/image-fit.c +58 -22
index ed98460..d255595 100644
@@ -31,6 +31,8 @@
 #include <time.h>
 #else
 #include <common.h>
+#include <errno.h>
+DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
 #include <bootstage.h>
@@ -235,42 +237,42 @@ void fit_print_contents(const void *fit)
  * @fit: pointer to the FIT format image header
  * @noffset: offset of the hash node
  * @p: pointer to prefix string
+ * @type: Type of information to print ("hash" or "sign")
  *
  * fit_image_print_data() lists properies for the processed hash node
  *
  * returns:
  *     no returned results
  */
-static void fit_image_print_data(const void *fit, int noffset, const char *p)
+static void fit_image_print_data(const void *fit, int noffset, const char *p,
+				 const char *type)
 {
-	char *algo;
+	const char *keyname;
 	uint8_t *value;
 	int value_len;
-	int i, ret;
-
-	/*
-	 * Check subnode name, must be equal to "hash".
-	 * Multiple hash nodes require unique unit node
-	 * names, e.g. hash at 1, hash at 2, etc.
-	 */
-	if (strncmp(fit_get_name(fit, noffset, NULL),
-			FIT_HASH_NODENAME,
-			strlen(FIT_HASH_NODENAME)) != 0)
-		return;
-
-	debug("%s  Hash node:    '%s'\n", p,
-			fit_get_name(fit, noffset, NULL));
+	char *algo;
+	int required;
+	int ret, i;
 
-	printf("%s  Hash algo:    ", p);
+	debug("%s  %s node:    '%s'\n", p, type,
+	      fit_get_name(fit, noffset, NULL));
+	printf("%s  %s algo:    ", p, type);
 	if (fit_image_hash_get_algo(fit, noffset, &algo)) {
 		printf("invalid/unsupported\n");
 		return;
 	}
-	printf("%s\n", algo);
+	printf("%s", algo);
+	keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	required = fdt_getprop(fit, noffset, "required", NULL) != NULL;
+	if (keyname)
+		printf(":%s", keyname);
+	if (required)
+		printf(" (required)");
+	printf("\n");
 
 	ret = fit_image_hash_get_value(fit, noffset, &value,
 					&value_len);
-	printf("%s  Hash value:   ", p);
+	printf("%s  %s value:   ", p, type);
 	if (ret) {
 		printf("unavailable\n");
 	} else {
@@ -279,7 +281,18 @@ static void fit_image_print_data(const void *fit, int noffset, const char *p)
 		printf("\n");
 	}
 
-	debug("%s  Hash len:     %d\n", p, value_len);
+	debug("%s  %s len:     %d\n", p, type, value_len);
+
+	/* Signatures have a time stamp */
+	if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+		time_t timestamp;
+
+		printf("%s  Timestamp:    ", p);
+		if (fit_get_timestamp(fit, noffset, &timestamp))
+			printf("unavailable\n");
+		else
+			genimg_print_time(timestamp);
+	}
 }
 
 /**
@@ -304,8 +317,12 @@ static void fit_image_print_verification_data(const void *fit, int noffset,
 	 * names, e.g. hash at 1, hash at 2, signature at 1, signature at 2, etc.
 	 */
 	name = fit_get_name(fit, noffset, NULL);
-	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME)))
-		fit_image_print_data(fit, noffset, p);
+	if (!strncmp(name, FIT_HASH_NODENAME, strlen(FIT_HASH_NODENAME))) {
+		fit_image_print_data(fit, noffset, p, "Hash");
+	} else if (!strncmp(name, FIT_SIG_NODENAME,
+				strlen(FIT_SIG_NODENAME))) {
+		fit_image_print_data(fit, noffset, p, "Sign");
+	}
 }
 
 /**
@@ -952,6 +969,8 @@ int fit_image_verify(const void *fit, int image_noffset)
 	int		noffset;
 	int		ndepth;
 	char		*err_msg = "";
+	int verify_all = 1;
+	int ret;
 
 	/* Get image data and data length */
 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
@@ -959,6 +978,14 @@ int fit_image_verify(const void *fit, int image_noffset)
 		return 0;
 	}
 
+	/* Verify all required signatures */
+	if (IMAGE_ENABLE_VERIFY &&
+			fit_image_verify_required_sigs(fit, image_noffset,
+				data, size, gd_fdt_blob(), &verify_all)) {
+		err_msg = "Unable to verify required signature";
+		goto error;
+	}
+
 	/* Process all hash subnodes of the component image node */
 	for (ndepth = 0,
 			noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
@@ -977,6 +1004,15 @@ int fit_image_verify(const void *fit, int image_noffset)
 					size, &err_msg))
 				goto error;
 			puts("+ ");
+		} else if (IMAGE_ENABLE_VERIFY && verify_all &&
+				!strncmp(name, FIT_SIG_NODENAME,
+					strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_check_sig(fit, noffset, data,
+							size, -1, &err_msg);
+			if (ret)
+				puts("- ");
+			else
+				puts("+ ");
 		}
 	}
 
common/image-sig.c +148 -0

157 lines not on this page · raw message

include/image.h +37 -0
index a1072c0..b8aea83 100644
@@ -765,6 +765,43 @@ struct image_sig_algo {
  */
 struct image_sig_algo *image_get_sig_algo(const char *name);
 
+/**
+ * fit_image_verify_required_sigs() - Verify signatures marked as 'required'
+ *
+ * @fit:		FIT to check
+ * @image_noffset:	Offset of image node to check
+ * @data:		Image data to check
+ * @size:		Size of image data
+ * @sig_blob:		FDT containing public keys
+ * @no_sigsp:		Returns 1 if no signatures were required, and
+ *			therefore nothing was checked. The caller may wish
+ *			to fall back to other mechanisms, or refuse to
+ *			boot.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_verify_required_sigs(const void *fit, int image_noffset,
+		const char *data, size_t size, const void *sig_blob,
+		int *no_sigsp);
+
+/**
+ * fit_image_check_sig() - Check a single image signature node
+ *
+ * @fit:		FIT to check
+ * @noffset:		Offset of signature node to check
+ * @data:		Image data to check
+ * @size:		Size of image data
+ * @required_keynode:	Offset in the control FDT of the required key node,
+ *			if any. If this is given, then the image wil not
+ *			pass verification unless that key is used. If this is
+ *			-1 then any signature will do.
+ * @err_msgp:		In the event of an error, this will be pointed to a
+ *			help error string to display to the user.
+ * @return 0 if all verified ok, <0 on error
+ */
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+		size_t size, int required_keynode, char **err_msgp);
+
+
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
Signature · 1 line
1.7.7.3
#52 lore raw

RFC PATCH 33/44 image: Verify signatures in FIT images

Dear Simon Glass,

[...]

common/image-fit.c static void fit_image_print_data(const void *fit, int noffset, const char *p) · line 292

Quoted 7 lines
common/image-fit.c +7 -0
+	/* Signatures have a time stamp */
+	if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+		time_t timestamp;
+
+		printf("%s  Timestamp:    ", p);
+		if (fit_get_timestamp(fit, noffset, &timestamp))
+			printf("unavailable\n");

puts()

[...]
Best regards,
Marek Vasut

#53 lore raw

RFC PATCH 33/44 image: Verify signatures in FIT images

Hi Marek,

Quoted 12 lines · Marek Vasut

Dear Simon Glass,

[...]

common/image-fit.c static void fit_image_print_data(const void *fit, int noffset, const char *p) · line 292

Quoted 7 lines
common/image-fit.c +7 -0
+     /* Signatures have a time stamp */
+     if (IMAGE_ENABLE_TIMESTAMP && keyname) {
+             time_t timestamp;
+
+             printf("%s  Timestamp:    ", p);
+             if (fit_get_timestamp(fit, noffset, &timestamp))
+                     printf("unavailable\n");
Quoted 1 line

puts()

I don't think I can do that, since puts() prints a newline on the host (mkimage) but not in U-Boot. I will add a comment to that effect.

Regards,
Simon

Quoted 4 lines

[...]
Best regards,
Marek Vasut

#54 lore raw

RFC PATCH 34/44 image: Add RSA support for image signing

In reply to Simon Glass

RSA provides a public key encryption facility which is ideal for image signing and verification.

Images are signed using a private key by mkimage. Then at run-time, the images are verified using a private key.

This implementation uses openssl for the host part (mkimage). To avoid bringing large libraries into the U-Boot binary, the RSA public key is encoded using a simple numeric representation in the device tree.

---
 Makefile             |    1 +
 README               |   10 +
 common/image-sig.c   |    7 +
 config.mk            |    1 +
 include/rsa.h        |  108 ++++++++++++
 lib/rsa/Makefile     |   46 +++++
 lib/rsa/rsa-sign.c   |  454 ++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rsa/rsa-verify.c |  374 +++++++++++++++++++++++++++++++++++++++++
 tools/Makefile       |   15 ++-
 9 files changed, 1013 insertions(+), 3 deletions(-)
 create mode 100644 include/rsa.h
 create mode 100644 lib/rsa/Makefile
 create mode 100644 lib/rsa/rsa-sign.c
 create mode 100644 lib/rsa/rsa-verify.c
Makefile +1 -0
index ee21b24..3ce0c7b 100644
@@ -246,6 +246,7 @@ OBJS := $(addprefix $(obj),$(OBJS) $(RESET_OBJS-))
 HAVE_VENDOR_COMMON_LIB = $(if $(wildcard board/$(VENDOR)/common/Makefile),y,n)
 
 LIBS-y += lib/libgeneric.o
+LIBS-y += lib/rsa/librsa.o
 LIBS-y += lib/lzma/liblzma.o
 LIBS-y += lib/lzo/liblzo.o
 LIBS-y += lib/zlib/libz.o
README +10 -0
index 46918c4..a637f91 100644
@@ -2461,6 +2461,16 @@ CBFS (Coreboot Filesystem) support
 		Note: There is also a sha1sum command, which should perhaps
 		be deprecated in favour of 'hash sha1'.
 
+- Signing support:
+		CONFIG_RSA
+
+		This enables the RSA algorithm used for FIT image verification
+		in U-Boot. See doc/uImage/signature for more information.
+
+		The signing part is build into mkimage regardless of this
+		option.
+
+
 - Show boot progress:
 		CONFIG_SHOW_BOOT_PROGRESS
 
common/image-sig.c +7 -0
index 793e7d6..c74d2f4 100644
@@ -27,8 +27,15 @@ DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 #include <errno.h>
 #include <image.h>
+#include <rsa.h>
 
 struct image_sig_algo image_sig_algos[] = {
+	{
+		"sha1,rsa2048",
+		rsa_sign,
+		rsa_add_verify_data,
+		rsa_verify,
+	}
 };
 
 struct image_sig_algo *image_get_sig_algo(const char *name)
config.mk +1 -0
index 04cfe89..74e2922 100644
@@ -91,6 +91,7 @@ HOSTCFLAGS	+= $(call os_x_before, 10, 4, "-traditional-cpp")
 HOSTLDFLAGS	+= $(call os_x_before, 10, 5, "-multiply_defined suppress")
 else
 HOSTCC		= gcc
+HOSTLIBS	+= -lssl -lcrypto
 endif
 
 ifeq ($(HOSTOS),cygwin)
include/rsa.h new file +108 -0

108 lines not on this page · raw message

lib/rsa/Makefile new file +46 -0

46 lines not on this page · raw message

lib/rsa/rsa-sign.c new file +454 -0

454 lines not on this page · raw message

lib/rsa/rsa-verify.c new file +374 -0

374 lines not on this page · raw message

tools/Makefile +12 -3
index 0dae54d..823d109 100644
@@ -121,6 +121,9 @@ LIBFDT_OBJ_FILES-y += fdt_rw.o
 LIBFDT_OBJ_FILES-y += fdt_strerror.o
 LIBFDT_OBJ_FILES-y += fdt_wip.o
 
+# RSA objects
+RSA_OBJ_FILES-y += rsa-sign.o
+
 # Generated LCD/video logo
 LOGO_H = $(OBJTREE)/include/bmp_logo.h
 LOGO_DATA_H = $(OBJTREE)/include/bmp_logo_data.h
@@ -155,8 +158,10 @@ endif
 HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c))
 HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c))
+HOSTSRCS += $(addprefix $(SRCTREE)/lib/rsa/,$(LIBRSA_OBJ_FILES-y:.o=.c))
 BINS	:= $(addprefix $(obj),$(sort $(BIN_FILES-y)))
 LIBFDT_OBJS	:= $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y))
+RSA_OBJS	:= $(addprefix $(obj),$(RSA_OBJ_FILES-y))
 
 HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y))
 NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y))
@@ -222,9 +227,10 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)omapimage.o \
 			$(obj)sha1.o \
 			$(obj)ublimage.o \
-			$(LIBFDT_OBJS)
-	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
-	$(HOSTSTRIP) $@
+			$(LIBFDT_OBJS) \
+			$(RSA_OBJS)
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
+	#(HOSTSTRIP) $@
 
 $(obj)mk$(BOARD)spl$(SFX):	$(obj)mkexynosspl.o
 	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
@@ -259,6 +265,9 @@ $(obj)%.o: $(SRCTREE)/lib/%.c
 $(obj)%.o: $(SRCTREE)/lib/libfdt/%.c
 	$(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
 
+$(obj)%.o: $(SRCTREE)/lib/rsa/%.c
+	$(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $<
+
 subdirs:
 ifeq ($(TOOLSUBDIRS),)
 	@:
Signature · 1 line
1.7.7.3
#55 lore raw

RFC PATCH 34/44 image: Add RSA support for image signing

Dear Simon Glass,

Quoted 11 lines

RSA provides a public key encryption facility which is ideal for image signing and verification.

Images are signed using a private key by mkimage. Then at run-time, the images are verified using a private key.

This implementation uses openssl for the host part (mkimage). To avoid bringing large libraries into the U-Boot binary, the RSA public key is encoded using a simple numeric representation in the device tree.

You want to run spellcheck over your comments ... eg. s/mutliply/multiply/ ;-) Best regards,
Marek Vasut

#56 lore raw

RFC PATCH 35/44 mkimage: Put FIT loading in function and tidy error handling

In reply to Simon Glass

The fit_handle_file() function is quiet long - split out the part that loads and checks a FIT into its own function. We will use this function for storing public keys into a destination FDT file.

The error handling is currently a bit repetitive - tidy it.

---
 tools/fit_image.c |   96 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 57 insertions(+), 39 deletions(-)
tools/fit_image.c +57 -39
index e0675d7..0f619a2 100644
@@ -47,6 +47,48 @@ static int fit_check_image_types (uint8_t type)
 		return EXIT_FAILURE;
 }
 
+int mmap_fdt(struct mkimage_params *params, const char *fname, void **blobp,
+		struct stat *sbuf)
+{
+	void *ptr;
+	int fd;
+
+	/* load FIT blob into memory */
+	fd = open(fname, O_RDWR|O_BINARY);
+
+	if (fd < 0) {
+		fprintf(stderr, "%s: Can't open %s: %s\n",
+				params->cmdname, fname, strerror(errno));
+		unlink(fname);
+		return -1;
+	}
+
+	if (fstat(fd, sbuf) < 0) {
+		fprintf(stderr, "%s: Can't stat %s: %s\n",
+				params->cmdname, fname, strerror(errno));
+		unlink(fname);
+		return -1;
+	}
+
+	ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+	if (ptr == MAP_FAILED) {
+		fprintf(stderr, "%s: Can't read %s: %s\n",
+				params->cmdname, fname, strerror(errno));
+		unlink(fname);
+		return -1;
+	}
+
+	/* check if ptr has a valid blob */
+	if (fdt_check_header(ptr)) {
+		fprintf(stderr, "%s: Invalid FIT blob\n", params->cmdname);
+		unlink(fname);
+		return -1;
+	}
+
+	*blobp = ptr;
+	return fd;
+}
+
 /**
  * fit_handle_file - main FIT file processing function
  *
@@ -65,7 +107,7 @@ static int fit_handle_file (struct mkimage_params *params)
 	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
 	int tfd;
 	struct stat sbuf;
-	unsigned char *ptr;
+	void *ptr;
 
 	/* Flattened Image Tree (FIT) format  handling */
 	debug ("FIT format handling\n");
@@ -87,57 +129,25 @@ static int fit_handle_file (struct mkimage_params *params)
 	if (system (cmd) == -1) {
 		fprintf (stderr, "%s: system(%s) failed: %s\n",
 				params->cmdname, cmd, strerror(errno));
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
-	}
-
-	/* load FIT blob into memory */
-	tfd = open (tmpfile, O_RDWR|O_BINARY);
-
-	if (tfd < 0) {
-		fprintf (stderr, "%s: Can't open %s: %s\n",
-				params->cmdname, tmpfile, strerror(errno));
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
+		goto err_system;
 	}
 
-	if (fstat (tfd, &sbuf) < 0) {
-		fprintf (stderr, "%s: Can't stat %s: %s\n",
-				params->cmdname, tmpfile, strerror(errno));
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
-	}
-
-	ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED,
-				tfd, 0);
-	if (ptr == MAP_FAILED) {
-		fprintf (stderr, "%s: Can't read %s: %s\n",
-				params->cmdname, tmpfile, strerror(errno));
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
-	}
-
-	/* check if ptr has a valid blob */
-	if (fdt_check_header (ptr)) {
-		fprintf (stderr, "%s: Invalid FIT blob\n", params->cmdname);
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
-	}
+	tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf);
+	if (tfd < 0)
+		goto err_mmap;
 
 	/* set hashes for images in the blob */
 	if (fit_add_verification_data(NULL, NULL, ptr, NULL, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
+		goto err_add_hashes;
 	}
 
 	/* add a timestamp at offset 0 i.e., root  */
 	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
 		fprintf (stderr, "%s: Can't add image timestamp\n",
 				params->cmdname);
-		unlink (tmpfile);
-		return (EXIT_FAILURE);
+		goto err_add_timestamp;
 	}
 	debug ("Added timestamp successfully\n");
 
@@ -153,6 +163,14 @@ static int fit_handle_file (struct mkimage_params *params)
 		return (EXIT_FAILURE);
 	}
 	return (EXIT_SUCCESS);
+
+err_add_timestamp:
+err_add_hashes:
+	munmap(ptr, sbuf.st_size);
+err_mmap:
+err_system:
+	unlink(tmpfile);
+	return -1;
 }
 
 static int fit_check_params (struct mkimage_params *params)
Signature · 1 line
1.7.7.3
#57 lore raw

RFC PATCH 35/44 mkimage: Put FIT loading in function and tidy error handling

Dear Simon Glass,

Quoted 1 line

The fit_handle_file() function is quiet long

quite ;-)

Quoted 18 lines

- split out the part that
loads and checks a FIT into its own function. We will use this function for storing public keys into a destination FDT file.

The error handling is currently a bit repetitive - tidy it.

---
 tools/fit_image.c |   96

+++++++++++++++++++++++++++++++--------------------- 1 files changed, 57 insertions(+), 39 deletions(-)

tools/fit_image.c +0 -0
index e0675d7..0f619a2 100644
@@ -47,6 +47,48 @@ static int fit_check_image_types (uint8_t type)
 		return EXIT_FAILURE;

tools/fit_image.c static int fit_check_image_types (uint8_t type) · line 57

Quoted 10 lines
tools/fit_image.c +7 -0
 }
 
+int mmap_fdt(struct mkimage_params *params, const char *fname, void
 **blobp, +		struct stat *sbuf)
+{
+	void *ptr;
+	int fd;
+
+	/* load FIT blob into memory */
+	fd = open(fname, O_RDWR|O_BINARY);

Why is it RDWR even?

otherwise

Best regards,
Marek Vasut

#58 lore raw

RFC PATCH 35/44 mkimage: Put FIT loading in function and tidy error handling

Hi Marek,

Quoted 5 lines · Marek Vasut

Dear Simon Glass,

Quoted 1 line

The fit_handle_file() function is quiet long

quite ;-)

Quite.

Quoted 21 lines
Quoted 21 lines

- split out the part that
loads and checks a FIT into its own function. We will use this function for storing public keys into a destination FDT file.

The error handling is currently a bit repetitive - tidy it.

---
 tools/fit_image.c |   96

+++++++++++++++++++++++++++++++--------------------- 1 files changed, 57 insertions(+), 39 deletions(-)

tools/fit_image.c +0 -0
index e0675d7..0f619a2 100644
@@ -47,6 +47,48 @@ static int fit_check_image_types (uint8_t type)
              return EXIT_FAILURE;
 }
 
Quoted 10 lines

tools/fit_image.c static int fit_check_image_types (uint8_t type) · line 57

Quoted 8 lines
tools/fit_image.c +7 -0
+int mmap_fdt(struct mkimage_params *params, const char *fname, void
 **blobp, +            struct stat *sbuf)
+{
+     void *ptr;
+     int fd;
+
+     /* load FIT blob into memory */
+     fd = open(fname, O_RDWR|O_BINARY);

Why is it RDWR even?

Because the blob gets updated (e.g. by writing hashes to the FIT). I will add a comment.

Quoted 7 lines

otherwise

Best regards,
Marek Vasut

Regards,
Simon

#59 lore raw

RFC PATCH 36/44 mkimage: Add -k option to specify key directory

In reply to Simon Glass

Keys required for signing images will be in a specific directory. Add a -k option to specify that directory.

Also update the mkimage man page with this information and a clearer list of available commands.

---
 doc/mkimage.1     |   25 ++++++++++++++++++++++---
 tools/fit_image.c |    2 +-
 tools/mkimage.c   |    9 +++++++--
 tools/mkimage.h   |    1 +
 4 files changed, 31 insertions(+), 6 deletions(-)
doc/mkimage.1 +22 -3
index 39652c8..6740fb1 100644
@@ -4,7 +4,14 @@
 mkimage \- Generate image for U-Boot
 .SH SYNOPSIS
 .B mkimage
-.RB [\fIoptions\fP]
+.RB "\-l [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " \-f [" "image tree source file" "]" " [" "uimage file name" "]"
+
+.B mkimage
+.RB [\fIoptions\fP] " (legacy mode)"
+
 .SH "DESCRIPTION"
 The
 .B mkimage
@@ -26,7 +33,8 @@ etc.
 The new
 .I FIT (Flattened Image Tree) format
 allows for more flexibility in handling images of various types and also
-enhances integrity protection of images with stronger checksums.
+enhances integrity protection of images with stronger checksums. It also
+supports verified boot.
 
 .SH "OPTIONS"
 
@@ -67,6 +75,10 @@ Set load address with a hex number.
 Set entry point with a hex number.
 
 .TP
+.BI "\-l"
+List the contents of an image.
+
+.TP
 .BI "\-n [" "image name" "]"
 Set image name to 'image name'.
 
@@ -91,6 +103,12 @@ create the image.
 Image tree source file that describes the structure and contents of the
 FIT image.
 
+.TP
+.BI "\-k [" "key_directory" "]"
+Specifies the directory containing keys to use for signing. This directory
+should contain a private key file <name>.key for use with signing and a
+certificate <name>.crt (containing the public key) for use with verification.
+
 .SH EXAMPLES
 
 List image information:
@@ -115,4 +133,5 @@ http://www.denx.de/wiki/U-Boot/WebHome
 .PP
 .SH AUTHOR
 This manual page was written by Nobuhiro Iwamatsu <[email protected]>
-and Wolfgang Denk <[email protected]>
+and Wolfgang Denk <[email protected]>. It was updated for image signing by
+Simon Glass <[email protected]>.
tools/fit_image.c +1 -1
index 0f619a2..5d04f96 100644
@@ -137,7 +137,7 @@ static int fit_handle_file (struct mkimage_params *params)
 		goto err_mmap;
 
 	/* set hashes for images in the blob */
-	if (fit_add_verification_data(NULL, NULL, ptr, NULL, 0)) {
+	if (fit_add_verification_data(params->keydir, NULL, ptr, NULL, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
 		goto err_add_hashes;
tools/mkimage.c +7 -2
index e43b09f..0eae136 100644
@@ -248,6 +248,11 @@ main (int argc, char **argv)
 				params.datafile = *++argv;
 				params.fflag = 1;
 				goto NXTARG;
+			case 'k':
+				if (--argc <= 0)
+					usage();
+				params.keydir = *++argv;
+				goto NXTARG;
 			case 'n':
 				if (--argc <= 0)
 					usage ();
@@ -623,8 +628,8 @@ usage ()
 			 "          -d ==> use image data from 'datafile'\n"
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
-	fprintf (stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n",
-		params.cmdname);
+	fprintf(stderr, "       %s [-k keydir] [-D dtc_options]"
+			" -f fit-image.its fit-image\n", params.cmdname);
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
tools/mkimage.h +1 -0
index e07a615..2a5f115 100644
@@ -75,6 +75,7 @@ struct mkimage_params {
 	char *datafile;
 	char *imagefile;
 	char *cmdname;
+	const char *keydir;	/* Directory holding private keys */
 };
 
 /*
Signature · 1 line
1.7.7.3
#60 lore raw

RFC PATCH 36/44 mkimage: Add -k option to specify key directory

Dear Simon Glass,

Quoted 7 lines

Keys required for signing images will be in a specific directory. Add a -k option to specify that directory.

Also update the mkimage man page with this information and a clearer list of available commands.

Best regards,
Marek Vasut

#61 lore raw

RFC PATCH 37/44 mkimage: Add -K to write public keys to an FDT blob

In reply to Simon Glass

FIT image verification requires public keys. Add a convenient option to mkimage to write the public keys to an FDT blob when it uses then for signing an image. This allows us to use:

mkimage -f test.its -K dest.dtb -k keys test.fit

and have the signatures written to test.fit and the corresponding public keys written to dest.dtb. Then dest.dtb can be used as the control FDT for U-Boot (CONFIG_OF_CONTROL), thus providing U-Boot with access to the public keys it needs.

---
 doc/mkimage.1     |   16 ++++++++++++++++
 tools/fit_image.c |   21 +++++++++++++++++++--
 tools/mkimage.c   |    7 ++++++-
 tools/mkimage.h   |    1 +
 4 files changed, 42 insertions(+), 3 deletions(-)
doc/mkimage.1 +16 -0
index 6740fb1..8185ff5 100644
@@ -109,6 +109,14 @@ Specifies the directory containing keys to use for signing. This directory
 should contain a private key file <name>.key for use with signing and a
 certificate <name>.crt (containing the public key) for use with verification.
 
+.TP
+.BI "\-K [" "key_destination" "]"
+Specifies a compiled device tree binary file (typically .dtb) to write
+public key information into. When a private key is used to sign an image,
+the corresponding public key is written into this file for for run-time
+verification. Typically the file here is the device tree binary used by
+CONFIG_OF_CONTROL in U-Boot.
+
 .SH EXAMPLES
 
 List image information:
@@ -127,6 +135,14 @@ Create FIT image with compressed PowerPC Linux kernel:
 .nf
 .B mkimage -f kernel.its kernel.itb
 .fi
+.P
+Create FIT image with compressed kernel and sign it with keys in the
+/public/signing-keys directory. Add corresponding public keys into u-boot.dtb,
+skipping those for which keys cannot be found. Also add a comment.
+.nf
+.B mkimage -f kernel.its -k /public/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
 
 .SH HOMEPAGE
 http://www.denx.de/wiki/U-Boot/WebHome
tools/fit_image.c +19 -2
index 5d04f96..306298a 100644
@@ -105,9 +105,11 @@ static int fit_handle_file (struct mkimage_params *params)
 {
 	char tmpfile[MKIMAGE_MAX_TMPFILE_LEN];
 	char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN];
-	int tfd;
+	int tfd, destfd = 0;
+	void *dest_blob = NULL;
 	struct stat sbuf;
 	void *ptr;
+	off_t destfd_size = 0;
 
 	/* Flattened Image Tree (FIT) format  handling */
 	debug ("FIT format handling\n");
@@ -132,12 +134,20 @@ static int fit_handle_file (struct mkimage_params *params)
 		goto err_system;
 	}
 
+	if (params->keydest) {
+		destfd = mmap_fdt(params, params->keydest, &dest_blob, &sbuf);
+		if (destfd < 0)
+			goto err_keydest;
+		destfd_size = sbuf.st_size;
+	}
+
 	tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf);
 	if (tfd < 0)
 		goto err_mmap;
 
 	/* set hashes for images in the blob */
-	if (fit_add_verification_data(params->keydir, NULL, ptr, NULL, 0)) {
+	if (fit_add_verification_data(params->keydir,
+			dest_blob, ptr, NULL, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
 		goto err_add_hashes;
@@ -153,6 +163,10 @@ static int fit_handle_file (struct mkimage_params *params)
 
 	munmap ((void *)ptr, sbuf.st_size);
 	close (tfd);
+	if (dest_blob) {
+		munmap(dest_blob, destfd_size);
+		close(destfd);
+	}
 
 	if (rename (tmpfile, params->imagefile) == -1) {
 		fprintf (stderr, "%s: Can't rename %s to %s: %s\n",
@@ -168,6 +182,9 @@ err_add_timestamp:
 err_add_hashes:
 	munmap(ptr, sbuf.st_size);
 err_mmap:
+	if (dest_blob)
+		munmap(dest_blob, destfd_size);
+err_keydest:
 err_system:
 	unlink(tmpfile);
 	return -1;
tools/mkimage.c +6 -1
index 0eae136..30a5a06 100644
@@ -253,6 +253,11 @@ main (int argc, char **argv)
 					usage();
 				params.keydir = *++argv;
 				goto NXTARG;
+			case 'K':
+				if (--argc <= 0)
+					usage();
+				params.keydest = *++argv;
+				goto NXTARG;
 			case 'n':
 				if (--argc <= 0)
 					usage ();
@@ -628,7 +633,7 @@ usage ()
 			 "          -d ==> use image data from 'datafile'\n"
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
-	fprintf(stderr, "       %s [-k keydir] [-D dtc_options]"
+	fprintf(stderr, "       %s [-k keydir] [-K dtb] [-D dtc_options]"
 			" -f fit-image.its fit-image\n", params.cmdname);
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
tools/mkimage.h +1 -0
index 2a5f115..41bec21 100644
@@ -76,6 +76,7 @@ struct mkimage_params {
 	char *imagefile;
 	char *cmdname;
 	const char *keydir;	/* Directory holding private keys */
+	const char *keydest;	/* Destination .dtb for public key */
 };
 
 /*
Signature · 1 line
1.7.7.3
#62 lore raw

RFC PATCH 37/44 mkimage: Add -K to write public keys to an FDT blob

Dear Simon Glass,

Quoted 4 lines

FIT image verification requires public keys. Add a convenient option to mkimage to write the public keys to an FDT blob when it uses then for signing an image. This allows us to use:

Quoted 8 lines

mkimage -f test.its -K dest.dtb -k keys test.fit

and have the signatures written to test.fit and the corresponding public keys written to dest.dtb. Then dest.dtb can be used as the control FDT for U-Boot (CONFIG_OF_CONTROL), thus providing U-Boot with access to the public keys it needs.

Best regards,
Marek Vasut

#63 lore raw

RFC PATCH 38/44 mkimage: Add -F option to modify an existing .fit file

In reply to Simon Glass

When signing images it is sometimes necessary to sign with different keys at different times, or make the signer entirely separate from the FIT creation to avoid needing the private keys to be publicly available in the system.

Add a -F option so that key signing can be a separate step, and possibly done multiple times as different keys are avaiable.

---
 doc/mkimage.1     |   20 ++++++++++++++++++++
 tools/fit_image.c |   18 ++++++++++++------
 tools/mkimage.c   |    6 ++++--
 3 files changed, 36 insertions(+), 8 deletions(-)
doc/mkimage.1 +20 -0
index 8185ff5..f9c733a 100644
@@ -10,6 +10,9 @@ mkimage \- Generate image for U-Boot
 .RB [\fIoptions\fP] " \-f [" "image tree source file" "]" " [" "uimage file name" "]"
 
 .B mkimage
+.RB [\fIoptions\fP] " \-F [" "uimage file name" "]"
+
+.B mkimage
 .RB [\fIoptions\fP] " (legacy mode)"
 
 .SH "DESCRIPTION"
@@ -104,6 +107,13 @@ Image tree source file that describes the structure and contents of the
 FIT image.
 
 .TP
+.BI "\-F"
+Indicates that an existing FIT image should be modified. No dtc
+compilation is performed and the -f flag should not be given.
+This can be used to sign images with additional keys after initial image
+creation.
+
+.TP
 .BI "\-k [" "key_directory" "]"
 Specifies the directory containing keys to use for signing. This directory
 should contain a private key file <name>.key for use with signing and a
@@ -144,6 +154,16 @@ skipping those for which keys cannot be found. Also add a comment.
 -c "Kernel 3.8 image for production devices" kernel.itb
 .fi
 
+.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
+with unavailable keys are skipped.
+.nf
+.B mkimage -F -k /secret/signing-keys -K u-boot.dtb \\\\
+-c "Kernel 3.8 image for production devices" kernel.itb
+.fi
+
 .SH HOMEPAGE
 http://www.denx.de/wiki/U-Boot/WebHome
 .PP
tools/fit_image.c +12 -6
index 306298a..835d2fb 100644
@@ -124,10 +124,16 @@ static int fit_handle_file (struct mkimage_params *params)
 	}
 	sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX);
 
-	/* dtc -I dts -O dtb -p 500 datafile > tmpfile */
-	sprintf (cmd, "%s %s %s > %s",
-		MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
-	debug ("Trying to execute \"%s\"\n", cmd);
+	/* We either compile the source file, or use the existing FIT image */
+	if (params->datafile) {
+		/* dtc -I dts -O dtb -p 500 datafile > tmpfile */
+		snprintf(cmd, sizeof(cmd), "%s %s %s > %s",
+			MKIMAGE_DTC, params->dtc, params->datafile, tmpfile);
+		debug("Trying to execute \"%s\"\n", cmd);
+	} else {
+		snprintf(cmd, sizeof(cmd), "cp %s %s",
+			params->imagefile, tmpfile);
+	}
 	if (system (cmd) == -1) {
 		fprintf (stderr, "%s: system(%s) failed: %s\n",
 				params->cmdname, cmd, strerror(errno));
@@ -153,8 +159,8 @@ static int fit_handle_file (struct mkimage_params *params)
 		goto err_add_hashes;
 	}
 
-	/* add a timestamp at offset 0 i.e., root  */
-	if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) {
+	/* for first image creation, add a timestamp at offset 0 i.e., root  */
+	if (params->datafile && fit_set_timestamp(ptr, 0, sbuf.st_mtime)) {
 		fprintf (stderr, "%s: Can't add image timestamp\n",
 				params->cmdname);
 		goto err_add_timestamp;
tools/mkimage.c +4 -2
index 30a5a06..99787d9 100644
@@ -240,12 +240,14 @@ main (int argc, char **argv)
 			case 'f':
 				if (--argc <= 0)
 					usage ();
+				params.datafile = *++argv;
+				/* no break */
+			case 'F':
 				/*
 				 * The flattened image tree (FIT) format
 				 * requires a flattened device tree image type
 				 */
 				params.type = IH_TYPE_FLATDT;
-				params.datafile = *++argv;
 				params.fflag = 1;
 				goto NXTARG;
 			case 'k':
@@ -634,7 +636,7 @@ usage ()
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
 	fprintf(stderr, "       %s [-k keydir] [-K dtb] [-D dtc_options]"
-			" -f fit-image.its fit-image\n", params.cmdname);
+			" [-f fit-image.its|-F] fit-image\n", params.cmdname);
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
Signature · 1 line
1.7.7.3
#64 lore raw

RFC PATCH 38/44 mkimage: Add -F option to modify an existing .fit file

Dear Simon Glass,

Quoted 9 lines

When signing images it is sometimes necessary to sign with different keys at different times, or make the signer entirely separate from the FIT creation to avoid needing the private keys to be publicly available in the system.

Add a -F option so that key signing can be a separate step, and possibly done multiple times as different keys are avaiable.

Best regards,
Marek Vasut

#65 lore raw

RFC PATCH 39/44 mkimage: Add -c option to specify a comment for key signing

In reply to Simon Glass

When signing an image, it is useful to add some details about which tool or person is authorising the signing. Add a comment field which can take care of miscellaneous requirements.

---
 doc/mkimage.1     |    6 ++++++
 tools/fit_image.c |    2 +-
 tools/mkimage.c   |    8 +++++++-
 tools/mkimage.h   |    1 +
 4 files changed, 15 insertions(+), 2 deletions(-)
doc/mkimage.1 +6 -0
index f9c733a..b67a351 100644
@@ -97,6 +97,12 @@ Set XIP (execute in place) flag.
 .B Create FIT image:
 
 .TP
+.BI "\-c [" "comment" "]"
+Specifies a comment to be added when signing. This is typically a useful
+message which describes how the image was signed or some other useful
+information.
+
+.TP
 .BI "\-D [" "dtc options" "]"
 Provide special options to the device tree compiler that is used to
 create the image.
tools/fit_image.c +1 -1
index 835d2fb..82f1597 100644
@@ -153,7 +153,7 @@ static int fit_handle_file (struct mkimage_params *params)
 
 	/* set hashes for images in the blob */
 	if (fit_add_verification_data(params->keydir,
-			dest_blob, ptr, NULL, 0)) {
+			dest_blob, ptr, params->comment, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
 				params->cmdname);
 		goto err_add_hashes;
tools/mkimage.c +7 -1
index 99787d9..d6e47a5 100644
@@ -183,6 +183,11 @@ main (int argc, char **argv)
 					genimg_get_arch_id (*++argv)) < 0)
 					usage ();
 				goto NXTARG;
+			case 'c':
+				if (--argc <= 0)
+					usage();
+				params.comment = *++argv;
+				goto NXTARG;
 			case 'C':
 				if ((--argc <= 0) ||
 					(params.comp =
@@ -636,7 +641,8 @@ usage ()
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
 	fprintf(stderr, "       %s [-k keydir] [-K dtb] [-D dtc_options]"
-			" [-f fit-image.its|-F] fit-image\n", params.cmdname);
+			" [ -c <comment>] [-f fit-image.its|-F] fit-image\n",
+			params.cmdname);
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
tools/mkimage.h +1 -0
index 41bec21..4391ca8 100644
@@ -77,6 +77,7 @@ struct mkimage_params {
 	char *cmdname;
 	const char *keydir;	/* Directory holding private keys */
 	const char *keydest;	/* Destination .dtb for public key */
+	const char *comment;	/* Comment to add to signature node */
 };
 
 /*
Signature · 1 line
1.7.7.3
#66 lore raw

RFC PATCH 39/44 mkimage: Add -c option to specify a comment for key signing

Dear Simon Glass,

Quoted 5 lines

When signing an image, it is useful to add some details about which tool or person is authorising the signing. Add a comment field which can take care of miscellaneous requirements.

Best regards,
Marek Vasut

#67 lore raw

RFC PATCH 40/44 mkimage: Add -r option to specify keys that must be verified

In reply to Simon Glass

Normally, multiple public keys can be provided and U-Boot is not required to use all of them for verification. This is because some images may not be signed, or may be optionally signed.

But we still need a mechanism to determine when a key must be used. This feature cannot be implemented in the FIT itself, since anyone could change it to mark a key as optional. The requirement for key verification must go in with the public keys, in a place that is protected from modification.

Add a -r option which tells mkimage to mark all keys that it uses for signing as 'required'.

If some keys are optional and some are required, run mkimage several times (perhaps with different key directories if some keys are very secret) using the -F flag to update an existing FIT.

---
 doc/mkimage.1     |    6 ++++++
 tools/fit_image.c |    5 +++--
 tools/mkimage.c   |    7 +++++--
 tools/mkimage.h   |    1 +
 4 files changed, 15 insertions(+), 4 deletions(-)
doc/mkimage.1 +6 -0
index b67a351..14374da 100644
@@ -133,6 +133,12 @@ the corresponding public key is written into this file for for run-time
 verification. Typically the file here is the device tree binary used by
 CONFIG_OF_CONTROL in U-Boot.
 
+.TP
+.BI "\-r
+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).
+
 .SH EXAMPLES
 
 List image information:
tools/fit_image.c +3 -2
index 82f1597..0b9f091 100644
@@ -153,8 +153,9 @@ static int fit_handle_file (struct mkimage_params *params)
 
 	/* set hashes for images in the blob */
 	if (fit_add_verification_data(params->keydir,
-			dest_blob, ptr, params->comment, 0)) {
-		fprintf (stderr, "%s Can't add hashes to FIT blob",
+			dest_blob, ptr, params->comment,
+			params->require_keys)) {
+		fprintf(stderr, "%s Can't add hashes to FIT blob\n",
 				params->cmdname);
 		goto err_add_hashes;
 	}
tools/mkimage.c +5 -2
index d6e47a5..8af84ce 100644
@@ -270,6 +270,9 @@ main (int argc, char **argv)
 					usage ();
 				params.imagename = *++argv;
 				goto NXTARG;
+			case 'r':
+				params.require_keys = 1;
+				break;
 			case 'R':
 				if (--argc <= 0)
 					usage();
@@ -641,8 +644,8 @@ usage ()
 			 "          -x ==> set XIP (execute in place)\n",
 		params.cmdname);
 	fprintf(stderr, "       %s [-k keydir] [-K dtb] [-D dtc_options]"
-			" [ -c <comment>] [-f fit-image.its|-F] fit-image\n",
-			params.cmdname);
+			" [ -c <comment>] [-f fit-image.its|-F] [-r]"
+			" fit-image\n", params.cmdname);
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
tools/mkimage.h +1 -0
index 4391ca8..d82be17 100644
@@ -78,6 +78,7 @@ struct mkimage_params {
 	const char *keydir;	/* Directory holding private keys */
 	const char *keydest;	/* Destination .dtb for public key */
 	const char *comment;	/* Comment to add to signature node */
+	int require_keys;	/* 1 to mark signing keys as 'required' */
 };
 
 /*
Signature · 1 line
1.7.7.3
#68 lore raw

RFC PATCH 40/44 mkimage: Add -r option to specify keys that must be verified

Dear Simon Glass,

Quoted 10 lines

Normally, multiple public keys can be provided and U-Boot is not required to use all of them for verification. This is because some images may not be signed, or may be optionally signed.

But we still need a mechanism to determine when a key must be used. This feature cannot be implemented in the FIT itself, since anyone could change it to mark a key as optional. The requirement for key verification must go in with the public keys, in a place that is protected from modification.

Quoted 8 lines

Add a -r option which tells mkimage to mark all keys that it uses for signing as 'required'.

If some keys are optional and some are required, run mkimage several times (perhaps with different key directories if some keys are very secret) using the -F flag to update an existing FIT.

Best regards,
Marek Vasut

#69 lore raw

RFC PATCH 41/44 libfdt: Add fdt_find_regions()

In reply to Simon Glass

Add a function to find regions in device tree given a list of nodes to include and properties to exclude.

See the header file for full documentation.

---
 include/libfdt.h     |   64 +++++++++++++++++++++++++
 lib/libfdt/fdt_wip.c |  129 ++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+), 0 deletions(-)
include/libfdt.h +64 -0
index 0dfb8a0..c765abe 100644
@@ -1492,4 +1492,68 @@ int fdt_del_node(void *fdt, int nodeoffset);
 
 const char *fdt_strerror(int errval);
 
+struct fdt_region {
+	int offset;
+	int size;
+};
+
+/**
+ * fdt_find_regions() - find regions in device tree
+ *
+ * Given a list of nodes to include and properties to exclude, find
+ * the regions of the device tree which describe those included parts.
+ *
+ * The intent is to get a list of regions which will be invariant provided
+ * those parts are invariant. For example, if you request a list of regions
+ * for all nodes but exclude the property "data", then you will get the
+ * same region contents regardless of any change to "data" properties.
+ *
+ * This function can be used to produce a byte-stream to send to a hashing
+ * function to verify that critical parts of the FDT have not changed.
+ *
+ * Nodes which are given in 'inc' are included in the region list, as
+ * are the names of the immediate subnodes nodes (but not the properties
+ * or subnodes of those subnodes).
+ *
+ * For eaxample "/" means to include the root node, all root properties
+ * and the FDT_BEGIN_NODE and FDT_END_NODE of all subnodes of /. The latter
+ * ensures that we capture the names of the subnodes. In a hashing situation
+ * it prevents the root node from changing at all Any change to non-excluded
+ * properties, names of subnodes or number of subnodes would be detected.
+ *
+ * When used with FITs this provides the ability to hash and sign parts of
+ * the FIT based on different configurations in the FIT. Then it is
+ * impossible to change anything about that configuration (include images
+ * attached to the configuration), but it may be possible to add new
+ * configurations, new images or new signatures within the existing
+ * framework.
+ *
+ * Adding new properties to a device tree may result in the string table
+ * being extended (if the new property names are different from those
+ * already added). This function can optionally include a region for
+ * the string table so that this can be part of the hash too.
+ *
+ * The device tree header is not included in the list.
+ *
+ * @fdt:	Device tree to check
+ * @inc:	List of node paths to included
+ * @inc_count:	Number of node paths in list
+ * @exc_prop:	List of properties names to exclude
+ * @exc_prop_count:	Number of properties in exclude list
+ * @region:	Returns list of regions
+ * @max_region:	Maximum length of region list
+ * @path:	Pointer to a temporary string for the function to use for
+ *		building path names
+ * @path_len:	Length of path, must be large enough to hold the longest
+ *		path in the tree
+ * @add_string_tab:	1 to add a region for the string table
+ * @return number of regions in list. If this is >max_regions then the
+ * region array was exhausted. You should increase max_regions and try
+ * the call again.
+ */
+int fdt_find_regions(const void *fdt, char * const inc[], int inc_count,
+		     char * const exc_prop[], int exc_prop_count,
+		     struct fdt_region region[], int max_regions,
+		     char *path, int path_len, int add_string_tab);
+
 #endif /* _LIBFDT_H */
lib/libfdt/fdt_wip.c +129 -0

132 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#70 lore raw

RFC PATCH 42/44 image: Add support for signing of FIT configurations

In reply to Simon Glass

While signing images is useful, it does not provide complete protection against several types of attack. For example, it it possible to create a FIT with the same signed images, but with the configuration changed such that a different one is selected (mix and match attack). It is also possible to substitute a signed image from an older FIT version into a newer FIT (roll-back attack).

Add support for signing of FIT configurations using the libfdt's region support.

Please see doc/uImage.FIT/signature.txt for more information.

---
 common/cmd_bootm.c              |   12 ++
 common/image-sig.c              |  212 +++++++++++++++++++++++-
 doc/uImage.FIT/sign-configs.its |   45 +++++
 doc/uImage.FIT/signature.txt    |  167 ++++++++++++++++++-
 include/image.h                 |   15 ++
 tools/image-host.c              |  350 ++++++++++++++++++++++++++++++++++++++-
 6 files changed, 798 insertions(+), 3 deletions(-)
 create mode 100644 doc/uImage.FIT/sign-configs.its
common/cmd_bootm.c +12 -0
index cac9e53..d71ffb5 100644
@@ -972,6 +972,18 @@ static const void *boot_get_kernel(cmd_tbl_t *cmdtp, int flag, int argc,
 								NULL);
 			printf("   Using '%s' configuration\n",
 				images->fit_uname_cfg);
+			if (IMAGE_ENABLE_VERIFY && images->verify) {
+				puts("   Verifying Hash Integrity ... ");
+				if (!fit_config_verify(fit_hdr,
+						cfg_noffset)) {
+					puts("Bad Data Hash\n");
+					bootstage_error(
+						BOOTSTAGE_ID_FIT_CHECK_HASH);
+					return NULL;
+				}
+				puts("OK\n");
+			}
+
 			bootstage_mark(BOOTSTAGE_ID_FIT_CONFIG);
 
 			os_noffset = fit_conf_get_kernel_node(fit_hdr,
common/image-sig.c +211 -1

227 lines not on this page · raw message

doc/uImage.FIT/sign-configs.its new file +45 -0

45 lines not on this page · raw message

doc/uImage.FIT/signature.txt +166 -1

180 lines not on this page · raw message

include/image.h +15 -0
index b8aea83..ad3e4b8 100644
@@ -633,6 +633,7 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
 			      const char *comment, int require_keys);
 
 int fit_image_verify(const void *fit, int noffset);
+int fit_config_verify(const void *fit, int conf_noffset);
 int fit_all_image_verify(const void *fit);
 int fit_image_check_os(const void *fit, int noffset, uint8_t os);
 int fit_image_check_arch(const void *fit, int noffset, uint8_t arch);
@@ -801,6 +802,20 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset,
 int fit_image_check_sig(const void *fit, int noffset, const void *data,
 		size_t size, int required_keynode, char **err_msgp);
 
+/**
+ * fit_region_make_list() - Make a list of regions to hash
+ *
+ * Given a list of FIT regions (offset, size) provided by libfdt, create
+ * a list of regions (void *, size) for use by the signature creationg
+ * and verification code.
+ *
+ * @fit:		FIT image to process
+ * @fdt_regions:	Regions as returned by libfdt
+ * @count:		Number of regions returned by libfdt
+ * @return pointer to list of regions, or NULL if out of memory
+ */
+struct image_region *fit_region_make_list(const void *fit,
+		struct fdt_region *fdt_regions, int count);
 
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
tools/image-host.c +349 -1

364 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#71 lore raw

RFC PATCH 43/44 Add verified boot information and test

In reply to Simon Glass

Add a description of how to implement verified boot using signed FIT images, and a simple test which verifies operation on sandbox.

---
 doc/uImage.FIT/verified-boot.txt |  104 ++++++++++++++++++++++++++++++++
 test/vboot/.gitignore            |    3 +
 test/vboot/sandbox-kernel.dts    |    7 ++
 test/vboot/sandbox-u-boot.dts    |    7 ++
 test/vboot/sign-configs.its      |   45 ++++++++++++++
 test/vboot/sign-images.its       |   42 +++++++++++++
 test/vboot/vboot_test.sh         |  122 ++++++++++++++++++++++++++++++++++++++
 7 files changed, 330 insertions(+), 0 deletions(-)
 create mode 100644 doc/uImage.FIT/verified-boot.txt
 create mode 100644 test/vboot/.gitignore
 create mode 100644 test/vboot/sandbox-kernel.dts
 create mode 100644 test/vboot/sandbox-u-boot.dts
 create mode 100644 test/vboot/sign-configs.its
 create mode 100644 test/vboot/sign-images.its
 create mode 100755 test/vboot/vboot_test.sh
doc/uImage.FIT/verified-boot.txt new file +104 -0
new file mode 100644
index 0000000..9fff66d
@@ -0,0 +1,104 @@
+U-Boot Verified Boot
+====================
+
+Introduction
+------------
+Verified boot here means the verification of all software loaded into a
+machine during the boot process to ensure that it is authorised and correct
+for that machine.
+
+Verified boot extends from the moment of system reset to as far as you wish
+into the boot process. An example might be loading U-Boot from read-only
+memory, then loading a signed kernel, then using the kernel's dm-verity
+driver to mount a signed root filesystem.
+
+A key point is that it is possible to field-upgrade the software on machines
+which use verified boot. Since the machine will only run software that has
+been correctly signed, it is safe to read software from an updatable medium.
+It is also possible to add a secondary signed firmware image, in read-write
+memory, so that firmware can easily be upgraded in a secure manner.
+
+
+Signing
+-------
+Verified boot uses cryptographic algorithms to 'sign' software images.
+Images are signed using a private key known only to the signer, but can
+be verified using a public key. As its name suggests the public key can be
+made available without risk to the verification process. The private and
+public keys are mathematically related. For more information on how this
+works look up "public key cryptography" and "RSA" (a particular algorithm).
+
+The signing and verification process looks something like this:
+
+
+      Signing                                      Verification
+      =======                                      ============
+
+ +--------------+                   *
+ | RSA key pair |                   *             +---------------+
+ | .key  .crt   |                   *             | Public key in |
+ +--------------+       +------> public key ----->| trusted place |
+       |                |           *             +---------------+
+       |                |           *                    |
+       v                |           *                    v
+   +---------+          |           *              +--------------+
+   |         |----------+           *              |              |
+   | signer  |                      *              |    U-Boot    |
+   |         |----------+           *              |  signature   |--> yes/no
+   +---------+          |           *              | verification |
+      ^                 |           *              |              |
+      |                 |           *              +--------------+
+      |                 |           *                    ^
+ +----------+           |           *                    |
+ | Software |           +----> signed image -------------+
+ |  image   |                       *
+ +----------+                       *
+
+
+The signature algorithm relies only on the public key to do its work. Using
+this key it checks the signature that it finds in the image. If it verifies
+then we know that the image is OK.
+
+The public key from the signer allows us to verify and therefore trust
+software from updatable memory.
+
+It is critical that the public key be secure and cannot be tampered with.
+It can be stored in read-only memory, or perhaps protected by other on-chip
+crypto provided by some modern SOCs. If the public key can ben changed, then
+the verification is worthless.
+
+
+Chaining Images
+---------------
+The above method works for a signer providing images to a run-time U-Boot.
+It is also possible to extend this scheme to a second level, like this:
+
+1. Master private key is used by the signer to sign a first-stage image.
+2. Master public key is placed in read-only memory.
+2. Secondary private key is created and used to sign second-stage images.
+3. Secondary public key is placed in first stage images
+4. We use the master public key to verify the first-stage image. We then
+use the secondary public key in the first-stage image to verify the second-
+state image.
+5. This chaining process can gon indefinitely. It is recommended to use a
+different key at each stage, so that a compromise in one place will not
+affect the whole change.
+
+
+Flattened Image Tree (FIT)
+--------------------------
+The FIT format is alreay widely used in U-Boot. It is a flattened device
+tree (FDT) in a particular format, with images containied within. FITs
+include hashes to verify images, so it is relatively straightforward to
+add signatures as well.
+
+The public key can be stored in U-Boot's CONFIG_OF_CONTROL device tree in
+a standard place. Then when a FIT it loaded it can be verified using that
+pulic key. Multiple keys and multiple signatures are supported.
+
+See signature.txt for more information.
+
+
+Simon Glass
+sjg at chromium.org
+1-1-13
test/vboot/.gitignore new file +3 -0
new file mode 100644
index 0000000..4631242
@@ -0,0 +1,3 @@
+/*.dtb
+/test.fit
+/dev-keys
test/vboot/sandbox-kernel.dts new file +7 -0
new file mode 100644
index 0000000..a1e853c
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
test/vboot/sandbox-u-boot.dts new file +7 -0
new file mode 100644
index 0000000..a1e853c
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
test/vboot/sign-configs.its new file +45 -0

45 lines not on this page · raw message

test/vboot/sign-images.its new file +42 -0

42 lines not on this page · raw message

test/vboot/vboot_test.sh new file +122 -0

122 lines not on this page · raw message

Signature · 1 line
1.7.7.3
#72 lore raw

RFC PATCH 44/44 WIP: sandbox: config: Add test config for verified boot

In reply to Simon Glass

This adds a test command to sandbox so that it can be used for running verified boot tests.

This patch is not intended to be merged.

---
 include/configs/sandbox.h |   14 +++++++++++++-
 1 files changed, 13 insertions(+), 1 deletions(-)
include/configs/sandbox.h +13 -1
index fb1c583..baf892a 100644
@@ -24,6 +24,7 @@
 
 #define CONFIG_NR_DRAM_BANKS	1
 #define CONFIG_DRAM_SIZE	(128 << 20)
+#define CONFIG_SYS_TEXT_BASE	0
 
 /* Number of bits in a C 'long' on this architecture */
 #define CONFIG_SANDBOX_BITS_PER_LONG	64
@@ -107,8 +108,19 @@
 
 #define CONFIG_BOOTARGS ""
 
+#define CONFIG_SANDBOX_ENV \
+	"test=sb load host 0 100 test.fit; " \
+		"fdt addr 100;" \
+		"bootm 100;" \
+		"reset;" \
+		"\0"
+
 #define CONFIG_EXTRA_ENV_SETTINGS	"stdin=serial\0" \
 					"stdout=serial\0" \
-					"stderr=serial\0"
+					"stderr=serial\0" \
+					CONFIG_SANDBOX_ENV
+
+#define CONFIG_BOOTCOMMAND	"run test"
+#define CONFIG_BOOTDELAY	0		/* -1 to disable auto boot */
 
 #endif
Signature · 1 line
1.7.7.3
#73 lore raw

cover RFC: Verified boot implementation based on FIT

In reply to Simon Glass

Hi,

Quoted 34 lines · Simon Glass

This series implemented a verified boot system based around FIT images as discussed on the U-Boot mailing list, including on this thread:

http://permalink.gmane.org/gmane.comp.boot-loaders.u-boot/147830

RSA is used to implement the encryption. Images are signed by mkimage using private keys created by the user. Public keys are written into U-Boot control FDT (CONFIG_OF_CONTROL) for access by bootm etc. at run-time. The control FDT must be stored in a secure place where it cannot be changed after manufacture. Some notes are provided in the documentaion on how this can be achieved.

When images are loaded, they are verified with the public keys.

Some minor restructuring of the image code is included in this series, since we now support signatures as well as hashes.

It is important to have a test framework for this series. For this, sandbox is used, and a script is provided which signs images and gets sandbox to load them using a script, to check that all is well. So some of the patches here release to adding image support for sandbox.

This series is not quite in final form since it still needs rollback support, using a TPM or some other mechanism to make sure that an attacker cannot boot your system with an old image that has been compromised.

Also a few more tests are needed to check that image corruption has the desired effect, some proofreading is required, another review of error checking, etc.

This series relies on two previous series: sandbox filesystem and sandbox memory. Without these, it is (at best) not possible to run the verified boot test on sandbox.

Quoted 7 lines

This series and its dependencies are available at:

   http://git.denx.de/u-boot-x86.git

in the branch 'vboot'.

Comments welcome.

I know are few people are trying this out. Are there any comments at this stage?

Che-Liang Chiou has posted a patch for the TPM command that are referenced above. These include rollback support.

http://patchwork.ozlabs.org/patch/224163/

I intend to respin this soon to tidy up a few issues.

Quoted 120 lines

Simon Glass (44):
sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT
bootstage: Don't build for HOSTCC
mkimage: Move ARRAY_SIZE to header file
libfdt: Add fdt_next_subnode() to permit easy subnode iteration
image: Move timestamp #ifdefs to header file
image: Export fit_check_ramdisk()
image: Split FIT code into new image-fit.c
image: Move HOSTCC image code to tools/
image: Split hash node processing into its own function
image: Convert fit_image_hash_set_value() to static, and rename
image: Rename fit_image_check_hashes() to fit_image_verify()
image: Move hash checking into its own functions
image: Move error! string to common place
image: Export fit_conf_get_prop_node()
image: Rename fit_add_hashes() to fit_add_verification_data()
image: Rename hash printing to fit_image_print_verification_data()
sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file
fdt: Add a parameter to fdt_valid()
Add getenv_hex() to return an environment variable as hex
fdt: Allow fdt command to check and update control FDT
sandbox: fdt: Support fdt command for sandbox
env: Fix minor comment typos in cmd_nvedit
fdt: Skip checking FDT if the pointer is NULL
Revert "fdt- Tell the FDT library where the device tree is" Add stdarg to vsprintf.h
Add minor updates to README.fdt-control
hash: Add a way to calculate a hash for any algortihm
sandbox: config: Enable FIT signatures with RSA
sandbox: Provide a way to map from host RAM to U-Boot RAM
sandbox: image: Add support for booting images in sandbox
image: Add signing infrastructure
image: Support signing of images
image: Verify signatures in FIT images
image: Add RSA support for image signing
mkimage: Put FIT loading in function and tidy error handling
mkimage: Add -k option to specify key directory
mkimage: Add -K to write public keys to an FDT blob
mkimage: Add -F option to modify an existing .fit file
mkimage: Add -c option to specify a comment for key signing
mkimage: Add -r option to specify keys that must be verified
libfdt: Add fdt_find_regions()
image: Add support for signing of FIT configurations Add verified boot information and test
WIP: sandbox: config: Add test config for verified boot

 Makefile                         |    1 +
 README                           |   15 +
 arch/sandbox/cpu/cpu.c           |    5 +
 arch/sandbox/cpu/start.c         |    7 +
 arch/sandbox/include/asm/io.h    |    2 +
 arch/sandbox/include/asm/state.h |    1 +
 arch/sandbox/lib/board.c         |   42 +-
 common/Makefile                  |    2 +
 common/cmd_bootm.c               |   37 +-
 common/cmd_fdt.c                 |   83 ++-
 common/cmd_fpga.c                |    2 +-
 common/cmd_nvedit.c              |   19 +-
 common/cmd_source.c              |    2 +-
 common/cmd_ximg.c                |    2 +-
 common/hash.c                    |   22 +
 common/image-fit.c               | 1544 +++++++++++++++++++++++++++++++++++
 common/image-sig.c               |  407 +++++++++
 common/image.c                   | 1677 +-------------------------------------
 common/main.c                    |    8 -
 common/update.c                  |    2 +-
 config.mk                        |    1 +
 doc/README.fdt-control           |   13 +-
 doc/mkimage.1                    |   73 ++-
 doc/uImage.FIT/sign-configs.its  |   45 +
 doc/uImage.FIT/sign-images.its   |   42 +
 doc/uImage.FIT/signature.txt     |  376 +++++++++
 doc/uImage.FIT/verified-boot.txt |  104 +++
 include/bootstage.h              |    5 +-
 include/common.h                 |   18 +
 include/configs/sandbox.h        |   20 +-
 include/hash.h                   |   15 +
 include/image.h                  |  213 +++++-
 include/libfdt.h                 |   81 ++
 include/rsa.h                    |  108 +++
 include/vsprintf.h               |    2 +
 lib/fdtdec.c                     |    3 +-
 lib/libfdt/fdt.c                 |   12 +
 lib/libfdt/fdt_wip.c             |  129 +++
 lib/rsa/Makefile                 |   46 +
 lib/rsa/rsa-sign.c               |  454 +++++++++++
 lib/rsa/rsa-verify.c             |  374 +++++++++
 test/vboot/.gitignore            |    3 +
 test/vboot/sandbox-kernel.dts    |    7 +
 test/vboot/sandbox-u-boot.dts    |    7 +
 test/vboot/sign-configs.its      |   45 +
 test/vboot/sign-images.its       |   42 +
 test/vboot/vboot_test.sh         |  122 +++
 tools/Makefile                   |   21 +-
 tools/aisimage.c                 |    1 -
 tools/fit_image.c                |  134 ++-
 tools/image-host.c               |  727 +++++++++++++++++
 tools/mkimage.c                  |   27 +-
 tools/mkimage.h                  |    6 +
 53 files changed, 5386 insertions(+), 1770 deletions(-)
 create mode 100644 common/image-fit.c
 create mode 100644 common/image-sig.c
 create mode 100644 doc/uImage.FIT/sign-configs.its
 create mode 100644 doc/uImage.FIT/sign-images.its
 create mode 100644 doc/uImage.FIT/signature.txt
 create mode 100644 doc/uImage.FIT/verified-boot.txt
 create mode 100644 include/rsa.h
 create mode 100644 lib/rsa/Makefile
 create mode 100644 lib/rsa/rsa-sign.c
 create mode 100644 lib/rsa/rsa-verify.c
 create mode 100644 test/vboot/.gitignore
 create mode 100644 test/vboot/sandbox-kernel.dts
 create mode 100644 test/vboot/sandbox-u-boot.dts
 create mode 100644 test/vboot/sign-configs.its
 create mode 100644 test/vboot/sign-images.its
 create mode 100755 test/vboot/vboot_test.sh
 create mode 100644 tools/image-host.c
Quoted 3 lines

--
1.7.7.3

Regards,
Simon