All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
@ 2013-03-18 23:51 Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 01/45] sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT Simon Glass
                   ` (46 more replies)
  0 siblings, 47 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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. The implementation is fairly
efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
to SPL size which is manageable on modern SoCs.

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 related to adding image support for sandbox. A follow-on series is
somewhat more agressive in further refactoring the FIT image support to
clean it up improve maintainability.

Rollback prevention has been added in a separate TPM patch. This ensures
that an attacker cannot boot your system with an old image that has been
compromised. Support for this is not built into bootm, but instead must
be scripted in U-Boot. It is possible that a standard scheme for this could
be devised by adding version number tags to the signing procedure. However
scripts do provide more flexibility. The TPM patch is here:

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

This series is available at:

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

in the branch 'vboot'.

I have received a number of off-list comments - please do copy the list when
replying so that everyone can see your comments.

Changes in v2:
- Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
- Add comment about why mkimage needs to open FIT with O_RDWR
- Add new patch to control FIT image printing in SPL
- Add new patch to remove #ifdefs in image-fit.c
- Add sanity checks on key sizes in RSA (improves security)
- Adjust how signing enable works in image.h
- Adjust mkimage help to separate out signing options
- Allow the control FDT to be set even if there is currently no control FDT
- Avoid using malloc in RSA routines (for smaller SPL code size)
- Build signing support unconditionally in mkimage
- Change hash_block() to use an unsigned int len
- Clarify use of output_size parameter to hash_block()
- Correct bug in setting control FDT
- Fix FDT error handling in fit_image_write_sig()
- Fix checkpatch checks about parenthesis alignment
- Fix checkpatch warnings about space after cast
- Fix checkpatch warnings about split strings
- Fix line continuation problem
- Fix spelling of multiply in rsa-verify.c
- Fix spelling of quite
- Fix typo "os defined" -> "is defined"
- Move sandbox's command list patch from a later series
- Only build RSA support into mkimage if CONFIG_RSA is defined
- Put err_msgp strings on a single line
- Put params before description in fit_conf_get_prop_node() comment
- Rebase on previous patches
- Rebase to use updated fdt_valid() function
- Rename commit message to say "function" instead of "function"
- Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
- Revert the whole change including the set_working_fdt_addr() part
- Support RSA library version without ERR_remove_thread_state()
- Tweak tools/Makefile to make image signing optional
- Update README to fix typos
- Update README to fix typos and clarify some points
- Use U-Boot's -c option instead of hard-coding a boot script
- Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)
- Use stack instead of calloc() within U-Boot's signature verification code
- fdt_valid() sets the FDT pointer to NULL on error, to simplify callers
- gd->fdt_blob is now available on all archs (generic board landed)

Simon Glass (45):
  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 function
  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: 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
  image: Remove remaining #ifdefs in image-fit.c
  image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
  sandbox: Allow -c argument to provide a command list
  Add verified boot information and test

 Makefile                         |    1 +
 README                           |   21 +
 arch/sandbox/cpu/cpu.c           |    5 +
 arch/sandbox/cpu/start.c         |    9 +-
 arch/sandbox/include/asm/io.h    |    2 +
 arch/sandbox/include/asm/state.h |    1 +
 arch/sandbox/lib/board.c         |   38 +-
 common/Makefile                  |    2 +
 common/cmd_bootm.c               |   37 +-
 common/cmd_fdt.c                 |   87 +-
 common/cmd_fpga.c                |    2 +-
 common/cmd_nvedit.c              |   19 +-
 common/cmd_source.c              |    2 +-
 common/cmd_ximg.c                |    2 +-
 common/hash.c                    |   23 +
 common/image-fit.c               | 1533 ++++++++++++++++++++++++++++++++++
 common/image-sig.c               |  430 ++++++++++
 common/image.c                   | 1686 +-------------------------------------
 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     |  382 +++++++++
 doc/uImage.FIT/verified-boot.txt |  104 +++
 include/bootstage.h              |    5 +-
 include/common.h                 |   18 +
 include/configs/sandbox.h        |    6 +
 include/hash.h                   |   22 +
 include/image.h                  |  265 +++++-
 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                 |   48 ++
 lib/rsa/rsa-sign.c               |  460 +++++++++++
 lib/rsa/rsa-verify.c             |  385 +++++++++
 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         |  126 +++
 tools/Makefile                   |   23 +-
 tools/aisimage.c                 |    1 -
 tools/fit_image.c                |  136 +--
 tools/image-host.c               |  722 ++++++++++++++++
 tools/mkimage.c                  |   36 +-
 tools/mkimage.h                  |    6 +
 53 files changed, 5485 insertions(+), 1783 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

-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 01/45] sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 02/45] bootstage: Don't build for HOSTCC Simon Glass
                   ` (45 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

Enable these options to use FITs on sandbox.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 include/configs/sandbox.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 406da43..67d788a 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -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
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 02/45] bootstage: Don't build for HOSTCC
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 01/45] sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 03/45] mkimage: Move ARRAY_SIZE to header file Simon Glass
                   ` (44 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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)

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Fix line continuation problem

 include/bootstage.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/include/bootstage.h b/include/bootstage.h
index 3b2216b..4df03ae 100644
--- a/include/bootstage.h
+++ b/include/bootstage.h
@@ -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 */
 
 /**
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 03/45] mkimage: Move ARRAY_SIZE to header file
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 01/45] sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 02/45] bootstage: Don't build for HOSTCC Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration Simon Glass
                   ` (43 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Marek Vasut <marex@denx.de>
---
Changes in v2: None

 tools/aisimage.c | 1 -
 tools/mkimage.h  | 2 ++
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/tools/aisimage.c b/tools/aisimage.c
index c645708..659df8c 100644
--- a/tools/aisimage.c
+++ b/tools/aisimage.c
@@ -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;
 
diff --git a/tools/mkimage.h b/tools/mkimage.h
index ea45f5c..e07a615 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -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"
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (2 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 03/45] mkimage: Move ARRAY_SIZE to header file Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 05/45] image: Move timestamp #ifdefs to header file Simon Glass
                   ` (42 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 include/libfdt.h | 17 +++++++++++++++++
 lib/libfdt/fdt.c | 12 ++++++++++++
 2 files changed, 29 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index fc7f75b..50c90d6 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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                                                  */
 /**********************************************************************/
diff --git a/lib/libfdt/fdt.c b/lib/libfdt/fdt.c
index 387e354..cd86811 100644
--- a/lib/libfdt/fdt.c
+++ b/lib/libfdt/fdt.c
@@ -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;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 05/45] image: Move timestamp #ifdefs to header file
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (3 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 06/45] image: Export fit_check_ramdisk() Simon Glass
                   ` (41 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Marek Vasut <marex@denx.de>
---
Changes in v2: None

 common/image.c  | 50 +++++++++++++++++++++-----------------------------
 include/image.h |  8 ++++++++
 2 files changed, 29 insertions(+), 29 deletions(-)

diff --git a/common/image.c b/common/image.c
index 6afbb40..d01b8f6 100644
--- a/common/image.c
+++ b/common/image.c
@@ -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>
@@ -162,10 +160,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 */
 /*****************************************************************************/
@@ -311,10 +305,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);
@@ -523,8 +517,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;
@@ -537,7 +531,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
@@ -1910,9 +1904,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 = "";
@@ -1928,14 +1920,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);
@@ -3046,13 +3038,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) {
diff --git a/include/image.h b/include/image.h
index 8e285f9..32a961c 100644
--- a/include/image.h
+++ b/include/image.h
@@ -332,6 +332,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
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 06/45] image: Export fit_check_ramdisk()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (4 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 05/45] image: Move timestamp #ifdefs to header file Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 07/45] image: Split FIT code into new image-fit.c Simon Glass
                   ` (40 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2: None

 common/image.c  | 9 ++-------
 include/image.h | 3 +++
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/common/image.c b/common/image.c
index d01b8f6..af66138 100644
--- a/common/image.c
+++ b/common/image.c
@@ -49,14 +49,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
@@ -3363,8 +3358,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, "   ");
 
diff --git a/include/image.h b/include/image.h
index 32a961c..880ce07 100644
--- a/include/image.h
+++ b/include/image.h
@@ -632,6 +632,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)
 {
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 07/45] image: Split FIT code into new image-fit.c
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (5 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 06/45] image: Export fit_check_ramdisk() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 08/45] image: Move HOSTCC image code to tools/ Simon Glass
                   ` (39 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Fix checkpatch checks about parenthesis alignment

 common/Makefile    |    1 +
 common/image-fit.c | 1636 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 common/image.c     | 1602 --------------------------------------------------
 tools/Makefile     |    2 +
 4 files changed, 1639 insertions(+), 1602 deletions(-)
 create mode 100644 common/image-fit.c

diff --git a/common/Makefile b/common/Makefile
index 08af1a8..36b4ffc 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -227,6 +227,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
 
diff --git a/common/image-fit.c b/common/image-fit.c
new file mode 100644
index 0000000..3ba1ad3
--- /dev/null
+++ b/common/image-fit.c
@@ -0,0 +1,1636 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <image.h>
+#include <time.h>
+#else
+#include <common.h>
+#endif /* !USE_HOSTCC*/
+
+#include <bootstage.h>
+#include <sha1.h>
+#include <u-boot/crc.h>
+#include <u-boot/md5.h>
+
+/*****************************************************************************/
+/* New uImage format routines */
+/*****************************************************************************/
+#ifndef USE_HOSTCC
+static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
+		ulong *addr, const char **name)
+{
+	const char *sep;
+
+	*addr = addr_curr;
+	*name = NULL;
+
+	sep = strchr(spec, sepc);
+	if (sep) {
+		if (sep - spec > 0)
+			*addr = simple_strtoul(spec, NULL, 16);
+
+		*name = sep + 1;
+		return 1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_parse_conf - parse FIT configuration spec
+ * @spec: input string, containing configuration spec
+ * @add_curr: current image address (to be used as a possible default)
+ * @addr: pointer to a ulong variable, will hold FIT image address of a given
+ * configuration
+ * @conf_name double pointer to a char, will hold pointer to a configuration
+ * unit name
+ *
+ * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
+ * where <addr> is a FIT image address that contains configuration
+ * with a <conf> unit name.
+ *
+ * Address part is optional, and if omitted default add_curr will
+ * be used instead.
+ *
+ * returns:
+ *     1 if spec is a valid configuration string,
+ *     addr and conf_name are set accordingly
+ *     0 otherwise
+ */
+int fit_parse_conf(const char *spec, ulong addr_curr,
+		ulong *addr, const char **conf_name)
+{
+	return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
+}
+
+/**
+ * fit_parse_subimage - parse FIT subimage spec
+ * @spec: input string, containing subimage spec
+ * @add_curr: current image address (to be used as a possible default)
+ * @addr: pointer to a ulong variable, will hold FIT image address of a given
+ * subimage
+ * @image_name: double pointer to a char, will hold pointer to a subimage name
+ *
+ * fit_parse_subimage() expects subimage spec in the for of
+ * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
+ * subimage with a <subimg> unit name.
+ *
+ * Address part is optional, and if omitted default add_curr will
+ * be used instead.
+ *
+ * returns:
+ *     1 if spec is a valid subimage string,
+ *     addr and image_name are set accordingly
+ *     0 otherwise
+ */
+int fit_parse_subimage(const char *spec, ulong addr_curr,
+		ulong *addr, const char **image_name)
+{
+	return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
+}
+#endif /* !USE_HOSTCC */
+
+static void fit_get_debug(const void *fit, int noffset,
+		char *prop_name, int err)
+{
+	debug("Can't get '%s' property from FIT 0x%08lx, node: offset %d, name %s (%s)\n",
+	      prop_name, (ulong)fit, noffset, fit_get_name(fit, noffset, NULL),
+	      fdt_strerror(err));
+}
+
+/**
+ * fit_print_contents - prints out the contents of the FIT format image
+ * @fit: pointer to the FIT format image header
+ * @p: pointer to prefix string
+ *
+ * fit_print_contents() formats a multi line FIT image contents description.
+ * The routine prints out FIT image properties (root node level) follwed by
+ * the details of each component image.
+ *
+ * returns:
+ *     no returned results
+ */
+void fit_print_contents(const void *fit)
+{
+	char *desc;
+	char *uname;
+	int images_noffset;
+	int confs_noffset;
+	int noffset;
+	int ndepth;
+	int count = 0;
+	int ret;
+	const char *p;
+	time_t timestamp;
+
+#ifdef USE_HOSTCC
+	p = "";
+#else
+	p = "   ";
+#endif
+
+	/* Root node properties */
+	ret = fit_get_desc(fit, 0, &desc);
+	printf("%sFIT description: ", p);
+	if (ret)
+		printf("unavailable\n");
+	else
+		printf("%s\n", desc);
+
+	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);
+	if (images_noffset < 0) {
+		printf("Can't find images parent node '%s' (%s)\n",
+		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
+		return;
+	}
+
+	/* Process its subnodes, print out component images details */
+	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) {
+			/*
+			 * Direct child node of the images parent node,
+			 * i.e. component image node.
+			 */
+			printf("%s Image %u (%s)\n", p, count++,
+			       fit_get_name(fit, noffset, NULL));
+
+			fit_image_print(fit, noffset, p);
+		}
+	}
+
+	/* Find configurations parent node offset */
+	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+	if (confs_noffset < 0) {
+		debug("Can't get configurations parent node '%s' (%s)\n",
+		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
+		return;
+	}
+
+	/* get default configuration unit name from default property */
+	uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
+	if (uname)
+		printf("%s Default Configuration: '%s'\n", p, uname);
+
+	/* Process its subnodes, print out configurations details */
+	for (ndepth = 0, count = 0,
+		noffset = fdt_next_node(fit, confs_noffset, &ndepth);
+	     (noffset >= 0) && (ndepth > 0);
+	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
+		if (ndepth == 1) {
+			/*
+			 * Direct child node of the configurations parent node,
+			 * i.e. configuration node.
+			 */
+			printf("%s Configuration %u (%s)\n", p, count++,
+			       fit_get_name(fit, noffset, NULL));
+
+			fit_conf_print(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
+ * @p: pointer to prefix string
+ *
+ * fit_image_print() lists all mandatory properies for the processed component
+ * image. If present, hash nodes are printed out as well. Load
+ * address for images of type firmware is also printed out. Since the load
+ * address is not mandatory for firmware images, it will be output as
+ * "unavailable" when not present.
+ *
+ * returns:
+ *     no returned results
+ */
+void fit_image_print(const void *fit, int image_noffset, const char *p)
+{
+	char *desc;
+	uint8_t type, arch, os, comp;
+	size_t size;
+	ulong load, entry;
+	const void *data;
+	int noffset;
+	int ndepth;
+	int ret;
+
+	/* Mandatory properties */
+	ret = fit_get_desc(fit, image_noffset, &desc);
+	printf("%s  Description:  ", p);
+	if (ret)
+		printf("unavailable\n");
+	else
+		printf("%s\n", desc);
+
+	fit_image_get_type(fit, image_noffset, &type);
+	printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
+
+	fit_image_get_comp(fit, image_noffset, &comp);
+	printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
+
+	ret = fit_image_get_data(fit, image_noffset, &data, &size);
+
+#ifndef USE_HOSTCC
+	printf("%s  Data Start:   ", p);
+	if (ret)
+		printf("unavailable\n");
+	else
+		printf("0x%08lx\n", (ulong)data);
+#endif
+
+	printf("%s  Data Size:    ", p);
+	if (ret)
+		printf("unavailable\n");
+	else
+		genimg_print_size(size);
+
+	/* Remaining, type dependent properties */
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
+	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
+	    (type == IH_TYPE_FLATDT)) {
+		fit_image_get_arch(fit, image_noffset, &arch);
+		printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
+	}
+
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
+		fit_image_get_os(fit, image_noffset, &os);
+		printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
+	}
+
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
+	    (type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
+		ret = fit_image_get_load(fit, image_noffset, &load);
+		printf("%s  Load Address: ", p);
+		if (ret)
+			printf("unavailable\n");
+		else
+			printf("0x%08lx\n", load);
+	}
+
+	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
+	    (type == IH_TYPE_RAMDISK)) {
+		fit_image_get_entry(fit, image_noffset, &entry);
+		printf("%s  Entry Point:  ", p);
+		if (ret)
+			printf("unavailable\n");
+		else
+			printf("0x%08lx\n", entry);
+	}
+
+	/* 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 */
+			fit_image_print_hash(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 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_get_desc - get node description property
+ * @fit: pointer to the FIT format image header
+ * @noffset: node offset
+ * @desc: double pointer to the char, will hold pointer to the descrption
+ *
+ * fit_get_desc() reads description property from a given node, if
+ * description is found pointer to it is returened in third call argument.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_get_desc(const void *fit, int noffset, char **desc)
+{
+	int len;
+
+	*desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
+	if (*desc == NULL) {
+		fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_get_timestamp - get node timestamp property
+ * @fit: pointer to the FIT format image header
+ * @noffset: node offset
+ * @timestamp: pointer to the time_t, will hold read timestamp
+ *
+ * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
+ * is found and has a correct size its value is retured in third call
+ * argument.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on property read failure
+ *     -2, on wrong timestamp size
+ */
+int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
+{
+	int len;
+	const void *data;
+
+	data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
+		return -1;
+	}
+	if (len != sizeof(uint32_t)) {
+		debug("FIT timestamp with incorrect size of (%u)\n", len);
+		return -2;
+	}
+
+	*timestamp = uimage_to_cpu(*((uint32_t *)data));
+	return 0;
+}
+
+/**
+ * fit_image_get_node - get node offset for component image of a given unit name
+ * @fit: pointer to the FIT format image header
+ * @image_uname: component image node unit name
+ *
+ * fit_image_get_node() finds a component image (withing the '/images'
+ * node) of a provided unit name. If image is found its node offset is
+ * returned to the caller.
+ *
+ * returns:
+ *     image node offset when found (>=0)
+ *     negative number on failure (FDT_ERR_* code)
+ */
+int fit_image_get_node(const void *fit, const char *image_uname)
+{
+	int noffset, images_noffset;
+
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (images_noffset < 0) {
+		debug("Can't find images parent node '%s' (%s)\n",
+		      FIT_IMAGES_PATH, fdt_strerror(images_noffset));
+		return images_noffset;
+	}
+
+	noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
+	if (noffset < 0) {
+		debug("Can't get node offset for image unit name: '%s' (%s)\n",
+		      image_uname, fdt_strerror(noffset));
+	}
+
+	return noffset;
+}
+
+/**
+ * fit_image_get_os - get os id for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @os: pointer to the uint8_t, will hold os numeric id
+ *
+ * fit_image_get_os() finds os property in a given component image node.
+ * If the property is found, its (string) value is translated to the numeric
+ * id which is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
+{
+	int len;
+	const void *data;
+
+	/* Get OS name from property data */
+	data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_OS_PROP, len);
+		*os = -1;
+		return -1;
+	}
+
+	/* Translate OS name to id */
+	*os = genimg_get_os_id(data);
+	return 0;
+}
+
+/**
+ * fit_image_get_arch - get arch id for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @arch: pointer to the uint8_t, will hold arch numeric id
+ *
+ * fit_image_get_arch() finds arch property in a given component image node.
+ * If the property is found, its (string) value is translated to the numeric
+ * id which is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
+{
+	int len;
+	const void *data;
+
+	/* Get architecture name from property data */
+	data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
+		*arch = -1;
+		return -1;
+	}
+
+	/* Translate architecture name to id */
+	*arch = genimg_get_arch_id(data);
+	return 0;
+}
+
+/**
+ * fit_image_get_type - get type id for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @type: pointer to the uint8_t, will hold type numeric id
+ *
+ * fit_image_get_type() finds type property in a given component image node.
+ * If the property is found, its (string) value is translated to the numeric
+ * id which is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
+{
+	int len;
+	const void *data;
+
+	/* Get image type name from property data */
+	data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
+		*type = -1;
+		return -1;
+	}
+
+	/* Translate image type name to id */
+	*type = genimg_get_type_id(data);
+	return 0;
+}
+
+/**
+ * fit_image_get_comp - get comp id for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @comp: pointer to the uint8_t, will hold comp numeric id
+ *
+ * fit_image_get_comp() finds comp property in a given component image node.
+ * If the property is found, its (string) value is translated to the numeric
+ * id which is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
+{
+	int len;
+	const void *data;
+
+	/* Get compression name from property data */
+	data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
+		*comp = -1;
+		return -1;
+	}
+
+	/* Translate compression name to id */
+	*comp = genimg_get_comp_id(data);
+	return 0;
+}
+
+/**
+ * fit_image_get_load() - get load addr property for given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @load: pointer to the uint32_t, will hold load address
+ *
+ * fit_image_get_load() finds load address property in a given component
+ * image node. If the property is found, its value is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_load(const void *fit, int noffset, ulong *load)
+{
+	int len;
+	const uint32_t *data;
+
+	data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_LOAD_PROP, len);
+		return -1;
+	}
+
+	*load = uimage_to_cpu(*data);
+	return 0;
+}
+
+/**
+ * fit_image_get_entry() - get entry point address property
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @entry: pointer to the uint32_t, will hold entry point address
+ *
+ * This gets the entry point address property for a given component image
+ * node.
+ *
+ * fit_image_get_entry() finds entry point address property in a given
+ * component image node.  If the property is found, its value is returned
+ * to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
+{
+	int len;
+	const uint32_t *data;
+
+	data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len);
+	if (data == NULL) {
+		fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len);
+		return -1;
+	}
+
+	*entry = uimage_to_cpu(*data);
+	return 0;
+}
+
+/**
+ * fit_image_get_data - get data property and its size for a given component image node
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @data: double pointer to void, will hold data property's data address
+ * @size: pointer to size_t, will hold data property's data size
+ *
+ * fit_image_get_data() finds data property in a given component image node.
+ * If the property is found its data start address and size are returned to
+ * the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_get_data(const void *fit, int noffset,
+		const void **data, size_t *size)
+{
+	int len;
+
+	*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
+	if (*data == NULL) {
+		fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
+		*size = 0;
+		return -1;
+	}
+
+	*size = len;
+	return 0;
+}
+
+/**
+ * fit_image_hash_get_algo - get hash algorithm name
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @algo: double pointer to char, will hold pointer to the algorithm name
+ *
+ * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
+ * If the property is found its data start address is returned to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
+{
+	int len;
+
+	*algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
+	if (*algo == NULL) {
+		fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_image_hash_get_value - get hash value and length
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @value: double pointer to uint8_t, will hold address of a hash value data
+ * @value_len: pointer to an int, will hold hash data length
+ *
+ * fit_image_hash_get_value() finds hash value property in a given hash node.
+ * If the property is found its data start address and size are returned to
+ * the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on failure
+ */
+int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
+				int *value_len)
+{
+	int len;
+
+	*value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
+	if (*value == NULL) {
+		fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
+		*value_len = 0;
+		return -1;
+	}
+
+	*value_len = len;
+	return 0;
+}
+
+#ifndef USE_HOSTCC
+/**
+ * fit_image_hash_get_ignore - get hash ignore flag
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @ignore: pointer to an int, will hold hash ignore flag
+ *
+ * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
+ * If the property is found and non-zero, the hash algorithm is not verified by
+ * u-boot automatically.
+ *
+ * returns:
+ *     0, on ignore not found
+ *     value, on ignore found
+ */
+int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
+{
+	int len;
+	int *value;
+
+	value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
+	if (value == NULL || len != sizeof(int))
+		*ignore = 0;
+	else
+		*ignore = *value;
+
+	return 0;
+}
+#endif
+
+/**
+ * fit_set_timestamp - set node timestamp property
+ * @fit: pointer to the FIT format image header
+ * @noffset: node offset
+ * @timestamp: timestamp value to be set
+ *
+ * fit_set_timestamp() attempts to set timestamp property in the requested
+ * node and returns operation status to the caller.
+ *
+ * returns:
+ *     0, on success
+ *     -1, on property read failure
+ */
+int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
+{
+	uint32_t t;
+	int ret;
+
+	t = cpu_to_uimage(timestamp);
+	ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
+				sizeof(uint32_t));
+	if (ret) {
+		printf("Can't set '%s' property for '%s' node (%s)\n",
+		       FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
+		       fdt_strerror(ret));
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * calculate_hash - calculate and return hash for provided input data
+ * @data: pointer to the input data
+ * @data_len: data length
+ * @algo: requested hash algorithm
+ * @value: pointer to the char, will hold hash value data (caller must
+ * allocate enough free space)
+ * value_len: length of the calculated hash
+ *
+ * calculate_hash() computes input data hash according to the requested
+ * algorithm.
+ * Resulting hash value is placed in caller provided 'value' buffer, length
+ * of the calculated hash is returned via value_len pointer argument.
+ *
+ * returns:
+ *     0, on success
+ *    -1, when algo is unsupported
+ */
+static int calculate_hash(const void *data, int data_len, const char *algo,
+			uint8_t *value, int *value_len)
+{
+	if (strcmp(algo, "crc32") == 0) {
+		*((uint32_t *)value) = crc32_wd(0, data, data_len,
+							CHUNKSZ_CRC32);
+		*((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
+		*value_len = 4;
+	} else if (strcmp(algo, "sha1") == 0) {
+		sha1_csum_wd((unsigned char *)data, data_len,
+			     (unsigned char *)value, CHUNKSZ_SHA1);
+		*value_len = 20;
+	} else if (strcmp(algo, "md5") == 0) {
+		md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
+		*value_len = 16;
+	} else {
+		debug("Unsupported hash alogrithm\n");
+		return -1;
+	}
+	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
+ * @image_noffset: component image node offset
+ *
+ * fit_image_check_hashes() goes over component image hash nodes,
+ * re-calculates each data hash and compares with the value stored in hash
+ * node.
+ *
+ * returns:
+ *     1, if all hashes are valid
+ *     0, otherwise (or on error)
+ */
+int fit_image_check_hashes(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 = "";
+
+	/* 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 0;
+	}
+
+	/* 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)
+				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";
+				goto error;
+			}
+			printf("+ ");
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = " error!\nCorrupted or truncated tree";
+		goto error;
+	}
+
+	return 1;
+
+error:
+	printf("%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;
+}
+
+/**
+ * fit_all_image_check_hashes - 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
+ * 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 images_noffset;
+	int noffset;
+	int ndepth;
+	int count;
+
+	/* 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 0;
+	}
+
+	/* Process all image subnodes, check hashes for each */
+	printf("## Checking hash(es) for FIT Image@%08lx ...\n",
+	       (ulong)fit);
+	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) {
+			/*
+			 * Direct child node of the images parent node,
+			 * i.e. component image node.
+			 */
+			printf("   Hash(es) for Image %u (%s): ", count++,
+			       fit_get_name(fit, noffset, NULL));
+
+			if (!fit_image_check_hashes(fit, noffset))
+				return 0;
+			printf("\n");
+		}
+	}
+	return 1;
+}
+
+/**
+ * fit_image_check_os - check whether image node is of a given os type
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @os: requested image os
+ *
+ * fit_image_check_os() reads image os property and compares its numeric
+ * id with the requested os. Comparison result is returned to the caller.
+ *
+ * returns:
+ *     1 if image is of given os type
+ *     0 otherwise (or on error)
+ */
+int fit_image_check_os(const void *fit, int noffset, uint8_t os)
+{
+	uint8_t image_os;
+
+	if (fit_image_get_os(fit, noffset, &image_os))
+		return 0;
+	return (os == image_os);
+}
+
+/**
+ * fit_image_check_arch - check whether image node is of a given arch
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @arch: requested imagearch
+ *
+ * fit_image_check_arch() reads image arch property and compares its numeric
+ * id with the requested arch. Comparison result is returned to the caller.
+ *
+ * returns:
+ *     1 if image is of given arch
+ *     0 otherwise (or on error)
+ */
+int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
+{
+	uint8_t image_arch;
+
+	if (fit_image_get_arch(fit, noffset, &image_arch))
+		return 0;
+	return (arch == image_arch);
+}
+
+/**
+ * fit_image_check_type - check whether image node is of a given type
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @type: requested image type
+ *
+ * fit_image_check_type() reads image type property and compares its numeric
+ * id with the requested type. Comparison result is returned to the caller.
+ *
+ * returns:
+ *     1 if image is of given type
+ *     0 otherwise (or on error)
+ */
+int fit_image_check_type(const void *fit, int noffset, uint8_t type)
+{
+	uint8_t image_type;
+
+	if (fit_image_get_type(fit, noffset, &image_type))
+		return 0;
+	return (type == image_type);
+}
+
+/**
+ * fit_image_check_comp - check whether image node uses given compression
+ * @fit: pointer to the FIT format image header
+ * @noffset: component image node offset
+ * @comp: requested image compression type
+ *
+ * fit_image_check_comp() reads image compression property and compares its
+ * numeric id with the requested compression type. Comparison result is
+ * returned to the caller.
+ *
+ * returns:
+ *     1 if image uses requested compression
+ *     0 otherwise (or on error)
+ */
+int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
+{
+	uint8_t image_comp;
+
+	if (fit_image_get_comp(fit, noffset, &image_comp))
+		return 0;
+	return (comp == image_comp);
+}
+
+/**
+ * fit_check_format - sanity check FIT image format
+ * @fit: pointer to the FIT format image header
+ *
+ * fit_check_format() runs a basic sanity FIT image verification.
+ * Routine checks for mandatory properties, nodes, etc.
+ *
+ * returns:
+ *     1, on success
+ *     0, on failure
+ */
+int fit_check_format(const void *fit)
+{
+	/* mandatory / node 'description' property */
+	if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
+		debug("Wrong FIT format: no description\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;
+		}
+	}
+
+	/* mandatory subimages parent '/images' node */
+	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
+		debug("Wrong FIT format: no images parent node\n");
+		return 0;
+	}
+
+	return 1;
+}
+
+
+/**
+ * fit_conf_find_compat
+ * @fit: pointer to the FIT format image header
+ * @fdt: pointer to the device tree to compare against
+ *
+ * fit_conf_find_compat() attempts to find the configuration whose fdt is the
+ * most compatible with the passed in device tree.
+ *
+ * Example:
+ *
+ * / o image-tree
+ *   |-o images
+ *   | |-o fdt at 1
+ *   | |-o fdt at 2
+ *   |
+ *   |-o configurations
+ *     |-o config at 1
+ *     | |-fdt = fdt at 1
+ *     |
+ *     |-o config at 2
+ *       |-fdt = fdt@2
+ *
+ * / o U-Boot fdt
+ *   |-compatible = "foo,bar", "bim,bam"
+ *
+ * / o kernel fdt1
+ *   |-compatible = "foo,bar",
+ *
+ * / o kernel fdt2
+ *   |-compatible = "bim,bam", "baz,biz"
+ *
+ * Configuration 1 would be picked because the first string in U-Boot's
+ * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
+ * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
+ *
+ * returns:
+ *     offset to the configuration to use if one was found
+ *     -1 otherwise
+ */
+int fit_conf_find_compat(const void *fit, const void *fdt)
+{
+	int ndepth = 0;
+	int noffset, confs_noffset, images_noffset;
+	const void *fdt_compat;
+	int fdt_compat_len;
+	int best_match_offset = 0;
+	int best_match_pos = 0;
+
+	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (confs_noffset < 0 || images_noffset < 0) {
+		debug("Can't find configurations or images nodes.\n");
+		return -1;
+	}
+
+	fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
+	if (!fdt_compat) {
+		debug("Fdt for comparison has no \"compatible\" property.\n");
+		return -1;
+	}
+
+	/*
+	 * Loop over the configurations in the FIT image.
+	 */
+	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
+			(noffset >= 0) && (ndepth > 0);
+			noffset = fdt_next_node(fit, noffset, &ndepth)) {
+		const void *kfdt;
+		const char *kfdt_name;
+		int kfdt_noffset;
+		const char *cur_fdt_compat;
+		int len;
+		size_t size;
+		int i;
+
+		if (ndepth > 1)
+			continue;
+
+		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
+		if (!kfdt_name) {
+			debug("No fdt property found.\n");
+			continue;
+		}
+		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
+						  kfdt_name);
+		if (kfdt_noffset < 0) {
+			debug("No image node named \"%s\" found.\n",
+			      kfdt_name);
+			continue;
+		}
+		/*
+		 * Get a pointer to this configuration's fdt.
+		 */
+		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
+			debug("Failed to get fdt \"%s\".\n", kfdt_name);
+			continue;
+		}
+
+		len = fdt_compat_len;
+		cur_fdt_compat = fdt_compat;
+		/*
+		 * Look for a match for each U-Boot compatibility string in
+		 * turn in this configuration's fdt.
+		 */
+		for (i = 0; len > 0 &&
+		     (!best_match_offset || best_match_pos > i); i++) {
+			int cur_len = strlen(cur_fdt_compat) + 1;
+
+			if (!fdt_node_check_compatible(kfdt, 0,
+						       cur_fdt_compat)) {
+				best_match_offset = noffset;
+				best_match_pos = i;
+				break;
+			}
+			len -= cur_len;
+			cur_fdt_compat += cur_len;
+		}
+	}
+	if (!best_match_offset) {
+		debug("No match found.\n");
+		return -1;
+	}
+
+	return best_match_offset;
+}
+
+/**
+ * fit_conf_get_node - get node offset for configuration of a given unit name
+ * @fit: pointer to the FIT format image header
+ * @conf_uname: configuration node unit name
+ *
+ * fit_conf_get_node() finds a configuration (withing the '/configurations'
+ * parant node) of a provided unit name. If configuration is found its node
+ * offset is returned to the caller.
+ *
+ * When NULL is provided in second argument fit_conf_get_node() will search
+ * for a default configuration node instead. Default configuration node unit
+ * name is retrived from FIT_DEFAULT_PROP property of the '/configurations'
+ * node.
+ *
+ * returns:
+ *     configuration node offset when found (>=0)
+ *     negative number on failure (FDT_ERR_* code)
+ */
+int fit_conf_get_node(const void *fit, const char *conf_uname)
+{
+	int noffset, confs_noffset;
+	int len;
+
+	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+	if (confs_noffset < 0) {
+		debug("Can't find configurations parent node '%s' (%s)\n",
+		      FIT_CONFS_PATH, fdt_strerror(confs_noffset));
+		return confs_noffset;
+	}
+
+	if (conf_uname == NULL) {
+		/* get configuration unit name from the default property */
+		debug("No configuration specified, trying default...\n");
+		conf_uname = (char *)fdt_getprop(fit, confs_noffset,
+						 FIT_DEFAULT_PROP, &len);
+		if (conf_uname == NULL) {
+			fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
+				      len);
+			return len;
+		}
+		debug("Found default configuration: '%s'\n", conf_uname);
+	}
+
+	noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
+	if (noffset < 0) {
+		debug("Can't get node offset for configuration unit name: '%s' (%s)\n",
+		      conf_uname, fdt_strerror(noffset));
+	}
+
+	return noffset;
+}
+
+static int __fit_conf_get_prop_node(const void *fit, int noffset,
+		const char *prop_name)
+{
+	char *uname;
+	int len;
+
+	/* get kernel image unit name from configuration kernel property */
+	uname = (char *)fdt_getprop(fit, noffset, prop_name, &len);
+	if (uname == NULL)
+		return len;
+
+	return fit_image_get_node(fit, uname);
+}
+
+/**
+ * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
+ * a given configuration
+ * @fit: pointer to the FIT format image header
+ * @noffset: configuration node offset
+ *
+ * fit_conf_get_kernel_node() retrives kernel image node unit name from
+ * configuration FIT_KERNEL_PROP property and translates it to the node
+ * offset.
+ *
+ * returns:
+ *     image node offset when found (>=0)
+ *     negative number on failure (FDT_ERR_* code)
+ */
+int fit_conf_get_kernel_node(const void *fit, int noffset)
+{
+	return __fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
+}
+
+/**
+ * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
+ * a given configuration
+ * @fit: pointer to the FIT format image header
+ * @noffset: configuration node offset
+ *
+ * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
+ * configuration FIT_KERNEL_PROP property and translates it to the node
+ * offset.
+ *
+ * returns:
+ *     image node offset when found (>=0)
+ *     negative number on failure (FDT_ERR_* code)
+ */
+int fit_conf_get_ramdisk_node(const void *fit, int noffset)
+{
+	return __fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
+}
+
+/**
+ * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
+ * a given configuration
+ * @fit: pointer to the FIT format image header
+ * @noffset: configuration node offset
+ *
+ * fit_conf_get_fdt_node() retrives fdt image node unit name from
+ * configuration FIT_KERNEL_PROP property and translates it to the node
+ * offset.
+ *
+ * returns:
+ *     image node offset when found (>=0)
+ *     negative number on failure (FDT_ERR_* code)
+ */
+int fit_conf_get_fdt_node(const void *fit, int noffset)
+{
+	return __fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
+}
+
+/**
+ * fit_conf_print - prints out the FIT configuration details
+ * @fit: pointer to the FIT format image header
+ * @noffset: offset of the configuration node
+ * @p: pointer to prefix string
+ *
+ * fit_conf_print() lists all mandatory properies for the processed
+ * configuration node.
+ *
+ * returns:
+ *     no returned results
+ */
+void fit_conf_print(const void *fit, int noffset, const char *p)
+{
+	char *desc;
+	char *uname;
+	int ret;
+
+	/* Mandatory properties */
+	ret = fit_get_desc(fit, noffset, &desc);
+	printf("%s  Description:  ", p);
+	if (ret)
+		printf("unavailable\n");
+	else
+		printf("%s\n", desc);
+
+	uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
+	printf("%s  Kernel:       ", p);
+	if (uname == NULL)
+		printf("unavailable\n");
+	else
+		printf("%s\n", uname);
+
+	/* Optional properties */
+	uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
+	if (uname)
+		printf("%s  Init Ramdisk: %s\n", p, uname);
+
+	uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
+	if (uname)
+		printf("%s  FDT:          %s\n", p, uname);
+}
+
+/**
+ * fit_check_ramdisk - verify FIT format ramdisk subimage
+ * @fit_hdr: pointer to the FIT ramdisk header
+ * @rd_noffset: ramdisk subimage node offset within FIT image
+ * @arch: requested ramdisk image architecture type
+ * @verify: data CRC verification flag
+ *
+ * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
+ * specified FIT image.
+ *
+ * returns:
+ *     1, on success
+ *     0, on failure
+ */
+#ifndef USE_HOSTCC
+int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
+			int verify)
+{
+	fit_image_print(fit, rd_noffset, "   ");
+
+	if (verify) {
+		puts("   Verifying Hash Integrity ... ");
+		if (!fit_image_check_hashes(fit, rd_noffset)) {
+			puts("Bad Data Hash\n");
+			bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
+			return 0;
+		}
+		puts("OK\n");
+	}
+
+	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
+	if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) ||
+	    !fit_image_check_arch(fit, rd_noffset, arch) ||
+	    !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) {
+		printf("No Linux %s Ramdisk Image\n",
+		       genimg_get_arch_name(arch));
+		bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
+		return 0;
+	}
+
+	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
+	return 1;
+}
+#endif /* USE_HOSTCC */
diff --git a/common/image.c b/common/image.c
index af66138..c7a793a 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1786,1605 +1786,3 @@ int boot_get_kbd(struct lmb *lmb, bd_t **kbd)
 }
 #endif /* CONFIG_SYS_BOOT_GET_KBD */
 #endif /* !USE_HOSTCC */
-
-#if defined(CONFIG_FIT)
-/*****************************************************************************/
-/* New uImage format routines */
-/*****************************************************************************/
-#ifndef USE_HOSTCC
-static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
-		ulong *addr, const char **name)
-{
-	const char *sep;
-
-	*addr = addr_curr;
-	*name = NULL;
-
-	sep = strchr(spec, sepc);
-	if (sep) {
-		if (sep - spec > 0)
-			*addr = simple_strtoul(spec, NULL, 16);
-
-		*name = sep + 1;
-		return 1;
-	}
-
-	return 0;
-}
-
-/**
- * fit_parse_conf - parse FIT configuration spec
- * @spec: input string, containing configuration spec
- * @add_curr: current image address (to be used as a possible default)
- * @addr: pointer to a ulong variable, will hold FIT image address of a given
- * configuration
- * @conf_name double pointer to a char, will hold pointer to a configuration
- * unit name
- *
- * fit_parse_conf() expects configuration spec in the for of [<addr>]#<conf>,
- * where <addr> is a FIT image address that contains configuration
- * with a <conf> unit name.
- *
- * Address part is optional, and if omitted default add_curr will
- * be used instead.
- *
- * returns:
- *     1 if spec is a valid configuration string,
- *     addr and conf_name are set accordingly
- *     0 otherwise
- */
-int fit_parse_conf(const char *spec, ulong addr_curr,
-		ulong *addr, const char **conf_name)
-{
-	return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
-}
-
-/**
- * fit_parse_subimage - parse FIT subimage spec
- * @spec: input string, containing subimage spec
- * @add_curr: current image address (to be used as a possible default)
- * @addr: pointer to a ulong variable, will hold FIT image address of a given
- * subimage
- * @image_name: double pointer to a char, will hold pointer to a subimage name
- *
- * fit_parse_subimage() expects subimage spec in the for of
- * [<addr>]:<subimage>, where <addr> is a FIT image address that contains
- * subimage with a <subimg> unit name.
- *
- * Address part is optional, and if omitted default add_curr will
- * be used instead.
- *
- * returns:
- *     1 if spec is a valid subimage string,
- *     addr and image_name are set accordingly
- *     0 otherwise
- */
-int fit_parse_subimage(const char *spec, ulong addr_curr,
-		ulong *addr, const char **image_name)
-{
-	return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
-}
-#endif /* !USE_HOSTCC */
-
-static void fit_get_debug(const void *fit, int noffset,
-		char *prop_name, int err)
-{
-	debug("Can't get '%s' property from FIT 0x%08lx, "
-		"node: offset %d, name %s (%s)\n",
-		prop_name, (ulong)fit, noffset,
-		fit_get_name(fit, noffset, NULL),
-		fdt_strerror(err));
-}
-
-/**
- * fit_print_contents - prints out the contents of the FIT format image
- * @fit: pointer to the FIT format image header
- * @p: pointer to prefix string
- *
- * fit_print_contents() formats a multi line FIT image contents description.
- * The routine prints out FIT image properties (root node level) follwed by
- * the details of each component image.
- *
- * returns:
- *     no returned results
- */
-void fit_print_contents(const void *fit)
-{
-	char *desc;
-	char *uname;
-	int images_noffset;
-	int confs_noffset;
-	int noffset;
-	int ndepth;
-	int count = 0;
-	int ret;
-	const char *p;
-	time_t timestamp;
-
-#ifdef USE_HOSTCC
-	p = "";
-#else
-	p = "   ";
-#endif
-
-	/* Root node properties */
-	ret = fit_get_desc(fit, 0, &desc);
-	printf("%sFIT description: ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		printf("%s\n", desc);
-
-	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);
-	if (images_noffset < 0) {
-		printf("Can't find images parent node '%s' (%s)\n",
-			FIT_IMAGES_PATH, fdt_strerror(images_noffset));
-		return;
-	}
-
-	/* Process its subnodes, print out component images details */
-	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) {
-			/*
-			 * Direct child node of the images parent node,
-			 * i.e. component image node.
-			 */
-			printf("%s Image %u (%s)\n", p, count++,
-					fit_get_name(fit, noffset, NULL));
-
-			fit_image_print(fit, noffset, p);
-		}
-	}
-
-	/* Find configurations parent node offset */
-	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
-	if (confs_noffset < 0) {
-		debug("Can't get configurations parent node '%s' (%s)\n",
-			FIT_CONFS_PATH, fdt_strerror(confs_noffset));
-		return;
-	}
-
-	/* get default configuration unit name from default property */
-	uname = (char *)fdt_getprop(fit, noffset, FIT_DEFAULT_PROP, NULL);
-	if (uname)
-		printf("%s Default Configuration: '%s'\n", p, uname);
-
-	/* Process its subnodes, print out configurations details */
-	for (ndepth = 0, count = 0,
-		noffset = fdt_next_node(fit, confs_noffset, &ndepth);
-	     (noffset >= 0) && (ndepth > 0);
-	     noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		if (ndepth == 1) {
-			/*
-			 * Direct child node of the configurations parent node,
-			 * i.e. configuration node.
-			 */
-			printf("%s Configuration %u (%s)\n", p, count++,
-					fit_get_name(fit, noffset, NULL));
-
-			fit_conf_print(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
- * @p: pointer to prefix string
- *
- * fit_image_print() lists all mandatory properies for the processed component
- * image. If present, hash nodes are printed out as well. Load
- * address for images of type firmware is also printed out. Since the load
- * address is not mandatory for firmware images, it will be output as
- * "unavailable" when not present.
- *
- * returns:
- *     no returned results
- */
-void fit_image_print(const void *fit, int image_noffset, const char *p)
-{
-	char *desc;
-	uint8_t type, arch, os, comp;
-	size_t size;
-	ulong load, entry;
-	const void *data;
-	int noffset;
-	int ndepth;
-	int ret;
-
-	/* Mandatory properties */
-	ret = fit_get_desc(fit, image_noffset, &desc);
-	printf("%s  Description:  ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		printf("%s\n", desc);
-
-	fit_image_get_type(fit, image_noffset, &type);
-	printf("%s  Type:         %s\n", p, genimg_get_type_name(type));
-
-	fit_image_get_comp(fit, image_noffset, &comp);
-	printf("%s  Compression:  %s\n", p, genimg_get_comp_name(comp));
-
-	ret = fit_image_get_data(fit, image_noffset, &data, &size);
-
-#ifndef USE_HOSTCC
-	printf("%s  Data Start:   ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		printf("0x%08lx\n", (ulong)data);
-#endif
-
-	printf("%s  Data Size:    ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		genimg_print_size(size);
-
-	/* Remaining, type dependent properties */
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-	    (type == IH_TYPE_RAMDISK) || (type == IH_TYPE_FIRMWARE) ||
-	    (type == IH_TYPE_FLATDT)) {
-		fit_image_get_arch(fit, image_noffset, &arch);
-		printf("%s  Architecture: %s\n", p, genimg_get_arch_name(arch));
-	}
-
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_RAMDISK)) {
-		fit_image_get_os(fit, image_noffset, &os);
-		printf("%s  OS:           %s\n", p, genimg_get_os_name(os));
-	}
-
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-		(type == IH_TYPE_FIRMWARE) || (type == IH_TYPE_RAMDISK)) {
-		ret = fit_image_get_load(fit, image_noffset, &load);
-		printf("%s  Load Address: ", p);
-		if (ret)
-			printf("unavailable\n");
-		else
-			printf("0x%08lx\n", load);
-	}
-
-	if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) ||
-		(type == IH_TYPE_RAMDISK)) {
-		fit_image_get_entry(fit, image_noffset, &entry);
-		printf("%s  Entry Point:  ", p);
-		if (ret)
-			printf("unavailable\n");
-		else
-			printf("0x%08lx\n", entry);
-	}
-
-	/* 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 */
-			fit_image_print_hash(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 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_get_desc - get node description property
- * @fit: pointer to the FIT format image header
- * @noffset: node offset
- * @desc: double pointer to the char, will hold pointer to the descrption
- *
- * fit_get_desc() reads description property from a given node, if
- * description is found pointer to it is returened in third call argument.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_get_desc(const void *fit, int noffset, char **desc)
-{
-	int len;
-
-	*desc = (char *)fdt_getprop(fit, noffset, FIT_DESC_PROP, &len);
-	if (*desc == NULL) {
-		fit_get_debug(fit, noffset, FIT_DESC_PROP, len);
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * fit_get_timestamp - get node timestamp property
- * @fit: pointer to the FIT format image header
- * @noffset: node offset
- * @timestamp: pointer to the time_t, will hold read timestamp
- *
- * fit_get_timestamp() reads timestamp poperty from given node, if timestamp
- * is found and has a correct size its value is retured in third call
- * argument.
- *
- * returns:
- *     0, on success
- *     -1, on property read failure
- *     -2, on wrong timestamp size
- */
-int fit_get_timestamp(const void *fit, int noffset, time_t *timestamp)
-{
-	int len;
-	const void *data;
-
-	data = fdt_getprop(fit, noffset, FIT_TIMESTAMP_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_TIMESTAMP_PROP, len);
-		return -1;
-	}
-	if (len != sizeof(uint32_t)) {
-		debug("FIT timestamp with incorrect size of (%u)\n", len);
-		return -2;
-	}
-
-	*timestamp = uimage_to_cpu(*((uint32_t *)data));
-	return 0;
-}
-
-/**
- * fit_image_get_node - get node offset for component image of a given unit name
- * @fit: pointer to the FIT format image header
- * @image_uname: component image node unit name
- *
- * fit_image_get_node() finds a component image (withing the '/images'
- * node) of a provided unit name. If image is found its node offset is
- * returned to the caller.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_image_get_node(const void *fit, const char *image_uname)
-{
-	int noffset, images_noffset;
-
-	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
-	if (images_noffset < 0) {
-		debug("Can't find images parent node '%s' (%s)\n",
-			FIT_IMAGES_PATH, fdt_strerror(images_noffset));
-		return images_noffset;
-	}
-
-	noffset = fdt_subnode_offset(fit, images_noffset, image_uname);
-	if (noffset < 0) {
-		debug("Can't get node offset for image unit name: '%s' (%s)\n",
-			image_uname, fdt_strerror(noffset));
-	}
-
-	return noffset;
-}
-
-/**
- * fit_image_get_os - get os id for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @os: pointer to the uint8_t, will hold os numeric id
- *
- * fit_image_get_os() finds os property in a given component image node.
- * If the property is found, its (string) value is translated to the numeric
- * id which is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_os(const void *fit, int noffset, uint8_t *os)
-{
-	int len;
-	const void *data;
-
-	/* Get OS name from property data */
-	data = fdt_getprop(fit, noffset, FIT_OS_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_OS_PROP, len);
-		*os = -1;
-		return -1;
-	}
-
-	/* Translate OS name to id */
-	*os = genimg_get_os_id(data);
-	return 0;
-}
-
-/**
- * fit_image_get_arch - get arch id for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @arch: pointer to the uint8_t, will hold arch numeric id
- *
- * fit_image_get_arch() finds arch property in a given component image node.
- * If the property is found, its (string) value is translated to the numeric
- * id which is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_arch(const void *fit, int noffset, uint8_t *arch)
-{
-	int len;
-	const void *data;
-
-	/* Get architecture name from property data */
-	data = fdt_getprop(fit, noffset, FIT_ARCH_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_ARCH_PROP, len);
-		*arch = -1;
-		return -1;
-	}
-
-	/* Translate architecture name to id */
-	*arch = genimg_get_arch_id(data);
-	return 0;
-}
-
-/**
- * fit_image_get_type - get type id for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @type: pointer to the uint8_t, will hold type numeric id
- *
- * fit_image_get_type() finds type property in a given component image node.
- * If the property is found, its (string) value is translated to the numeric
- * id which is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_type(const void *fit, int noffset, uint8_t *type)
-{
-	int len;
-	const void *data;
-
-	/* Get image type name from property data */
-	data = fdt_getprop(fit, noffset, FIT_TYPE_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_TYPE_PROP, len);
-		*type = -1;
-		return -1;
-	}
-
-	/* Translate image type name to id */
-	*type = genimg_get_type_id(data);
-	return 0;
-}
-
-/**
- * fit_image_get_comp - get comp id for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @comp: pointer to the uint8_t, will hold comp numeric id
- *
- * fit_image_get_comp() finds comp property in a given component image node.
- * If the property is found, its (string) value is translated to the numeric
- * id which is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_comp(const void *fit, int noffset, uint8_t *comp)
-{
-	int len;
-	const void *data;
-
-	/* Get compression name from property data */
-	data = fdt_getprop(fit, noffset, FIT_COMP_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_COMP_PROP, len);
-		*comp = -1;
-		return -1;
-	}
-
-	/* Translate compression name to id */
-	*comp = genimg_get_comp_id(data);
-	return 0;
-}
-
-/**
- * fit_image_get_load - get load address property for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @load: pointer to the uint32_t, will hold load address
- *
- * fit_image_get_load() finds load address property in a given component image node.
- * If the property is found, its value is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_load(const void *fit, int noffset, ulong *load)
-{
-	int len;
-	const uint32_t *data;
-
-	data = fdt_getprop(fit, noffset, FIT_LOAD_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_LOAD_PROP, len);
-		return -1;
-	}
-
-	*load = uimage_to_cpu(*data);
-	return 0;
-}
-
-/**
- * fit_image_get_entry - get entry point address property for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @entry: pointer to the uint32_t, will hold entry point address
- *
- * fit_image_get_entry() finds entry point address property in a given component image node.
- * If the property is found, its value is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_entry(const void *fit, int noffset, ulong *entry)
-{
-	int len;
-	const uint32_t *data;
-
-	data = fdt_getprop(fit, noffset, FIT_ENTRY_PROP, &len);
-	if (data == NULL) {
-		fit_get_debug(fit, noffset, FIT_ENTRY_PROP, len);
-		return -1;
-	}
-
-	*entry = uimage_to_cpu(*data);
-	return 0;
-}
-
-/**
- * fit_image_get_data - get data property and its size for a given component image node
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @data: double pointer to void, will hold data property's data address
- * @size: pointer to size_t, will hold data property's data size
- *
- * fit_image_get_data() finds data property in a given component image node.
- * If the property is found its data start address and size are returned to
- * the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_get_data(const void *fit, int noffset,
-		const void **data, size_t *size)
-{
-	int len;
-
-	*data = fdt_getprop(fit, noffset, FIT_DATA_PROP, &len);
-	if (*data == NULL) {
-		fit_get_debug(fit, noffset, FIT_DATA_PROP, len);
-		*size = 0;
-		return -1;
-	}
-
-	*size = len;
-	return 0;
-}
-
-/**
- * fit_image_hash_get_algo - get hash algorithm name
- * @fit: pointer to the FIT format image header
- * @noffset: hash node offset
- * @algo: double pointer to char, will hold pointer to the algorithm name
- *
- * fit_image_hash_get_algo() finds hash algorithm property in a given hash node.
- * If the property is found its data start address is returned to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_hash_get_algo(const void *fit, int noffset, char **algo)
-{
-	int len;
-
-	*algo = (char *)fdt_getprop(fit, noffset, FIT_ALGO_PROP, &len);
-	if (*algo == NULL) {
-		fit_get_debug(fit, noffset, FIT_ALGO_PROP, len);
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * fit_image_hash_get_value - get hash value and length
- * @fit: pointer to the FIT format image header
- * @noffset: hash node offset
- * @value: double pointer to uint8_t, will hold address of a hash value data
- * @value_len: pointer to an int, will hold hash data length
- *
- * fit_image_hash_get_value() finds hash value property in a given hash node.
- * If the property is found its data start address and size are returned to
- * the caller.
- *
- * returns:
- *     0, on success
- *     -1, on failure
- */
-int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
-				int *value_len)
-{
-	int len;
-
-	*value = (uint8_t *)fdt_getprop(fit, noffset, FIT_VALUE_PROP, &len);
-	if (*value == NULL) {
-		fit_get_debug(fit, noffset, FIT_VALUE_PROP, len);
-		*value_len = 0;
-		return -1;
-	}
-
-	*value_len = len;
-	return 0;
-}
-
-#ifndef USE_HOSTCC
-/**
- * fit_image_hash_get_ignore - get hash ignore flag
- * @fit: pointer to the FIT format image header
- * @noffset: hash node offset
- * @ignore: pointer to an int, will hold hash ignore flag
- *
- * fit_image_hash_get_ignore() finds hash ignore property in a given hash node.
- * If the property is found and non-zero, the hash algorithm is not verified by
- * u-boot automatically.
- *
- * returns:
- *     0, on ignore not found
- *     value, on ignore found
- */
-int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
-{
-	int len;
-	int *value;
-
-	value = (int *)fdt_getprop(fit, noffset, FIT_IGNORE_PROP, &len);
-	if (value == NULL || len != sizeof(int))
-		*ignore = 0;
-	else
-		*ignore = *value;
-
-	return 0;
-}
-#endif
-
-/**
- * fit_set_timestamp - set node timestamp property
- * @fit: pointer to the FIT format image header
- * @noffset: node offset
- * @timestamp: timestamp value to be set
- *
- * fit_set_timestamp() attempts to set timestamp property in the requested
- * node and returns operation status to the caller.
- *
- * returns:
- *     0, on success
- *     -1, on property read failure
- */
-int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
-{
-	uint32_t t;
-	int ret;
-
-	t = cpu_to_uimage(timestamp);
-	ret = fdt_setprop(fit, noffset, FIT_TIMESTAMP_PROP, &t,
-				sizeof(uint32_t));
-	if (ret) {
-		printf("Can't set '%s' property for '%s' node (%s)\n",
-			FIT_TIMESTAMP_PROP, fit_get_name(fit, noffset, NULL),
-			fdt_strerror(ret));
-		return -1;
-	}
-
-	return 0;
-}
-
-/**
- * calculate_hash - calculate and return hash for provided input data
- * @data: pointer to the input data
- * @data_len: data length
- * @algo: requested hash algorithm
- * @value: pointer to the char, will hold hash value data (caller must
- * allocate enough free space)
- * value_len: length of the calculated hash
- *
- * calculate_hash() computes input data hash according to the requested algorithm.
- * Resulting hash value is placed in caller provided 'value' buffer, length
- * of the calculated hash is returned via value_len pointer argument.
- *
- * returns:
- *     0, on success
- *    -1, when algo is unsupported
- */
-static int calculate_hash(const void *data, int data_len, const char *algo,
-			uint8_t *value, int *value_len)
-{
-	if (strcmp(algo, "crc32") == 0) {
-		*((uint32_t *)value) = crc32_wd(0, data, data_len,
-							CHUNKSZ_CRC32);
-		*((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
-		*value_len = 4;
-	} else if (strcmp(algo, "sha1") == 0) {
-		sha1_csum_wd((unsigned char *) data, data_len,
-				(unsigned char *) value, CHUNKSZ_SHA1);
-		*value_len = 20;
-	} else if (strcmp(algo, "md5") == 0) {
-		md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
-		*value_len = 16;
-	} else {
-		debug("Unsupported hash alogrithm\n");
-		return -1;
-	}
-	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
- * @image_noffset: component image node offset
- *
- * fit_image_check_hashes() goes over component image hash nodes,
- * re-calculates each data hash and compares with the value stored in hash
- * node.
- *
- * returns:
- *     1, if all hashes are valid
- *     0, otherwise (or on error)
- */
-int fit_image_check_hashes(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 = "";
-
-	/* 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 0;
-	}
-
-	/* 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)
-				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";
-				goto error;
-			}
-			printf("+ ");
-		}
-	}
-
-	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
-		err_msg = " error!\nCorrupted or truncated tree";
-		goto error;
-	}
-
-	return 1;
-
-error:
-	printf("%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;
-}
-
-/**
- * fit_all_image_check_hashes - 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
- * 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 images_noffset;
-	int noffset;
-	int ndepth;
-	int count;
-
-	/* 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 0;
-	}
-
-	/* Process all image subnodes, check hashes for each */
-	printf("## Checking hash(es) for FIT Image@%08lx ...\n",
-		(ulong)fit);
-	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) {
-			/*
-			 * Direct child node of the images parent node,
-			 * i.e. component image node.
-			 */
-			printf("   Hash(es) for Image %u (%s): ", count++,
-					fit_get_name(fit, noffset, NULL));
-
-			if (!fit_image_check_hashes(fit, noffset))
-				return 0;
-			printf("\n");
-		}
-	}
-	return 1;
-}
-
-/**
- * fit_image_check_os - check whether image node is of a given os type
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @os: requested image os
- *
- * fit_image_check_os() reads image os property and compares its numeric
- * id with the requested os. Comparison result is returned to the caller.
- *
- * returns:
- *     1 if image is of given os type
- *     0 otherwise (or on error)
- */
-int fit_image_check_os(const void *fit, int noffset, uint8_t os)
-{
-	uint8_t image_os;
-
-	if (fit_image_get_os(fit, noffset, &image_os))
-		return 0;
-	return (os == image_os);
-}
-
-/**
- * fit_image_check_arch - check whether image node is of a given arch
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @arch: requested imagearch
- *
- * fit_image_check_arch() reads image arch property and compares its numeric
- * id with the requested arch. Comparison result is returned to the caller.
- *
- * returns:
- *     1 if image is of given arch
- *     0 otherwise (or on error)
- */
-int fit_image_check_arch(const void *fit, int noffset, uint8_t arch)
-{
-	uint8_t image_arch;
-
-	if (fit_image_get_arch(fit, noffset, &image_arch))
-		return 0;
-	return (arch == image_arch);
-}
-
-/**
- * fit_image_check_type - check whether image node is of a given type
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @type: requested image type
- *
- * fit_image_check_type() reads image type property and compares its numeric
- * id with the requested type. Comparison result is returned to the caller.
- *
- * returns:
- *     1 if image is of given type
- *     0 otherwise (or on error)
- */
-int fit_image_check_type(const void *fit, int noffset, uint8_t type)
-{
-	uint8_t image_type;
-
-	if (fit_image_get_type(fit, noffset, &image_type))
-		return 0;
-	return (type == image_type);
-}
-
-/**
- * fit_image_check_comp - check whether image node uses given compression
- * @fit: pointer to the FIT format image header
- * @noffset: component image node offset
- * @comp: requested image compression type
- *
- * fit_image_check_comp() reads image compression property and compares its
- * numeric id with the requested compression type. Comparison result is
- * returned to the caller.
- *
- * returns:
- *     1 if image uses requested compression
- *     0 otherwise (or on error)
- */
-int fit_image_check_comp(const void *fit, int noffset, uint8_t comp)
-{
-	uint8_t image_comp;
-
-	if (fit_image_get_comp(fit, noffset, &image_comp))
-		return 0;
-	return (comp == image_comp);
-}
-
-/**
- * fit_check_format - sanity check FIT image format
- * @fit: pointer to the FIT format image header
- *
- * fit_check_format() runs a basic sanity FIT image verification.
- * Routine checks for mandatory properties, nodes, etc.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-int fit_check_format(const void *fit)
-{
-	/* mandatory / node 'description' property */
-	if (fdt_getprop(fit, 0, FIT_DESC_PROP, NULL) == NULL) {
-		debug("Wrong FIT format: no description\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;
-		}
-	}
-
-	/* mandatory subimages parent '/images' node */
-	if (fdt_path_offset(fit, FIT_IMAGES_PATH) < 0) {
-		debug("Wrong FIT format: no images parent node\n");
-		return 0;
-	}
-
-	return 1;
-}
-
-
-/**
- * fit_conf_find_compat
- * @fit: pointer to the FIT format image header
- * @fdt: pointer to the device tree to compare against
- *
- * fit_conf_find_compat() attempts to find the configuration whose fdt is the
- * most compatible with the passed in device tree.
- *
- * Example:
- *
- * / o image-tree
- *   |-o images
- *   | |-o fdt at 1
- *   | |-o fdt at 2
- *   |
- *   |-o configurations
- *     |-o config at 1
- *     | |-fdt = fdt at 1
- *     |
- *     |-o config at 2
- *       |-fdt = fdt@2
- *
- * / o U-Boot fdt
- *   |-compatible = "foo,bar", "bim,bam"
- *
- * / o kernel fdt1
- *   |-compatible = "foo,bar",
- *
- * / o kernel fdt2
- *   |-compatible = "bim,bam", "baz,biz"
- *
- * Configuration 1 would be picked because the first string in U-Boot's
- * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
- * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
- *
- * returns:
- *     offset to the configuration to use if one was found
- *     -1 otherwise
- */
-int fit_conf_find_compat(const void *fit, const void *fdt)
-{
-	int ndepth = 0;
-	int noffset, confs_noffset, images_noffset;
-	const void *fdt_compat;
-	int fdt_compat_len;
-	int best_match_offset = 0;
-	int best_match_pos = 0;
-
-	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
-	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
-	if (confs_noffset < 0 || images_noffset < 0) {
-		debug("Can't find configurations or images nodes.\n");
-		return -1;
-	}
-
-	fdt_compat = fdt_getprop(fdt, 0, "compatible", &fdt_compat_len);
-	if (!fdt_compat) {
-		debug("Fdt for comparison has no \"compatible\" property.\n");
-		return -1;
-	}
-
-	/*
-	 * Loop over the configurations in the FIT image.
-	 */
-	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
-			(noffset >= 0) && (ndepth > 0);
-			noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		const void *kfdt;
-		const char *kfdt_name;
-		int kfdt_noffset;
-		const char *cur_fdt_compat;
-		int len;
-		size_t size;
-		int i;
-
-		if (ndepth > 1)
-			continue;
-
-		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
-		if (!kfdt_name) {
-			debug("No fdt property found.\n");
-			continue;
-		}
-		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
-						  kfdt_name);
-		if (kfdt_noffset < 0) {
-			debug("No image node named \"%s\" found.\n",
-			      kfdt_name);
-			continue;
-		}
-		/*
-		 * Get a pointer to this configuration's fdt.
-		 */
-		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
-			debug("Failed to get fdt \"%s\".\n", kfdt_name);
-			continue;
-		}
-
-		len = fdt_compat_len;
-		cur_fdt_compat = fdt_compat;
-		/*
-		 * Look for a match for each U-Boot compatibility string in
-		 * turn in this configuration's fdt.
-		 */
-		for (i = 0; len > 0 &&
-		     (!best_match_offset || best_match_pos > i); i++) {
-			int cur_len = strlen(cur_fdt_compat) + 1;
-
-			if (!fdt_node_check_compatible(kfdt, 0,
-						       cur_fdt_compat)) {
-				best_match_offset = noffset;
-				best_match_pos = i;
-				break;
-			}
-			len -= cur_len;
-			cur_fdt_compat += cur_len;
-		}
-	}
-	if (!best_match_offset) {
-		debug("No match found.\n");
-		return -1;
-	}
-
-	return best_match_offset;
-}
-
-/**
- * fit_conf_get_node - get node offset for configuration of a given unit name
- * @fit: pointer to the FIT format image header
- * @conf_uname: configuration node unit name
- *
- * fit_conf_get_node() finds a configuration (withing the '/configurations'
- * parant node) of a provided unit name. If configuration is found its node offset
- * is returned to the caller.
- *
- * When NULL is provided in second argument fit_conf_get_node() will search
- * for a default configuration node instead. Default configuration node unit name
- * is retrived from FIT_DEFAULT_PROP property of the '/configurations' node.
- *
- * returns:
- *     configuration node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_node(const void *fit, const char *conf_uname)
-{
-	int noffset, confs_noffset;
-	int len;
-
-	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
-	if (confs_noffset < 0) {
-		debug("Can't find configurations parent node '%s' (%s)\n",
-			FIT_CONFS_PATH, fdt_strerror(confs_noffset));
-		return confs_noffset;
-	}
-
-	if (conf_uname == NULL) {
-		/* get configuration unit name from the default property */
-		debug("No configuration specified, trying default...\n");
-		conf_uname = (char *)fdt_getprop(fit, confs_noffset,
-						 FIT_DEFAULT_PROP, &len);
-		if (conf_uname == NULL) {
-			fit_get_debug(fit, confs_noffset, FIT_DEFAULT_PROP,
-					len);
-			return len;
-		}
-		debug("Found default configuration: '%s'\n", conf_uname);
-	}
-
-	noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname);
-	if (noffset < 0) {
-		debug("Can't get node offset for configuration unit name: "
-			"'%s' (%s)\n",
-			conf_uname, fdt_strerror(noffset));
-	}
-
-	return noffset;
-}
-
-static int __fit_conf_get_prop_node(const void *fit, int noffset,
-		const char *prop_name)
-{
-	char *uname;
-	int len;
-
-	/* get kernel image unit name from configuration kernel property */
-	uname = (char *)fdt_getprop(fit, noffset, prop_name, &len);
-	if (uname == NULL)
-		return len;
-
-	return fit_image_get_node(fit, uname);
-}
-
-/**
- * fit_conf_get_kernel_node - get kernel image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_kernel_node() retrives kernel image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_kernel_node(const void *fit, int noffset)
-{
-	return __fit_conf_get_prop_node(fit, noffset, FIT_KERNEL_PROP);
-}
-
-/**
- * fit_conf_get_ramdisk_node - get ramdisk image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_ramdisk_node() retrives ramdisk image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_ramdisk_node(const void *fit, int noffset)
-{
-	return __fit_conf_get_prop_node(fit, noffset, FIT_RAMDISK_PROP);
-}
-
-/**
- * fit_conf_get_fdt_node - get fdt image node offset that corresponds to
- * a given configuration
- * @fit: pointer to the FIT format image header
- * @noffset: configuration node offset
- *
- * fit_conf_get_fdt_node() retrives fdt image node unit name from
- * configuration FIT_KERNEL_PROP property and translates it to the node
- * offset.
- *
- * returns:
- *     image node offset when found (>=0)
- *     negative number on failure (FDT_ERR_* code)
- */
-int fit_conf_get_fdt_node(const void *fit, int noffset)
-{
-	return __fit_conf_get_prop_node(fit, noffset, FIT_FDT_PROP);
-}
-
-/**
- * fit_conf_print - prints out the FIT configuration details
- * @fit: pointer to the FIT format image header
- * @noffset: offset of the configuration node
- * @p: pointer to prefix string
- *
- * fit_conf_print() lists all mandatory properies for the processed
- * configuration node.
- *
- * returns:
- *     no returned results
- */
-void fit_conf_print(const void *fit, int noffset, const char *p)
-{
-	char *desc;
-	char *uname;
-	int ret;
-
-	/* Mandatory properties */
-	ret = fit_get_desc(fit, noffset, &desc);
-	printf("%s  Description:  ", p);
-	if (ret)
-		printf("unavailable\n");
-	else
-		printf("%s\n", desc);
-
-	uname = (char *)fdt_getprop(fit, noffset, FIT_KERNEL_PROP, NULL);
-	printf("%s  Kernel:       ", p);
-	if (uname == NULL)
-		printf("unavailable\n");
-	else
-		printf("%s\n", uname);
-
-	/* Optional properties */
-	uname = (char *)fdt_getprop(fit, noffset, FIT_RAMDISK_PROP, NULL);
-	if (uname)
-		printf("%s  Init Ramdisk: %s\n", p, uname);
-
-	uname = (char *)fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL);
-	if (uname)
-		printf("%s  FDT:          %s\n", p, uname);
-}
-
-/**
- * fit_check_ramdisk - verify FIT format ramdisk subimage
- * @fit_hdr: pointer to the FIT ramdisk header
- * @rd_noffset: ramdisk subimage node offset within FIT image
- * @arch: requested ramdisk image architecture type
- * @verify: data CRC verification flag
- *
- * fit_check_ramdisk() verifies integrity of the ramdisk subimage and from
- * specified FIT image.
- *
- * returns:
- *     1, on success
- *     0, on failure
- */
-#ifndef USE_HOSTCC
-int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
-			int verify)
-{
-	fit_image_print(fit, rd_noffset, "   ");
-
-	if (verify) {
-		puts("   Verifying Hash Integrity ... ");
-		if (!fit_image_check_hashes(fit, rd_noffset)) {
-			puts("Bad Data Hash\n");
-			bootstage_error(BOOTSTAGE_ID_FIT_RD_HASH);
-			return 0;
-		}
-		puts("OK\n");
-	}
-
-	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-	if (!fit_image_check_os(fit, rd_noffset, IH_OS_LINUX) ||
-	    !fit_image_check_arch(fit, rd_noffset, arch) ||
-	    !fit_image_check_type(fit, rd_noffset, IH_TYPE_RAMDISK)) {
-		printf("No Linux %s Ramdisk Image\n",
-				genimg_get_arch_name(arch));
-		bootstage_error(BOOTSTAGE_ID_FIT_RD_CHECK_ALL);
-		return 0;
-	}
-
-	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
-	return 1;
-}
-#endif /* USE_HOSTCC */
-#endif /* CONFIG_FIT */
diff --git a/tools/Makefile b/tools/Makefile
index c5952fc..81c5c38 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -78,6 +78,7 @@ BIN_FILES-$(CONFIG_KIRKWOOD) += kwboot$(SFX)
 # Source files which exist outside the tools directory
 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-y += lib/crc32.o
 EXT_OBJ_FILES-y += lib/md5.o
 EXT_OBJ_FILES-y += lib/sha1.o
@@ -208,6 +209,7 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)crc32.o \
 			$(obj)default_image.o \
 			$(obj)fit_image.o \
+			$(obj)image-fit.o \
 			$(obj)image.o \
 			$(obj)imximage.o \
 			$(obj)kwbimage.o \
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 08/45] image: Move HOSTCC image code to tools/
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (6 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 07/45] image: Split FIT code into new image-fit.c Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 09/45] image: Split hash node processing into its own function Simon Glass
                   ` (38 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Rebase on previous patches

 common/image-fit.c | 171 +--------------------------------------------
 include/image.h    |   3 +
 tools/Makefile     |   2 +
 tools/image-host.c | 201 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 207 insertions(+), 170 deletions(-)
 create mode 100644 tools/image-host.c

diff --git a/common/image-fit.c b/common/image-fit.c
index 3ba1ad3..3e72da0 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -827,7 +827,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) {
@@ -849,175 +849,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
diff --git a/include/image.h b/include/image.h
index 880ce07..8b02998 100644
--- a/include/image.h
+++ b/include/image.h
@@ -635,6 +635,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)
 {
diff --git a/tools/Makefile b/tools/Makefile
index 81c5c38..0452e65 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -96,6 +96,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
@@ -211,6 +212,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 \
diff --git a/tools/image-host.c b/tools/image-host.c
new file mode 100644
index 0000000..82b6cee
--- /dev/null
+++ b/tools/image-host.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "mkimage.h"
+#include <bootstage.h>
+#include <image.h>
+#include <sha1.h>
+#include <time.h>
+#include <u-boot/crc.h>
+#include <u-boot/md5.h>
+
+/**
+ * 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;
+}
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 09/45] image: Split hash node processing into its own function
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (7 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 08/45] image: Move HOSTCC image code to tools/ Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 10/45] image: Convert fit_image_hash_set_value() to static, and rename Simon Glass
                   ` (37 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Acked-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Rebase on previous patches

 tools/image-host.c | 96 ++++++++++++++++++++++++++++++++----------------------
 1 file changed, 57 insertions(+), 39 deletions(-)

diff --git a/tools/image-host.c b/tools/image-host.c
index 82b6cee..6648215 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -79,6 +79,56 @@ 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 +161,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,47 +171,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;
-			}
 		}
 	}
 
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 10/45] image: Convert fit_image_hash_set_value() to static, and rename
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (8 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 09/45] image: Split hash node processing into its own function Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 11/45] image: Rename fit_image_check_hashes() to fit_image_verify() Simon Glass
                   ` (36 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Rebase on previous patches

 include/image.h    |  2 --
 tools/image-host.c | 62 +++++++++++++++++++++++++++---------------------------
 2 files changed, 31 insertions(+), 33 deletions(-)

diff --git a/include/image.h b/include/image.h
index 8b02998..9bb9071 100644
--- a/include/image.h
+++ b/include/image.h
@@ -613,8 +613,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);
diff --git a/tools/image-host.c b/tools/image-host.c
index 6648215..a6b4f6b 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -79,6 +79,36 @@ int fit_set_hashes(void *fit)
 }
 
 /**
+ * fit_set_hash_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_set_hash_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
+ */
+static int fit_set_hash_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;
+}
+
+/**
  * fit_image_process_hash - Process a single subnode of the images/ node
  *
  * Check each subnode and process accordingly. For hash nodes we generate
@@ -119,7 +149,7 @@ static int fit_image_process_hash(void *fit, const char *image_name,
 		return -1;
 	}
 
-	if (fit_image_hash_set_value(fit, noffset, value, value_len)) {
+	if (fit_set_hash_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;
@@ -187,33 +217,3 @@ int fit_image_set_hashes(void *fit, int image_noffset)
 
 	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;
-}
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 11/45] image: Rename fit_image_check_hashes() to fit_image_verify()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (9 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 10/45] image: Convert fit_image_hash_set_value() to static, and rename Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 12/45] image: Move hash checking into its own function Simon Glass
                   ` (35 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2: None

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

diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 5d2ce00..f6eb7a6 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -809,7 +809,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;
@@ -1163,7 +1163,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;
 		}
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 1834246..1341604 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -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;
 				}
diff --git a/common/cmd_source.c b/common/cmd_source.c
index 02a862c..6a82fb2 100644
--- a/common/cmd_source.c
+++ b/common/cmd_source.c
@@ -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;
 			}
diff --git a/common/cmd_ximg.c b/common/cmd_ximg.c
index ea0a26e..f8722a0 100644
--- a/common/cmd_ximg.c
+++ b/common/cmd_ximg.c
@@ -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;
 			}
diff --git a/common/image-fit.c b/common/image-fit.c
index 3e72da0..9360af2 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -850,11 +850,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.
  *
@@ -862,7 +862,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;
@@ -955,17 +955,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;
@@ -995,7 +995,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");
 		}
@@ -1443,7 +1443,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;
diff --git a/common/image.c b/common/image.c
index c7a793a..3fbdd9b 100644
--- a/common/image.c
+++ b/common/image.c
@@ -1209,7 +1209,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;
 		}
diff --git a/common/update.c b/common/update.c
index 94d6a82..87941ec 100644
--- a/common/update.c
+++ b/common/update.c
@@ -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;
diff --git a/include/image.h b/include/image.h
index 9bb9071..c09325c 100644
--- a/include/image.h
+++ b/include/image.h
@@ -614,8 +614,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);
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 12/45] image: Move hash checking into its own function
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (10 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 11/45] image: Rename fit_image_check_hashes() to fit_image_verify() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 13/45] image: Move error! string to common place Simon Glass
                   ` (34 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de> (v1)
---
Changes in v2:
- Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
- Rebase on previous patches
- Rename commit message to say "function" instead of "function"

 common/image-fit.c | 128 ++++++++++++++++++++++++++++-------------------------
 include/image.h    |   8 ++--
 2 files changed, 72 insertions(+), 64 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index 9360af2..fa21f18 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -748,7 +748,6 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 	return 0;
 }
 
-#ifndef USE_HOSTCC
 /**
  * fit_image_hash_get_ignore - get hash ignore flag
  * @fit: pointer to the FIT format image header
@@ -763,7 +762,7 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
  *     0, on ignore not found
  *     value, on ignore found
  */
-int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
+static int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
 {
 	int len;
 	int *value;
@@ -776,7 +775,6 @@ int fit_image_hash_get_ignore(const void *fit, int noffset, int *ignore)
 
 	return 0;
 }
-#endif
 
 /**
  * fit_set_timestamp - set node timestamp property
@@ -849,6 +847,57 @@ 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;
+	int ignore;
+
+	*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);
+
+	if (IMAGE_ENABLE_IGNORE) {
+		fit_image_hash_get_ignore(fit, noffset, &ignore);
+		if (ignore) {
+			printf("-skipped ");
+			return 0;
+		}
+	}
+
+	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
@@ -866,14 +915,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 = "";
@@ -885,58 +926,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("+ ");
 		}
 	}
 
diff --git a/include/image.h b/include/image.h
index c09325c..0d3d1db 100644
--- a/include/image.h
+++ b/include/image.h
@@ -43,12 +43,17 @@
 #define CONFIG_OF_LIBFDT	1
 #define CONFIG_FIT_VERBOSE	1 /* enable fit_format_{error,warning}() */
 
+#define IMAGE_ENABLE_IGNORE	0
+
 #else
 
 #include <lmb.h>
 #include <asm/u-boot.h>
 #include <command.h>
 
+/* Take notice of the 'ignore' property for hashes */
+#define IMAGE_ENABLE_IGNORE	1
+
 #endif /* USE_HOSTCC */
 
 #if defined(CONFIG_FIT)
@@ -606,9 +611,6 @@ int fit_image_get_data(const void *fit, int noffset,
 int fit_image_hash_get_algo(const void *fit, int noffset, char **algo);
 int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 				int *value_len);
-#ifndef USE_HOSTCC
-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);
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 13/45] image: Move error! string to common place
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (11 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 12/45] image: Move hash checking into its own function Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 14/45] image: Export fit_conf_get_prop_node() Simon Glass
                   ` (33 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Put err_msgp strings on a single line
- Rebase on previous patches

 common/image-fit.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index fa21f18..97f8521 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -860,8 +860,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 "
-				"property";
+		*err_msgp = "Can't get hash algo property";
 		return -1;
 	}
 	printf("%s", algo);
@@ -876,22 +875,20 @@ 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 "
-				"property";
+		*err_msgp = "Can't get hash value property";
 		return -1;
 	}
 
 	if (calculate_hash(data, size, algo, value, &value_len)) {
-		*err_msgp = " error!\n"
-				"Unsupported hash algorithm";
+		*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;
 	}
 
@@ -921,7 +918,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;
 	}
 
@@ -947,14 +944,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;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 14/45] image: Export fit_conf_get_prop_node()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (12 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 13/45] image: Move error! string to common place Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 15/45] image: Rename fit_add_hashes() to fit_add_verification_data() Simon Glass
                   ` (32 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Put params before description in fit_conf_get_prop_node() comment

 common/image-fit.c |  8 ++++----
 include/image.h    | 14 ++++++++++++++
 2 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index 97f8521..b8a1eb4 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1310,7 +1310,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;
@@ -1340,7 +1340,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);
 }
 
 /**
@@ -1359,7 +1359,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);
 }
 
 /**
@@ -1378,7 +1378,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);
 }
 
 /**
diff --git a/include/image.h b/include/image.h
index 0d3d1db..c5e8844 100644
--- a/include/image.h
+++ b/include/image.h
@@ -630,6 +630,20 @@ 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
+ * @fit:	FIT to check
+ * @noffset:	Offset of conf at xxx node to check
+ * @prop_name:	Property to read from the conf node
+ *
+ * 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".
+ */
+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,
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 15/45] image: Rename fit_add_hashes() to fit_add_verification_data()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (13 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 14/45] image: Export fit_conf_get_prop_node() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 16/45] image: Rename hash printing to fit_image_print_verification_data() Simon Glass
                   ` (31 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Rebase on previous patches

 include/image.h    |  10 +++-
 tools/fit_image.c  |   2 +-
 tools/image-host.c | 146 +++++++++++++++++++++++++----------------------------
 3 files changed, 79 insertions(+), 79 deletions(-)

diff --git a/include/image.h b/include/image.h
index c5e8844..4901ce7 100644
--- a/include/image.h
+++ b/include/image.h
@@ -613,8 +613,14 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 				int *value_len);
 
 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);
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 76bbba1..8f51159 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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);
diff --git a/tools/image-host.c b/tools/image-host.c
index a6b4f6b..3ba05de 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -34,51 +34,6 @@
 #include <u-boot/md5.h>
 
 /**
- * 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_set_hash_value - set hash value in requested has node
  * @fit: pointer to the FIT format image header
  * @noffset: hash node offset
@@ -125,33 +80,27 @@ 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];
+	const char *node_name;
 	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;
+	node_name = fit_get_name(fit, noffset, NULL);
 
 	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);
+		       node_name, 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);
+		       algo, node_name, image_name);
 		return -1;
 	}
 
 	if (fit_set_hash_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);
+		       node_name, image_name);
 		return -1;
 	}
 
@@ -159,14 +108,13 @@ static int fit_image_process_hash(void *fit, const char *image_name,
 }
 
 /**
- * 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_add_verification_data() - calculate/set hash data for 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:
+ * This adds hash values for a 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:
  *
@@ -183,17 +131,19 @@ static int fit_image_process_hash(void *fit, const char *image_name,
  *     |- algo = "sha1"
  *     |- value = sha1(data)
  *
- * returns:
- *     0 on sucess
- *    <0 on failure
+ * For signature details, please see doc/uImage.FIT/signature.txt
+ *
+ * @fit:	Pointer to the FIT format image header
+ * @image_noffset: Requested component image node
+ * @return: 0 on success, <0 on failure
  */
-int fit_image_set_hashes(void *fit, int image_noffset)
+int fit_image_add_verification_data(void *fit, int image_noffset)
 {
+	const char *image_name;
 	const void *data;
 	size_t size;
 	int noffset;
 	int ndepth;
-	const char *image_name;
 
 	/* Get image data and data length */
 	if (fit_image_get_data(fit, image_noffset, &data, &size)) {
@@ -204,15 +154,59 @@ int fit_image_set_hashes(void *fit, int image_noffset)
 	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)) {
-		if (ndepth == 1) {
-			/* Direct child node of the component image node */
-			if (fit_image_process_hash(fit, image_name, noffset,
-						   data, size))
-				return -1;
+	for (ndepth = 0,
+			noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		const char *node_name;
+		int ret = 0;
+
+		/*
+		 * Check subnode name, must be equal to "hash" or "signature".
+		 * Multiple hash nodes require unique unit node
+		 * names, e.g. hash at 1, hash at 2, signature at 1, etc.
+		 */
+		node_name = fit_get_name(fit, noffset, NULL);
+		if (!strncmp(node_name, FIT_HASH_NODENAME,
+			     strlen(FIT_HASH_NODENAME))) {
+			ret = fit_image_process_hash(fit, image_name, noffset,
+						data, size);
 		}
+		if (ret)
+			return -1;
+	}
+
+	return 0;
+}
+
+int fit_add_verification_data(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_subnode(fit, images_noffset,
+						   &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		/*
+		 * Direct child node of the images parent node,
+		 * i.e. component image node.
+		 */
+		ret = fit_image_add_verification_data(fit, noffset);
+		if (ret)
+			return ret;
 	}
 
 	return 0;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 16/45] image: Rename hash printing to fit_image_print_verification_data()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (14 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 15/45] image: Rename fit_add_hashes() to fit_add_verification_data() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 17/45] sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file Simon Glass
                   ` (30 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Rebase on previous patches

 common/image-fit.c | 131 ++++++++++++++++++++++++++++++++---------------------
 include/image.h    |   1 -
 2 files changed, 79 insertions(+), 53 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index b8a1eb4..5dcb0c6 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -229,6 +229,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
@@ -323,63 +401,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
diff --git a/include/image.h b/include/image.h
index 4901ce7..41d95f3 100644
--- a/include/image.h
+++ b/include/image.h
@@ -555,7 +555,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
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 17/45] sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (15 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 16/45] image: Rename hash printing to fit_image_print_verification_data() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 18/45] fdt: Add a parameter to fdt_valid() Simon Glass
                   ` (29 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Fix checkpatch warnings about split strings
- Fix typo "os defined" -> "is defined"
- Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)

 arch/sandbox/cpu/start.c         |  7 +++++++
 arch/sandbox/include/asm/state.h |  1 +
 arch/sandbox/lib/board.c         | 38 ++++++++++++++++++++++++++++++++++----
 doc/README.fdt-control           |  6 +++++-
 include/configs/sandbox.h        |  2 ++
 5 files changed, 49 insertions(+), 5 deletions(-)

diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 5287fd5..2fcec8b 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -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;
diff --git a/arch/sandbox/include/asm/state.h b/arch/sandbox/include/asm/state.h
index 2b62b46..9552708 100644
--- a/arch/sandbox/include/asm/state.h
+++ b/arch/sandbox/include/asm/state.h
@@ -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 */
diff --git a/arch/sandbox/lib/board.c b/arch/sandbox/lib/board.c
index 3752fab..7d12979 100644
--- a/arch/sandbox/lib/board.c
+++ b/arch/sandbox/lib/board.c
@@ -39,13 +39,15 @@
 
 #include <common.h>
 #include <command.h>
+#include <fs.h>
+#include <fdtdec.h>
 #include <malloc.h>
+#include <os.h>
 #include <stdio_dev.h>
 #include <timestamp.h>
 #include <version.h>
 #include <serial.h>
-
-#include <os.h>
+#include <asm/state.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -89,6 +91,21 @@ static int display_dram_config(void)
 	return 0;
 }
 
+static int read_fdt_from_file(void)
+{
+	struct sandbox_state *state = state_get_current();
+	int size;
+
+	if (fs_set_blk_dev("host", NULL, FS_TYPE_SANDBOX))
+		return 1;
+	size = fs_read(state->fdt_fname, CONFIG_SYS_FDT_LOAD_ADDR, 0, 0);
+	if (size < 0)
+		return 1;
+	gd->fdt_blob = map_sysmem(CONFIG_SYS_FDT_LOAD_ADDR, size);
+
+	return 0;
+}
+
 /*
  * Breathe some life into the board...
  *
@@ -127,6 +144,9 @@ init_fnc_t *init_sequence[] = {
 #if defined(CONFIG_ARCH_CPU_INIT)
 	arch_cpu_init,		/* basic arch cpu dependent setup */
 #endif
+#ifdef CONFIG_OF_CONTROL
+	fdtdec_check_fdt,
+#endif
 #if defined(CONFIG_BOARD_EARLY_INIT_F)
 	board_early_init_f,
 #endif
@@ -156,6 +176,11 @@ void board_init_f(ulong bootflag)
 	assert(gd);
 
 	memset((void *)gd, 0, sizeof(gd_t));
+	size = CONFIG_SYS_SDRAM_SIZE;
+	mem = os_malloc(CONFIG_SYS_SDRAM_SIZE);
+
+	assert(mem);
+	gd->arch.ram_buf = mem;
 
 #if defined(CONFIG_OF_EMBED)
 	/* Get a pointer to the FDT */
@@ -163,6 +188,8 @@ void board_init_f(ulong bootflag)
 #elif defined(CONFIG_OF_SEPARATE)
 	/* FDT is at end of image */
 	gd->fdt_blob = (void *)(_end_ofs + _TEXT_BASE);
+#elif defined(CONFIG_OF_HOSTFILE)
+	read_fdt_from_file();
 #endif
 
 	for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
@@ -170,8 +197,11 @@ void board_init_f(ulong bootflag)
 			hang();
 	}
 
-	size = CONFIG_SYS_SDRAM_SIZE;
-	mem = os_malloc(CONFIG_SYS_SDRAM_SIZE);
+#ifdef CONFIG_OF_CONTROL
+	/* For now, put this check after the console is ready */
+	if (fdtdec_prepare_fdt())
+		panic("** CONFIG_OF_CONTROL defined but no FDT - please see doc/README.fdt-control");
+#endif
 
 	assert(mem);
 	gd->arch.ram_buf = mem;
diff --git a/doc/README.fdt-control b/doc/README.fdt-control
index 85bda03..1e016d1 100644
--- a/doc/README.fdt-control
+++ b/doc/README.fdt-control
@@ -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 is 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
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 67d788a..1c7bbe1 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -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)
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 18/45] fdt: Add a parameter to fdt_valid()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (16 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 17/45] sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 19/45] Add getenv_hex() to return an environment variable as hex Simon Glass
                   ` (28 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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().

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Allow the control FDT to be set even if there is currently no control FDT
- fdt_valid() sets the FDT pointer to NULL on error, to simplify callers

 common/cmd_fdt.c | 38 ++++++++++++++++++++------------------
 1 file changed, 20 insertions(+), 18 deletions(-)

diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index ac77a08..07072f3 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -43,7 +43,7 @@
  */
 DECLARE_GLOBAL_DATA_PTR;
 
-static int fdt_valid(void);
+static int fdt_valid(struct fdt_header **blobp);
 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);
@@ -104,9 +104,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))
 				return 1;
-			}
 			printf("The address of the fdt is %p\n", working_fdt);
 			return 0;
 		}
@@ -114,9 +113,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))
 			return 1;
-		}
 
 		if (argc >= 4) {
 			int  len;
@@ -167,9 +165,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))
 			return 1;
-		}
 
 		newaddr = (struct fdt_header *)simple_strtoul(argv[3],NULL,16);
 
@@ -592,16 +589,23 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 
 /****************************************************************************/
 
-static int fdt_valid(void)
+/**
+ * fdt_valid() - Check if an FDT is valid. If not, change it to NULL
+ *
+ * @blobp: Pointer to FDT pointer
+ * @return 1 if OK, 0 if bad (in which case *blobp is set to NULL)
+ */
+static int fdt_valid(struct fdt_header **blobp)
 {
-	int  err;
+	const void *blob = *blobp;
+	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 */
 
@@ -611,23 +615,21 @@ 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;
 		}
 		printf("\n");
+		*blobp = NULL;
 		return 0;
 	}
 	return 1;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 19/45] Add getenv_hex() to return an environment variable as hex
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (17 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 18/45] fdt: Add a parameter to fdt_valid() Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 20/45] fdt: Allow fdt command to check and update control FDT Simon Glass
                   ` (27 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 common/cmd_nvedit.c | 15 +++++++++++++++
 include/common.h    | 13 +++++++++++++
 2 files changed, 28 insertions(+)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 947d6c4..967d8b1 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -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[])
 {
diff --git a/include/common.h b/include/common.h
index d41aeb4..52f2b33 100644
--- a/include/common.h
+++ b/include/common.h
@@ -352,6 +352,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)
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 20/45] fdt: Allow fdt command to check and update control FDT
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (18 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 19/45] Add getenv_hex() to return an environment variable as hex Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 21/45] sandbox: fdt: Support fdt command for sandbox Simon Glass
                   ` (26 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Correct bug in setting control FDT
- Fix checkpatch checks about parenthesis alignment

 common/cmd_fdt.c | 47 ++++++++++++++++++++++++++++++++++-------------
 1 file changed, 34 insertions(+), 13 deletions(-)

diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index 07072f3..e582961 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -100,38 +100,59 @@ 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;
+		struct fdt_header *blob;
 		/*
 		 * Set the address [and length] of the fdt.
 		 */
-		if (argc == 2) {
-			if (!fdt_valid(&working_fdt))
+		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) {
+			if (control)
+				blob = (struct fdt_header *)gd->fdt_blob;
+			else
+				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))
+		addr = simple_strtoul(argv[0], NULL, 16);
+		blob = (struct fdt_header *)addr;
+		if (!fdt_valid(&blob))
 			return 1;
+		if (control)
+			gd->fdt_blob = blob;
+		else
+			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 +981,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
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 21/45] sandbox: fdt: Support fdt command for sandbox
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (19 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 20/45] fdt: Allow fdt command to check and update control FDT Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit Simon Glass
                   ` (25 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Rebase to use updated fdt_valid() function

 common/cmd_fdt.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c
index e582961..edefd77 100644
--- a/common/cmd_fdt.c
+++ b/common/cmd_fdt.c
@@ -31,6 +31,7 @@
 #include <asm/global_data.h>
 #include <libfdt.h>
 #include <fdt_support.h>
+#include <asm/io.h>
 
 #define MAX_LEVEL	32		/* how deeply nested we will go */
 #define SCRATCHPAD	1024		/* bytes of scratchpad memory */
@@ -55,7 +56,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);
 }
 
@@ -129,13 +133,13 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 		}
 
 		addr = simple_strtoul(argv[0], NULL, 16);
-		blob = (struct fdt_header *)addr;
+		blob = map_sysmem(addr, 0);
 		if (!fdt_valid(&blob))
 			return 1;
 		if (control)
 			gd->fdt_blob = blob;
 		else
-			set_working_fdt_addr((void *)addr);
+			set_working_fdt_addr(blob);
 
 		if (argc >= 2) {
 			int  len;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (20 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 21/45] sandbox: fdt: Support fdt command for sandbox Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 23/45] fdt: Skip checking FDT if the pointer is NULL Simon Glass
                   ` (24 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

This should say 'environmnent'.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 common/cmd_nvedit.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index 967d8b1..b95b942 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -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
  */
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 23/45] fdt: Skip checking FDT if the pointer is NULL
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (21 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 24/45] Revert "fdt- Tell the FDT library where the device tree is" Simon Glass
                   ` (23 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Fix checkpatch checks about parenthesis alignment

 lib/fdtdec.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index 3ae348d..8e1542b 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -329,7 +329,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");
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 24/45] Revert "fdt- Tell the FDT library where the device tree is"
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (22 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 23/45] fdt: Skip checking FDT if the pointer is NULL Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 25/45] Add stdarg to vsprintf.h Simon Glass
                   ` (22 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Revert the whole change including the set_working_fdt_addr() part

 common/main.c | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/common/main.c b/common/main.c
index a15f020..953ef29 100644
--- a/common/main.c
+++ b/common/main.c
@@ -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>
@@ -376,10 +372,6 @@ void main_loop (void)
 
 	bootstage_mark_name(BOOTSTAGE_ID_MAIN_LOOP, "main_loop");
 
-#if defined CONFIG_OF_CONTROL
-       set_working_fdt_addr((void *)gd->fdt_blob);
-#endif /* CONFIG_OF_CONTROL */
-
 #ifdef CONFIG_BOOTCOUNT_LIMIT
 	bootcount = bootcount_load();
 	bootcount++;
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 25/45] Add stdarg to vsprintf.h
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (23 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 24/45] Revert "fdt- Tell the FDT library where the device tree is" Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 26/45] Add minor updates to README.fdt-control Simon Glass
                   ` (21 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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?

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 include/vsprintf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 651077c..704b8cd 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -24,6 +24,8 @@
 #ifndef __VSPRINTF_H
 #define __VSPRINTF_H
 
+#include <stdarg.h>
+
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
 /**
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 26/45] Add minor updates to README.fdt-control
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (24 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 25/45] Add stdarg to vsprintf.h Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 27/45] hash: Add a way to calculate a hash for any algortihm Simon Glass
                   ` (20 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 doc/README.fdt-control | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/doc/README.fdt-control b/doc/README.fdt-control
index 1e016d1..01b31fe 100644
--- a/doc/README.fdt-control
+++ b/doc/README.fdt-control
@@ -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?
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 27/45] hash: Add a way to calculate a hash for any algortihm
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (25 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 26/45] Add minor updates to README.fdt-control Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 28/45] sandbox: config: Enable FIT signatures with RSA Simon Glass
                   ` (19 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Change hash_block() to use an unsigned int len
- Clarify use of output_size parameter to hash_block()

 common/hash.c  | 23 +++++++++++++++++++++++
 include/hash.h | 22 ++++++++++++++++++++++
 2 files changed, 45 insertions(+)

diff --git a/common/hash.c b/common/hash.c
index f5badcb..10ed2cb 100644
--- a/common/hash.c
+++ b/common/hash.c
@@ -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
@@ -220,6 +221,28 @@ 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, unsigned 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;
+	}
+	if (output_size)
+		*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 flags, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[])
 {
diff --git a/include/hash.h b/include/hash.h
index 2dbbd9b..c402067 100644
--- a/include/hash.h
+++ b/include/hash.h
@@ -71,4 +71,26 @@ enum {
 int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag,
 		 int argc, char * const argv[]);
 
+/**
+ * hash_block() - Hash a block according to the requested algorithm
+ *
+ * The caller probably knows the hash length for the chosen algorithm, but
+ * in order to provide a general interface, and output_size parameter is
+ * provided.
+ *
+ * @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, pointer to the number of bytes available in
+ *			output. On exit, pointer to the number of bytes used.
+ *			If NULL, then it is assumed that the caller has
+ *			allocated enough space for the hash. This is possible
+ *			since the caller is selecting the algorithm.
+ * @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, unsigned int len,
+	       uint8_t *output, int *output_size);
+
 #endif
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 28/45] sandbox: config: Enable FIT signatures with RSA
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (26 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 27/45] hash: Add a way to calculate a hash for any algortihm Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 29/45] sandbox: Provide a way to map from host RAM to U-Boot RAM Simon Glass
                   ` (18 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2: None

 include/configs/sandbox.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h
index 1c7bbe1..fb1c583 100644
--- a/include/configs/sandbox.h
+++ b/include/configs/sandbox.h
@@ -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
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 29/45] sandbox: Provide a way to map from host RAM to U-Boot RAM
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (27 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 28/45] sandbox: config: Enable FIT signatures with RSA Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 30/45] sandbox: image: Add support for booting images in sandbox Simon Glass
                   ` (17 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)

 arch/sandbox/cpu/cpu.c        | 5 +++++
 arch/sandbox/include/asm/io.h | 2 ++
 include/common.h              | 5 +++++
 3 files changed, 12 insertions(+)

diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c
index b2788d5..dd8d495 100644
--- a/arch/sandbox/cpu/cpu.c
+++ b/arch/sandbox/cpu/cpu.c
@@ -57,6 +57,11 @@ void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
 	return (void *)(gd->arch.ram_buf + paddr);
 }
 
+phys_addr_t map_to_sysmem(void *ptr)
+{
+	return (u8 *)ptr - gd->arch.ram_buf;
+}
+
 void flush_dcache_range(unsigned long start, unsigned long stop)
 {
 }
diff --git a/arch/sandbox/include/asm/io.h b/arch/sandbox/include/asm/io.h
index d8c0236..4ce7a84 100644
--- a/arch/sandbox/include/asm/io.h
+++ b/arch/sandbox/include/asm/io.h
@@ -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);
diff --git a/include/common.h b/include/common.h
index 52f2b33..58fccd3 100644
--- a/include/common.h
+++ b/include/common.h
@@ -907,6 +907,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)(uintptr_t)ptr;
+}
 # endif
 
 #endif /* __ASSEMBLY__ */
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 30/45] sandbox: image: Add support for booting images in sandbox
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (28 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 29/45] sandbox: Provide a way to map from host RAM to U-Boot RAM Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 31/45] image: Add signing infrastructure Simon Glass
                   ` (16 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de> (v1)
---
Changes in v2:
- Fix checkpatch checks about parenthesis alignment

 common/cmd_bootm.c | 21 ++++++++++++---------
 common/image.c     | 48 ++++++++++++++++++++++++++++--------------------
 include/image.h    |  2 +-
 3 files changed, 41 insertions(+), 30 deletions(-)

diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index f6eb7a6..c03e88f 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -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)
@@ -97,7 +98,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);
 
@@ -197,8 +198,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");
@@ -849,14 +850,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;
@@ -892,7 +894,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);
@@ -937,7 +940,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);
 
@@ -1014,7 +1017,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;
@@ -1028,7 +1031,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
diff --git a/common/image.c b/common/image.c
index 3fbdd9b..14d1c48 100644
--- a/common/image.c
+++ b/common/image.c
@@ -51,6 +51,7 @@
 
 #include <u-boot/md5.h>
 #include <sha1.h>
+#include <asm/io.h>
 
 #ifdef CONFIG_CMD_BDI
 extern int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
@@ -90,6 +91,7 @@ static const table_entry_t uimage_arch[] = {
 	{	IH_ARCH_AVR32,		"avr32",	"AVR32",	},
 	{	IH_ARCH_NDS32,		"nds32",	"NDS32",	},
 	{	IH_ARCH_OPENRISC,	"or1k",		"OpenRISC 1000",},
+	{	IH_ARCH_SANDBOX,	"sandbox",	"Sandbox",	},
 	{	-1,			"",		"",		},
 };
 
@@ -660,7 +662,7 @@ int genimg_get_comp_id(const char *name)
  * returns:
  *     image format type or IMAGE_FORMAT_INVALID if no image is present
  */
-int genimg_get_format(void *img_addr)
+int genimg_get_format(const void *img_addr)
 {
 	ulong format = IMAGE_FORMAT_INVALID;
 	const image_header_t *hdr;
@@ -700,6 +702,8 @@ ulong genimg_get_image(ulong img_addr)
 	ulong h_size, d_size;
 
 	if (addr_dataflash(img_addr)) {
+		void *buf;
+
 		/* ger RAM address */
 		ram_addr = CONFIG_SYS_LOAD_ADDR;
 
@@ -714,20 +718,20 @@ ulong genimg_get_image(ulong img_addr)
 		debug("   Reading image header from dataflash address "
 			"%08lx to RAM address %08lx\n", img_addr, ram_addr);
 
-		read_dataflash(img_addr, h_size, (char *)ram_addr);
+		buf = map_sysmem(ram_addr, 0);
+		read_dataflash(img_addr, h_size, buf);
 
 		/* get data size */
-		switch (genimg_get_format((void *)ram_addr)) {
+		switch (genimg_get_format(buf)) {
 		case IMAGE_FORMAT_LEGACY:
-			d_size = image_get_data_size(
-					(const image_header_t *)ram_addr);
+			d_size = image_get_data_size(buf);
 			debug("   Legacy format image found at 0x%08lx, "
 					"size 0x%08lx\n",
 					ram_addr, d_size);
 			break;
 #if defined(CONFIG_FIT)
 		case IMAGE_FORMAT_FIT:
-			d_size = fit_get_size((const void *)ram_addr) - h_size;
+			d_size = fit_get_size(buf) - h_size;
 			debug("   FIT/FDT format image found at 0x%08lx, "
 					"size 0x%08lx\n",
 					ram_addr, d_size);
@@ -745,7 +749,7 @@ ulong genimg_get_image(ulong img_addr)
 			ram_addr + h_size);
 
 		read_dataflash(img_addr + h_size, d_size,
-				(char *)(ram_addr + h_size));
+				(char *)(buf + h_size));
 
 	}
 #endif /* CONFIG_HAS_DATAFLASH */
@@ -801,6 +805,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 	ulong rd_addr, rd_load;
 	ulong rd_data, rd_len;
 	const image_header_t *rd_hdr;
+	void *buf;
 #ifdef CONFIG_SUPPORT_RAW_INITRD
 	char *end;
 #endif
@@ -862,7 +867,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 			/* use FIT configuration provided in first bootm
 			 * command argument
 			 */
-			rd_addr = (ulong)images->fit_hdr_os;
+			rd_addr = map_to_sysmem(images->fit_hdr_os);
 			fit_uname_config = images->fit_uname_cfg;
 			debug("*  ramdisk: using config '%s' from image "
 					"at 0x%08lx\n",
@@ -872,7 +877,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 			 * Check whether configuration has ramdisk defined,
 			 * if not, don't try to use it, quit silently.
 			 */
-			fit_hdr = (void *)rd_addr;
+			fit_hdr = images->fit_hdr_os;
 			cfg_noffset = fit_conf_get_node(fit_hdr,
 							fit_uname_config);
 			if (cfg_noffset < 0) {
@@ -897,7 +902,8 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 		 * address provided in the second bootm argument
 		 * check image type, for FIT images get FIT node.
 		 */
-		switch (genimg_get_format((void *)rd_addr)) {
+		buf = map_sysmem(rd_addr, 0);
+		switch (genimg_get_format(buf)) {
 		case IMAGE_FORMAT_LEGACY:
 			printf("## Loading init Ramdisk from Legacy "
 					"Image at %08lx ...\n", rd_addr);
@@ -915,7 +921,7 @@ int boot_get_ramdisk(int argc, char * const argv[], bootm_headers_t *images,
 			break;
 #if defined(CONFIG_FIT)
 		case IMAGE_FORMAT_FIT:
-			fit_hdr = (void *)rd_addr;
+			fit_hdr = buf;
 			printf("## Loading init Ramdisk from FIT "
 					"Image@%08lx ...\n", rd_addr);
 
@@ -1158,7 +1164,7 @@ static void fdt_error(const char *msg)
 
 static const image_header_t *image_get_fdt(ulong fdt_addr)
 {
-	const image_header_t *fdt_hdr = (const image_header_t *)fdt_addr;
+	const image_header_t *fdt_hdr = map_sysmem(fdt_addr, 0);
 
 	image_print_contents(fdt_hdr);
 
@@ -1395,6 +1401,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 	char		*fdt_blob = NULL;
 	ulong		image_start, image_data, image_end;
 	ulong		load_start, load_end;
+	void		*buf;
 #if defined(CONFIG_FIT)
 	void		*fit_hdr;
 	const char	*fit_uname_config = NULL;
@@ -1448,7 +1455,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 			/* use FIT configuration provided in first bootm
 			 * command argument
 			 */
-			fdt_addr = (ulong)images->fit_hdr_os;
+			fdt_addr = map_to_sysmem(images->fit_hdr_os);
 			fit_uname_config = images->fit_uname_cfg;
 			debug("*  fdt: using config '%s' from image "
 					"at 0x%08lx\n",
@@ -1458,7 +1465,7 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 			 * Check whether configuration has FDT blob defined,
 			 * if not quit silently.
 			 */
-			fit_hdr = (void *)fdt_addr;
+			fit_hdr = images->fit_hdr_os;
 			cfg_noffset = fit_conf_get_node(fit_hdr,
 					fit_uname_config);
 			if (cfg_noffset < 0) {
@@ -1486,7 +1493,8 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 		 * address provided in the second bootm argument
 		 * check image type, for FIT images get a FIT node.
 		 */
-		switch (genimg_get_format((void *)fdt_addr)) {
+		buf = map_sysmem(fdt_addr, 0);
+		switch (genimg_get_format(buf)) {
 		case IMAGE_FORMAT_LEGACY:
 			/* verify fdt_addr points to a valid image header */
 			printf("## Flattened Device Tree from Legacy Image "
@@ -1535,11 +1543,11 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 			 */
 #if defined(CONFIG_FIT)
 			/* check FDT blob vs FIT blob */
-			if (fit_check_format((const void *)fdt_addr)) {
+			if (fit_check_format(buf)) {
 				/*
 				 * FIT image
 				 */
-				fit_hdr = (void *)fdt_addr;
+				fit_hdr = buf;
 				printf("## Flattened Device Tree from FIT "
 						"Image at %08lx\n",
 						fdt_addr);
@@ -1645,10 +1653,10 @@ int boot_get_fdt(int flag, int argc, char * const argv[],
 				/*
 				 * FDT blob
 				 */
-				fdt_blob = (char *)fdt_addr;
+				fdt_blob = buf;
 				debug("*  fdt: raw FDT blob\n");
-				printf("## Flattened Device Tree blob at "
-					"%08lx\n", (long)fdt_blob);
+				printf("## Flattened Device Tree blob@%08lx\n",
+				       (long)fdt_addr);
 			}
 			break;
 		default:
diff --git a/include/image.h b/include/image.h
index 41d95f3..008aeef 100644
--- a/include/image.h
+++ b/include/image.h
@@ -351,7 +351,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);
 
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 31/45] image: Add signing infrastructure
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (29 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 30/45] sandbox: image: Add support for booting images in sandbox Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 32/45] image: Support signing of images Simon Glass
                   ` (15 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Adjust how signing enable works in image.h
- Rebase on previous patches
- Tweak tools/Makefile to make image signing optional
- Update README to fix typos and clarify some points
- gd->fdt_blob is now available on all archs (generic board landed)

 README                       |   5 +
 common/Makefile              |   1 +
 common/image-sig.c           |  42 +++++++++
 doc/uImage.FIT/signature.txt | 216 +++++++++++++++++++++++++++++++++++++++++++
 include/image.h              | 107 ++++++++++++++++++++-
 tools/Makefile               |   6 ++
 6 files changed, 376 insertions(+), 1 deletion(-)
 create mode 100644 common/image-sig.c
 create mode 100644 doc/uImage.FIT/signature.txt

diff --git a/README b/README
index a620f0a..de753f3 100644
--- a/README
+++ b/README
@@ -2705,6 +2705,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
 
diff --git a/common/Makefile b/common/Makefile
index 36b4ffc..32cfe70 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -228,6 +228,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
 
diff --git a/common/image-sig.c b/common/image-sig.c
new file mode 100644
index 0000000..841c662
--- /dev/null
+++ b/common/image-sig.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifdef USE_HOSTCC
+#include "mkimage.h"
+#include <time.h>
+#else
+#include <common.h>
+#endif /* !USE_HOSTCC*/
+#include <errno.h>
+#include <image.h>
+
+struct image_sig_algo image_sig_algos[] = {
+};
+
+struct image_sig_algo *image_get_sig_algo(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(image_sig_algos); i++) {
+		if (!strcmp(image_sig_algos[i].name, name))
+			return &image_sig_algos[i];
+	}
+
+	return NULL;
+}
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
new file mode 100644
index 0000000..0d145e0
--- /dev/null
+++ b/doc/uImage.FIT/signature.txt
@@ -0,0 +1,216 @@
+U-Boot FIT Signature Verification
+=================================
+
+Introduction
+------------
+FIT supports hashing of images so that these hashes can be checked on
+loading. This protects against corruption of the image. However it does not
+prevent the substitution of one image for another.
+
+The signature feature allows the hash to be signed with a private key such
+that it can be verified using a public key later. Provided that the private
+key is kept secret and the public key is stored in a non-volatile place,
+any image can be verified in this way.
+
+See verified-boot.txt for more general information on verified boot.
+
+
+Concepts
+--------
+Some familiarity with public key cryptography is assumed in this section.
+
+The procedure for signing is as follows:
+
+   - hash an image in the FIT
+   - sign the hash with a private key to produce a signature
+   - store the resulting signature in the FIT
+
+The procedure for verification is:
+
+   - read the FIT
+   - obtain the public key
+   - extract the signature from the FIT
+   - hash the image from the FIT
+   - verify (with the public key) that the extracted signature matches the
+       hash
+
+The signing is generally performed by mkimage, as part of making a firmware
+image for the device. The verification is normally done in U-Boot on the
+device.
+
+
+Algorithms
+----------
+In principle any suitable algorithm can be used to sign and verify a hash.
+At present only one class of algorithms is supported: SHA1 hashing with RSA.
+This works by hashing the image to produce a 20-byte hash.
+
+While it is acceptable to bring in large cryptographic libraries such as
+openssl on the host side (e.g. mkimage), it is not desirable for U-Boot.
+For the run-time verification side, it is important to keep code and data
+size as small as possible.
+
+For this reason the RSA image verification uses pre-processed public keys
+which can be used with a very small amount of code - just some extraction
+of data from the FDT and exponentiation mod n. Code size impact is a little
+under 5KB on Tegra Seaboard, for example.
+
+It is relatively straightforward to add new algorithms if required. If
+another RSA variant is needed, then it can be added to the table in
+image-sig.c. If another algorithm is needed (such as DSA) then it can be
+placed alongside rsa.c, and its functions added to the table in image-sig.c
+also.
+
+
+Creating an RSA key and certificate
+-----------------------------------
+To create a new public key, size 2048 bits:
+
+$ openssl genrsa -F4 -out keys/dev.key 2048
+
+To create a certificate for this:
+
+$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt
+
+If you like you can look at the public key also:
+
+$ openssl rsa -in keys/dev.key -pubout
+
+
+Device Tree Bindings
+--------------------
+The following properties are required in the FIT's signature node(s) to
+allow thes signer to operate. These should be added to the .its file.
+Signature nodes sit at the same level as hash nodes and are called
+signature at 1, signature@2, etc.
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+- key-name-hint: Name of key to use for signing. The keys will normally be in
+a single directory (parameter -k to mkimage). For a given key <name>, its
+private key is stored in <name>.key and the certificate is stored in
+<name>.crt.
+
+When the image is signed, the following properties are added (mandatory):
+
+- value: The signature data (e.g. 256 bytes for 2048-bit RSA)
+
+When the image is signed, the following properties are optional:
+
+- timestamp: Time when image was signed (standard Unix time_t format)
+
+- signer-name: Name of the signer (e.g. "mkimage")
+
+- signer-version: Version string of the signer (e.g. "2013.01")
+
+- comment: Additional information about the signer or image
+
+
+Example: See sign-images.its for an example image tree source file.
+
+
+Public Key Storage
+------------------
+In order to verify an image that has been signed with a public key we need to
+have a trusted public key. This cannot be stored in the signed image, since
+it would be easy to alter. For this implementation we choose to store the
+public key in U-Boot's control FDT (using CONFIG_OF_CONTROL).
+
+Public keys should be stored as sub-nodes in a /signature node. Required
+properties are:
+
+- algo: Algorithm name (e.g. "sha1,rs2048")
+
+Optional properties are:
+
+- key-name-hint: Name of key used for signing. This is only a hint since it
+is possible for the name to be changed. Verification can proceed by checking
+all available signing keys until one matches.
+
+- required: If present this indicates that the key must be verified for the
+image / configuration to be considered valid. Only required keys are
+normally verified by the FIT image booting algorithm. Valid values are
+"image" to force verification of all images, and "conf" to force verfication
+of the selected configuration (which then relies on hashes in the images to
+verify those).
+
+Each signing algorithm has its own additional properties.
+
+For RSA the following are mandatory:
+
+- rsa,num-bits: Number of key bits (e.g. 2048)
+- rsa,modulus: Modulus (N) as a big-endian multi-word integer
+- rsa,r-squared: (2^num-bits)^2 as a big-endian multi-word integer
+- rsa,n0-inverse: -1 / modulus[0] mod 2^32
+
+
+Verification
+------------
+FITs are verified when loaded. After the configuration is selected a list
+of required images is produced. If there are 'required' public keys, then
+each image must be verified against those keys. This means that every image
+that might be used by the target needs to be signed with 'required' keys.
+
+This happens automatically as part of a bootm command when FITs are used.
+
+
+Enabling FIT Verification
+-------------------------
+In addition to the options to enable FIT itself, the following CONFIGs must
+be enabled:
+
+CONFIG_FIT_SIGNATURE - enable signing and verfication in FITs
+CONFIG_RSA - enable RSA algorithm for signing
+
+
+Testing
+-------
+An easy way to test signing and verfication is to use the test script
+provided in test/vboot/vboot_test.sh. This uses sandbox (a special version
+of U-Boot which runs under Linux) to show the operation of a 'bootm'
+command loading and verifying images.
+
+A sample run is show below:
+
+$ make O=sandbox sandbox_config
+$ make O=sandbox
+$ O=sandbox ./test/vboot/vboot_test.sh
+Simple Verified Boot Test
+=========================
+
+Please see doc/uImage.FIT/verified-boot.txt for more information
+
+Build keys
+Build FIT with signed images
+Test Verified Boot Run: unsigned signatures:: OK
+Sign images
+Test Verified Boot Run: signed images: OK
+Build FIT with signed configuration
+Test Verified Boot Run: unsigned config: OK
+Sign images
+Test Verified Boot Run: signed config: OK
+
+Test passed
+
+
+Future Work
+-----------
+- Roll-back protection using a TPM is done using the tpm command. This can
+be scripted, but we might consider a default way of doing this, built into
+bootm.
+
+
+Possible Future Work
+--------------------
+- Add support for other RSA/SHA variants, such as rsa4096,sha512.
+- Other algorithms besides RSA
+- More sandbox tests for failure modes
+- Passwords for keys/certificates
+- Perhaps implement OAEP
+- Enhance bootm to permit scripted signature verification (so that a script
+can verify an image but not actually boot it)
+
+
+Simon Glass
+sjg at chromium.org
+1-1-13
diff --git a/include/image.h b/include/image.h
index 008aeef..695473a 100644
--- a/include/image.h
+++ b/include/image.h
@@ -43,6 +43,9 @@
 #define CONFIG_OF_LIBFDT	1
 #define CONFIG_FIT_VERBOSE	1 /* enable fit_format_{error,warning}() */
 
+/* Support FIT image signing on host */
+#define CONFIG_FIT_SIGNATURE
+
 #define IMAGE_ENABLE_IGNORE	0
 
 #else
@@ -522,11 +525,12 @@ static inline int image_check_target_arch(const image_header_t *hdr)
 #define FIT_IMAGES_PATH		"/images"
 #define FIT_CONFS_PATH		"/configurations"
 
-/* hash node */
+/* hash/signature node */
 #define FIT_HASH_NODENAME	"hash"
 #define FIT_ALGO_PROP		"algo"
 #define FIT_VALUE_PROP		"value"
 #define FIT_IGNORE_PROP		"uboot-ignore"
+#define FIT_SIG_NODENAME	"signature"
 
 /* image node */
 #define FIT_DATA_PROP		"data"
@@ -657,6 +661,107 @@ int fit_check_ramdisk(const void *fit, int os_noffset,
 int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len);
 
+/*
+ * At present we only support signing on the host, and verification on the
+ * device
+ */
+#if defined(CONFIG_FIT_SIGNATURE)
+# ifdef USE_HOSTCC
+#  define IMAGE_ENABLE_SIGN	1
+#  define IMAGE_ENABLE_VERIFY	0
+#else
+#  define IMAGE_ENABLE_SIGN	0
+#  define IMAGE_ENABLE_VERIFY	1
+# endif
+#else
+# define IMAGE_ENABLE_SIGN	0
+# define IMAGE_ENABLE_VERIFY	0
+#endif
+
+#ifdef USE_HOSTCC
+# define gd_fdt_blob()		NULL
+#else
+# define gd_fdt_blob()		(gd->fdt_blob)
+#endif
+
+/* Information passed to the signing routines */
+struct image_sign_info {
+	const char *keydir;		/* Directory conaining keys */
+	const char *keyname;		/* Name of key to use */
+	void *fit;			/* Pointer to FIT blob */
+	int node_offset;		/* Offset of signature node */
+	struct image_sig_algo *algo;	/* Algorithm information */
+	const void *fdt_blob;		/* FDT containing public keys */
+	int required_keynode;		/* Node offset of key to use: -1=any */
+	const char *require_keys;	/* Value for 'required' property */
+};
+
+/* A part of an image, used for hashing */
+struct image_region {
+	const void *data;
+	int size;
+};
+
+struct image_sig_algo {
+	const char *name;		/* Name of algorithm */
+
+	/**
+	 * sign() - calculate and return signature for given input data
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @data:	Pointer to the input data
+	 * @data_len:	Data length
+	 * @sigp:	Set to an allocated buffer holding the signature
+	 * @sig_len:	Set to length of the calculated hash
+	 *
+	 * This computes input data signature according to selected algorithm.
+	 * Resulting signature value is placed in an allocated buffer, the
+	 * pointer is returned as *sigp. The length of the calculated
+	 * signature is returned via the sig_len pointer argument. The caller
+	 * should free *sigp.
+	 *
+	 * @return: 0, on success, -ve on error
+	 */
+	int (*sign)(struct image_sign_info *info,
+		    const struct image_region region[],
+		    int region_count, uint8_t **sigp, uint *sig_len);
+
+	/**
+	 * add_verify_data() - Add verification information to FDT
+	 *
+	 * Add public key information to the FDT node, suitable for
+	 * verification at run-time. The information added depends on the
+	 * algorithm being used.
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @keydest:	Destination FDT blob for public key data
+	 * @return: 0, on success, -ve on error
+	 */
+	int (*add_verify_data)(struct image_sign_info *info, void *keydest);
+
+	/**
+	 * verify() - Verify a signature against some data
+	 *
+	 * @info:	Specifies key and FIT information
+	 * @data:	Pointer to the input data
+	 * @data_len:	Data length
+	 * @sig:	Signature
+	 * @sig_len:	Number of bytes in signature
+	 * @return 0 if verified, -ve on error
+	 */
+	int (*verify)(struct image_sign_info *info,
+		      const struct image_region region[], int region_count,
+		      uint8_t *sig, uint sig_len);
+};
+
+/**
+ * image_get_sig_algo() - Look up a signature algortihm
+ *
+ * @param name		Name of algorithm
+ * @return pointer to algorithm information, or NULL if not found
+ */
+struct image_sig_algo *image_get_sig_algo(const char *name);
+
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
 {
diff --git a/tools/Makefile b/tools/Makefile
index 0452e65..a58bb98 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -79,6 +79,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-y += 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
@@ -159,6 +160,10 @@ HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c))
 BINS	:= $(addprefix $(obj),$(sort $(BIN_FILES-y)))
 LIBFDT_OBJS	:= $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y))
 
+# We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host
+FIT_SIG_OBJ_FILES	:= image-sig.o
+FIT_SIG_OBJS		:= $(addprefix $(obj),$(FIT_SIG_OBJ_FILES))
+
 HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y))
 NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y))
 
@@ -213,6 +218,7 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)image-fit.o \
 			$(obj)image.o \
 			$(obj)image-host.o \
+			$(FIT_SIG_OBJS) \
 			$(obj)imximage.o \
 			$(obj)kwbimage.o \
 			$(obj)pblimage.o \
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 32/45] image: Support signing of images
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (30 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 31/45] image: Add signing infrastructure Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 33/45] image: Add RSA support for image signing Simon Glass
                   ` (14 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Adjust how signing enable works in image.h
- Fix FDT error handling in fit_image_write_sig()
- Fix checkpatch checks about parenthesis alignment
- Fix checkpatch warnings about split strings
- Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing

 common/image-fit.c             |  85 ++++++++++++++-----
 common/image-sig.c             | 148 ++++++++++++++++++++++++++++++++
 doc/uImage.FIT/sign-images.its |  42 ++++++++++
 include/image.h                |  59 ++++++++++++-
 tools/fit_image.c              |   2 +-
 tools/image-host.c             | 186 ++++++++++++++++++++++++++++++++++++++---
 6 files changed, 484 insertions(+), 38 deletions(-)
 create mode 100644 doc/uImage.FIT/sign-images.its

diff --git a/common/image-fit.c b/common/image-fit.c
index 5dcb0c6..30790d3 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -31,6 +31,8 @@
 #include <time.h>
 #else
 #include <common.h>
+#include <errno.h>
+DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 
 #include <bootstage.h>
@@ -233,42 +235,45 @@ 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
  *
+ * This function avoid using puts() since it prints a newline on the host
+ * but does not in U-Boot.
+ *
  * 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;
+	char *algo;
+	int required;
+	int ret, i;
 
-	debug("%s  Hash node:    '%s'\n", p,
+	debug("%s  %s node:    '%s'\n", p, type,
 	      fit_get_name(fit, noffset, NULL));
-
-	printf("%s  Hash algo:    ", p);
+	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 {
@@ -277,7 +282,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);
+	}
 }
 
 /**
@@ -302,8 +318,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");
+	}
 }
 
 /**
@@ -939,14 +959,24 @@ int fit_image_verify(const void *fit, int image_noffset)
 {
 	const void	*data;
 	size_t		size;
-	int		noffset;
+	int		noffset = 0;
 	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)) {
 		err_msg = "Can't get image data/size";
-		return 0;
+		goto error;
+	}
+
+	/* 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 */
@@ -967,6 +997,15 @@ int fit_image_verify(const void *fit, int image_noffset)
 						 &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("+ ");
 		}
 	}
 
diff --git a/common/image-sig.c b/common/image-sig.c
index 841c662..1401c75 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -22,6 +22,8 @@
 #include <time.h>
 #else
 #include <common.h>
+#include <malloc.h>
+DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
 #include <errno.h>
 #include <image.h>
@@ -40,3 +42,149 @@ struct image_sig_algo *image_get_sig_algo(const char *name)
 
 	return NULL;
 }
+
+static int fit_image_setup_verify(struct image_sign_info *info,
+		const void *fit, int noffset, int required_keynode,
+		char **err_msgp)
+{
+	char *algo_name;
+
+	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+		*err_msgp = "Can't get hash algo property";
+		return -1;
+	}
+	memset(info, '\0', sizeof(*info));
+	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	info->fit = (void *)fit;
+	info->node_offset = noffset;
+	info->algo = image_get_sig_algo(algo_name);
+	info->fdt_blob = gd_fdt_blob();
+	info->required_keynode = required_keynode;
+	printf("%s:%s", algo_name, info->keyname);
+
+	if (!info->algo) {
+		*err_msgp = "Unknown signature algorithm";
+		return -1;
+	}
+
+	return 0;
+}
+
+int fit_image_check_sig(const void *fit, int noffset, const void *data,
+		size_t size, int required_keynode, char **err_msgp)
+{
+	struct image_sign_info info;
+	struct image_region region;
+	uint8_t *fit_value;
+	int fit_value_len;
+
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	region.data = data;
+	region.size = size;
+
+	if (info.algo->verify(&info, &region, 1, fit_value, fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_image_verify_sig(const void *fit, int image_noffset,
+		const char *data, size_t size, const void *sig_blob,
+		int sig_offset)
+{
+	int noffset;
+	int ndepth;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes 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);
+
+		if (!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("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	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 -1;
+}
+
+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)
+{
+	int verify_count = 0;
+	int ndepth, noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	*no_sigsp = 1;
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	for (ndepth = 0, noffset = fdt_next_subnode(sig_blob, sig_node,
+						     &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(sig_blob, noffset,
+						   &ndepth)) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "image"))
+			continue;
+		ret = fit_image_verify_sig(fit, image_noffset, data, size,
+					sig_blob, noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+		verify_count++;
+	}
+
+	if (verify_count)
+		*no_sigsp = 0;
+
+	return 0;
+}
diff --git a/doc/uImage.FIT/sign-images.its b/doc/uImage.FIT/sign-images.its
new file mode 100644
index 0000000..f69326a
--- /dev/null
+++ b/doc/uImage.FIT/sign-images.its
@@ -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";
+		};
+	};
+};
diff --git a/include/image.h b/include/image.h
index 695473a..99015cd 100644
--- a/include/image.h
+++ b/include/image.h
@@ -618,12 +618,26 @@ int fit_image_hash_get_value(const void *fit, int noffset, uint8_t **value,
 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);
@@ -762,6 +776,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)
 {
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 8f51159..e0675d7 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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);
diff --git a/tools/image-host.c b/tools/image-host.c
index 3ba05de..2836881 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -26,12 +26,8 @@
  */
 
 #include "mkimage.h"
-#include <bootstage.h>
 #include <image.h>
-#include <sha1.h>
-#include <time.h>
-#include <u-boot/crc.h>
-#include <u-boot/md5.h>
+#include <version.h>
 
 /**
  * fit_set_hash_value - set hash value in requested has node
@@ -108,9 +104,165 @@ static int fit_image_process_hash(void *fit, const char *image_name,
 }
 
 /**
- * fit_image_add_verification_data() - calculate/set hash data for image node
+ * fit_image_write_sig() - write the signature to a FIT
  *
- * This adds hash values for a component image node.
+ * This writes the signature and signer data to the FIT.
+ *
+ * @fit: pointer to the FIT format image header
+ * @noffset: hash node offset
+ * @value: signature value to be set
+ * @value_len: signature value length
+ * @comment: Text comment to write (NULL for none)
+ *
+ * returns
+ *     0, on success
+ *     -FDT_ERR_..., on failure
+ */
+static int fit_image_write_sig(void *fit, int noffset, uint8_t *value,
+		int value_len, const char *comment, const char *region_prop,
+		int region_proplen)
+{
+	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);
+	if (!ret) {
+		ret = fdt_setprop_string(fit, noffset, "signer-name",
+					 "mkimage");
+	}
+	if (!ret) {
+		ret = fdt_setprop_string(fit, noffset, "signer-version",
+				  PLAIN_VERSION);
+	}
+	if (comment && !ret)
+		ret = fdt_setprop_string(fit, noffset, "comment", comment);
+	if (!ret)
+		ret = fit_set_timestamp(fit, noffset, time(NULL));
+	if (region_prop && !ret) {
+		uint32_t strdata[2];
+
+		ret = fdt_setprop(fit, noffset, "hashed-nodes",
+				   region_prop, region_proplen);
+		strdata[0] = 0;
+		strdata[1] = cpu_to_fdt32(string_size);
+		if (!ret) {
+			ret = fdt_setprop(fit, noffset, "hashed-strings",
+					  strdata, sizeof(strdata));
+		}
+	}
+
+	return ret;
+}
+
+static int fit_image_setup_sig(struct image_sign_info *info,
+		const char *keydir, void *fit, const char *image_name,
+		int noffset, const char *require_keys)
+{
+	const char *node_name;
+	char *algo_name;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	if (fit_image_hash_get_algo(fit, noffset, &algo_name)) {
+		printf("Can't get algo property for '%s' signature node in '%s' image node\n",
+		       node_name, image_name);
+		return -1;
+	}
+
+	memset(info, '\0', sizeof(*info));
+	info->keydir = keydir;
+	info->keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+	info->fit = fit;
+	info->node_offset = noffset;
+	info->algo = image_get_sig_algo(algo_name);
+	info->require_keys = require_keys;
+	if (!info->algo) {
+		printf("Unsupported signature algorithm (%s) for '%s' signature node in '%s' image node\n",
+		       algo_name, node_name, image_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_image_process_sig- Process a single subnode of the images/ node
+ *
+ * Check each subnode and process accordingly. For signature nodes we
+ * generate a signed hash of the supplised data and store it in the node.
+ *
+ * @keydir:	Directory containing keys to use for signing
+ * @keydest:	Destination FDT blob to write public keys into
+ * @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
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
+ * @return 0 if ok, -1 on error
+ */
+static int fit_image_process_sig(const char *keydir, void *keydest,
+		void *fit, const char *image_name,
+		int noffset, const void *data, size_t size,
+		const char *comment, int require_keys)
+{
+	struct image_sign_info info;
+	struct image_region region;
+	const char *node_name;
+	uint8_t *value;
+	uint value_len;
+	int ret;
+
+	if (fit_image_setup_sig(&info, keydir, fit, image_name, noffset,
+				require_keys ? "image" : NULL))
+		return -1;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	region.data = data;
+	region.size = size;
+	ret = info.algo->sign(&info, &region, 1, &value, &value_len);
+	if (ret) {
+		printf("Failed to sign '%s' signature node in '%s' image node: %d\n",
+		       node_name, image_name, ret);
+
+		/* We allow keys to be missing */
+		if (ret == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	ret = fit_image_write_sig(fit, noffset, value, value_len, comment,
+			NULL, 0);
+	if (ret) {
+		printf("Can't write signature for '%s' signature node in '%s' image node: %s\n",
+		       node_name, image_name, fdt_strerror(ret));
+		return -1;
+	}
+	free(value);
+
+	/* Get keyname again, as FDT has changed and invalidated our pointer */
+	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+	/* Write the public key into the supplied FDT file */
+	if (keydest && info.algo->add_verify_data(&info, keydest)) {
+		printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+		       node_name, image_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * fit_image_add_verification_data() - calculate/set verig. data for image node
+ *
+ * This adds hash and signature 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
@@ -133,11 +285,17 @@ static int fit_image_process_hash(void *fit, const char *image_name,
  *
  * For signature details, please see doc/uImage.FIT/signature.txt
  *
+ * @keydir	Directory containing *.key and *.crt files (or NULL)
+ * @keydest	FDT Blob to write public keys into (NULL if none)
  * @fit:	Pointer to the FIT format image header
  * @image_noffset: Requested component image node
+ * @comment:	Comment to add to signature nodes
+ * @require_keys: Mark all keys as 'required'
  * @return: 0 on success, <0 on failure
  */
-int fit_image_add_verification_data(void *fit, int image_noffset)
+int fit_image_add_verification_data(const char *keydir, void *keydest,
+		void *fit, int image_noffset, const char *comment,
+		int require_keys)
 {
 	const char *image_name;
 	const void *data;
@@ -171,6 +329,12 @@ int fit_image_add_verification_data(void *fit, int image_noffset)
 			     strlen(FIT_HASH_NODENAME))) {
 			ret = fit_image_process_hash(fit, image_name, noffset,
 						data, size);
+		} else if (IMAGE_ENABLE_SIGN && keydir &&
+			   !strncmp(node_name, FIT_SIG_NODENAME,
+				strlen(FIT_SIG_NODENAME))) {
+			ret = fit_image_process_sig(keydir, keydest,
+				fit, image_name, noffset, data, size,
+				comment, require_keys);
 		}
 		if (ret)
 			return -1;
@@ -179,7 +343,8 @@ int fit_image_add_verification_data(void *fit, int image_noffset)
 	return 0;
 }
 
-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 images_noffset;
 	int noffset;
@@ -204,7 +369,8 @@ int fit_add_verification_data(void *fit)
 		 * Direct child node of the images parent node,
 		 * i.e. component image node.
 		 */
-		ret = fit_image_add_verification_data(fit, noffset);
+		ret = fit_image_add_verification_data(keydir, keydest,
+				fit, noffset, comment, require_keys);
 		if (ret)
 			return ret;
 	}
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 33/45] image: Add RSA support for image signing
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (31 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 32/45] image: Support signing of images Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 34/45] mkimage: Put FIT loading in function and tidy error handling Simon Glass
                   ` (13 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add sanity checks on key sizes in RSA (improves security)
- Avoid using malloc in RSA routines (for smaller SPL code size)
- Build signing support unconditionally in mkimage
- Fix checkpatch checks about parenthesis alignment
- Fix spelling of multiply in rsa-verify.c
- Only build RSA support into mkimage if CONFIG_RSA is defined
- Support RSA library version without ERR_remove_thread_state()

 Makefile             |   1 +
 README               |  10 ++
 common/image-sig.c   |   7 +
 config.mk            |   1 +
 include/rsa.h        | 108 ++++++++++++
 lib/rsa/Makefile     |  48 ++++++
 lib/rsa/rsa-sign.c   | 460 +++++++++++++++++++++++++++++++++++++++++++++++++++
 lib/rsa/rsa-verify.c | 385 ++++++++++++++++++++++++++++++++++++++++++
 tools/Makefile       |  13 +-
 9 files changed, 1031 insertions(+), 2 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

diff --git a/Makefile b/Makefile
index 55bd55c..b6397b9 100644
--- a/Makefile
+++ b/Makefile
@@ -242,6 +242,7 @@ OBJS := $(addprefix $(obj),$(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
diff --git a/README b/README
index de753f3..d8ccc3e 100644
--- a/README
+++ b/README
@@ -2481,6 +2481,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
 
diff --git a/common/image-sig.c b/common/image-sig.c
index 1401c75..1bdb4bf 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -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)
diff --git a/config.mk b/config.mk
index 9886415..1542e66 100644
--- a/config.mk
+++ b/config.mk
@@ -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)
diff --git a/include/rsa.h b/include/rsa.h
new file mode 100644
index 0000000..a5dd676
--- /dev/null
+++ b/include/rsa.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * (C) Copyright 2008 Semihalf
+ *
+ * (C) Copyright 2000-2006
+ * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _RSA_H
+#define _RSA_H
+
+#include <errno.h>
+#include <image.h>
+
+#if IMAGE_ENABLE_SIGN
+/**
+ * sign() - calculate and return signature for given input data
+ *
+ * @info:	Specifies key and FIT information
+ * @data:	Pointer to the input data
+ * @data_len:	Data length
+ * @sigp:	Set to an allocated buffer holding the signature
+ * @sig_len:	Set to length of the calculated hash
+ *
+ * This computes input data signature according to selected algorithm.
+ * Resulting signature value is placed in an allocated buffer, the
+ * pointer is returned as *sigp. The length of the calculated
+ * signature is returned via the sig_len pointer argument. The caller
+ * should free *sigp.
+ *
+ * @return: 0, on success, -ve on error
+ */
+int rsa_sign(struct image_sign_info *info,
+	     const struct image_region region[],
+	     int region_count, uint8_t **sigp, uint *sig_len);
+
+/**
+ * add_verify_data() - Add verification information to FDT
+ *
+ * Add public key information to the FDT node, suitable for
+ * verification at run-time. The information added depends on the
+ * algorithm being used.
+ *
+ * @info:	Specifies key and FIT information
+ * @keydest:	Destination FDT blob for public key data
+ * @return: 0, on success, -ve on error
+*/
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest);
+#else
+static inline int rsa_sign(struct image_sign_info *info,
+		const struct image_region region[], int region_count,
+		uint8_t **sigp, uint *sig_len)
+{
+	return -ENXIO;
+}
+
+static inline int rsa_add_verify_data(struct image_sign_info *info,
+				      void *keydest)
+{
+	return -ENXIO;
+}
+#endif
+
+#if IMAGE_ENABLE_VERIFY
+/**
+ * rsa_verify() - Verify a signature against some data
+ *
+ * Verify a RSA PKCS1.5 signature against an expected hash.
+ *
+ * @info:	Specifies key and FIT information
+ * @data:	Pointer to the input data
+ * @data_len:	Data length
+ * @sig:	Signature
+ * @sig_len:	Number of bytes in signature
+ * @return 0 if verified, -ve on error
+ */
+int rsa_verify(struct image_sign_info *info,
+	       const struct image_region region[], int region_count,
+	       uint8_t *sig, uint sig_len);
+#else
+static inline int rsa_verify(struct image_sign_info *info,
+		const struct image_region region[], int region_count,
+		uint8_t *sig, uint sig_len)
+{
+	return -ENXIO;
+}
+#endif
+
+#endif
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
new file mode 100644
index 0000000..9eb3e40
--- /dev/null
+++ b/lib/rsa/Makefile
@@ -0,0 +1,48 @@
+#
+# Copyright (c) 2013, Google Inc.
+#
+# (C) Copyright 2000-2007
+# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB	= $(obj)librsa.o
+
+ifdef CONFIG_FIT_SIGNATURE
+COBJS-$(CONFIG_RSA) += rsa-verify.o
+endif
+
+COBJS	:= $(sort $(COBJS-y))
+SRCS	:= $(COBJS:.o=.c)
+OBJS	:= $(addprefix $(obj),$(COBJS))
+
+$(LIB):	$(obj).depend $(OBJS)
+	$(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
new file mode 100644
index 0000000..a75ae24
--- /dev/null
+++ b/lib/rsa/rsa-sign.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "mkimage.h"
+#include <stdio.h>
+#include <string.h>
+#include <error.h>
+#include <image.h>
+#include <time.h>
+#include <openssl/rsa.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/ssl.h>
+#include <openssl/evp.h>
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#define HAVE_ERR_REMOVE_THREAD_STATE
+#endif
+
+static int rsa_err(const char *msg)
+{
+	unsigned long sslErr = ERR_get_error();
+
+	fprintf(stderr, "%s", msg);
+	fprintf(stderr, ": %s\n",
+		ERR_error_string(sslErr, 0));
+
+	return -1;
+}
+
+/**
+ * rsa_get_pub_key() - read a public key from a .crt file
+ *
+ * @keydir:	Directory containins the key
+ * @name	Name of key file (will have a .crt extension)
+ * @rsap	Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_pub_key(const char *keydir, const char *name, RSA **rsap)
+{
+	char path[1024];
+	EVP_PKEY *key;
+	X509 *cert;
+	RSA *rsa;
+	FILE *f;
+	int ret;
+
+	*rsap = NULL;
+	snprintf(path, sizeof(path), "%s/%s.crt", keydir, name);
+	f = fopen(path, "r");
+	if (!f) {
+		fprintf(stderr, "Couldn't open RSA certificate: '%s': %s\n",
+			path, strerror(errno));
+		return -EACCES;
+	}
+
+	/* Read the certificate */
+	cert = NULL;
+	if (!PEM_read_X509(f, &cert, NULL, NULL)) {
+		rsa_err("Couldn't read certificate");
+		ret = -EINVAL;
+		goto err_cert;
+	}
+
+	/* Get the public key from the certificate. */
+	key = X509_get_pubkey(cert);
+	if (!key) {
+		rsa_err("Couldn't read public key\n");
+		ret = -EINVAL;
+		goto err_pubkey;
+	}
+
+	/* Convert to a RSA_style key. */
+	rsa = EVP_PKEY_get1_RSA(key);
+	if (!rsa) {
+		rsa_err("Couldn't convert to a RSA style key");
+		goto err_rsa;
+	}
+	fclose(f);
+	EVP_PKEY_free(key);
+	X509_free(cert);
+	*rsap = rsa;
+
+	return 0;
+
+err_rsa:
+	EVP_PKEY_free(key);
+err_pubkey:
+	X509_free(cert);
+err_cert:
+	fclose(f);
+	return ret;
+}
+
+/**
+ * rsa_get_priv_key() - read a private key from a .key file
+ *
+ * @keydir:	Directory containins the key
+ * @name	Name of key file (will have a .key extension)
+ * @rsap	Returns RSA object, or NULL on failure
+ * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL)
+ */
+static int rsa_get_priv_key(const char *keydir, const char *name, RSA **rsap)
+{
+	char path[1024];
+	RSA *rsa;
+	FILE *f;
+
+	*rsap = NULL;
+	snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
+	f = fopen(path, "r");
+	if (!f) {
+		fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n",
+			path, strerror(errno));
+		return -ENOENT;
+	}
+
+	rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path);
+	if (!rsa) {
+		rsa_err("Failure reading private key");
+		fclose(f);
+		return -EPROTO;
+	}
+	fclose(f);
+	*rsap = rsa;
+
+	return 0;
+}
+
+static int rsa_init(void)
+{
+	int ret;
+
+	ret = SSL_library_init();
+	if (!ret) {
+		fprintf(stderr, "Failure to init SSL library\n");
+		return -1;
+	}
+	SSL_load_error_strings();
+
+	OpenSSL_add_all_algorithms();
+	OpenSSL_add_all_digests();
+	OpenSSL_add_all_ciphers();
+
+	return 0;
+}
+
+static void rsa_remove(void)
+{
+	CRYPTO_cleanup_all_ex_data();
+	ERR_free_strings();
+#ifdef HAVE_ERR_REMOVE_THREAD_STATE
+	ERR_remove_thread_state(NULL);
+#else
+	ERR_remove_state(0);
+#endif
+	EVP_cleanup();
+}
+
+static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
+		int region_count, uint8_t **sigp, uint *sig_size)
+{
+	EVP_PKEY *key;
+	EVP_MD_CTX *context;
+	int size, ret = 0;
+	uint8_t *sig;
+	int i;
+
+	key = EVP_PKEY_new();
+	if (!key)
+		return rsa_err("EVP_PKEY object creation failed");
+
+	if (!EVP_PKEY_set1_RSA(key, rsa)) {
+		ret = rsa_err("EVP key setup failed");
+		goto err_set;
+	}
+
+	size = EVP_PKEY_size(key);
+	sig = malloc(size);
+	if (!sig) {
+		fprintf(stderr, "Out of memory for signature (%d bytes)\n",
+			size);
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	context = EVP_MD_CTX_create();
+	if (!context) {
+		ret = rsa_err("EVP context creation failed");
+		goto err_create;
+	}
+	EVP_MD_CTX_init(context);
+	if (!EVP_SignInit(context, EVP_sha1())) {
+		ret = rsa_err("Signer setup failed");
+		goto err_sign;
+	}
+
+	for (i = 0; i < region_count; i++) {
+		if (!EVP_SignUpdate(context, region[i].data, region[i].size)) {
+			ret = rsa_err("Signing data failed");
+			goto err_sign;
+		}
+	}
+
+	if (!EVP_SignFinal(context, sig, sig_size, key)) {
+		ret = rsa_err("Could not obtain signature");
+		goto err_sign;
+	}
+	EVP_MD_CTX_cleanup(context);
+	EVP_MD_CTX_destroy(context);
+	EVP_PKEY_free(key);
+
+	debug("Got signature: %d bytes, expected %d\n", *sig_size, size);
+	*sigp = sig;
+	*sig_size = size;
+
+	return 0;
+
+err_sign:
+	EVP_MD_CTX_destroy(context);
+err_create:
+	free(sig);
+err_alloc:
+err_set:
+	EVP_PKEY_free(key);
+	return ret;
+}
+
+int rsa_sign(struct image_sign_info *info,
+	     const struct image_region region[], int region_count,
+	     uint8_t **sigp, uint *sig_len)
+{
+	RSA *rsa;
+	int ret;
+
+	ret = rsa_init();
+	if (ret)
+		return ret;
+
+	ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
+	if (ret)
+		goto err_priv;
+	ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
+	if (ret)
+		goto err_sign;
+
+	RSA_free(rsa);
+	rsa_remove();
+
+	return ret;
+
+err_sign:
+	RSA_free(rsa);
+err_priv:
+	rsa_remove();
+	return ret;
+}
+
+/*
+ * rsa_get_params(): - Get the important parameters of an RSA public key
+ */
+int rsa_get_params(RSA *key, uint32_t *n0_invp, BIGNUM **modulusp,
+		   BIGNUM **r_squaredp)
+{
+	BIGNUM *big1, *big2, *big32, *big2_32;
+	BIGNUM *n, *r, *r_squared, *tmp;
+	BN_CTX *bn_ctx = BN_CTX_new();
+	int ret = 0;
+
+	/* Initialize BIGNUMs */
+	big1 = BN_new();
+	big2 = BN_new();
+	big32 = BN_new();
+	r = BN_new();
+	r_squared = BN_new();
+	tmp = BN_new();
+	big2_32 = BN_new();
+	n = BN_new();
+	if (!big1 || !big2 || !big32 || !r || !r_squared || !tmp || !big2_32 ||
+	    !n) {
+		fprintf(stderr, "Out of memory (bignum)\n");
+		return -ENOMEM;
+	}
+
+	if (!BN_copy(n, key->n) || !BN_set_word(big1, 1L) ||
+	    !BN_set_word(big2, 2L) || !BN_set_word(big32, 32L))
+		ret = -1;
+
+	/* big2_32 = 2^32 */
+	if (!BN_exp(big2_32, big2, big32, bn_ctx))
+		ret = -1;
+
+	/* Calculate n0_inv = -1 / n[0] mod 2^32 */
+	if (!BN_mod_inverse(tmp, n, big2_32, bn_ctx) ||
+	    !BN_sub(tmp, big2_32, tmp))
+		ret = -1;
+	*n0_invp = BN_get_word(tmp);
+
+	/* Calculate R = 2^(# of key bits) */
+	if (!BN_set_word(tmp, BN_num_bits(n)) ||
+	    !BN_exp(r, big2, tmp, bn_ctx))
+		ret = -1;
+
+	/* Calculate r_squared = R^2 mod n */
+	if (!BN_copy(r_squared, r) ||
+	    !BN_mul(tmp, r_squared, r, bn_ctx) ||
+	    !BN_mod(r_squared, tmp, n, bn_ctx))
+		ret = -1;
+
+	*modulusp = n;
+	*r_squaredp = r_squared;
+
+	BN_free(big1);
+	BN_free(big2);
+	BN_free(big32);
+	BN_free(r);
+	BN_free(tmp);
+	BN_free(big2_32);
+	if (ret) {
+		fprintf(stderr, "Bignum operations failed\n");
+		return -ENOMEM;
+	}
+
+	return ret;
+}
+
+static int fdt_add_bignum(void *blob, int noffset, const char *prop_name,
+			  BIGNUM *num, int num_bits)
+{
+	int nwords = num_bits / 32;
+	int size;
+	uint32_t *buf, *ptr;
+	BIGNUM *tmp, *big2, *big32, *big2_32;
+	BN_CTX *ctx;
+	int ret;
+
+	tmp = BN_new();
+	big2 = BN_new();
+	big32 = BN_new();
+	big2_32 = BN_new();
+	if (!tmp || !big2 || !big32 || !big2_32) {
+		fprintf(stderr, "Out of memory (bignum)\n");
+		return -ENOMEM;
+	}
+	ctx = BN_CTX_new();
+	if (!tmp) {
+		fprintf(stderr, "Out of memory (bignum context)\n");
+		return -ENOMEM;
+	}
+	BN_set_word(big2, 2L);
+	BN_set_word(big32, 32L);
+	BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */
+
+	size = nwords * sizeof(uint32_t);
+	buf = malloc(size);
+	if (!buf) {
+		fprintf(stderr, "Out of memory (%d bytes)\n", size);
+		return -ENOMEM;
+	}
+
+	/* Write out modulus as big endian array of integers */
+	for (ptr = buf + nwords - 1; ptr >= buf; ptr--) {
+		BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */
+		*ptr = cpu_to_fdt32(BN_get_word(tmp));
+		BN_rshift(num, num, 32); /*  N = N/B */
+	}
+
+	ret = fdt_setprop(blob, noffset, prop_name, buf, size);
+	if (ret) {
+		fprintf(stderr, "Failed to write public key to FIT\n");
+		return -ENOSPC;
+	}
+	free(buf);
+	BN_free(tmp);
+	BN_free(big2);
+	BN_free(big32);
+	BN_free(big2_32);
+
+	return ret;
+}
+
+int rsa_add_verify_data(struct image_sign_info *info, void *keydest)
+{
+	BIGNUM *modulus, *r_squared;
+	uint32_t n0_inv;
+	int parent, node;
+	char name[100];
+	int ret;
+	int bits;
+	RSA *rsa;
+
+	debug("%s: Getting verification data\n", __func__);
+	ret = rsa_get_pub_key(info->keydir, info->keyname, &rsa);
+	if (ret)
+		return ret;
+	ret = rsa_get_params(rsa, &n0_inv, &modulus, &r_squared);
+	if (ret)
+		return ret;
+	bits = BN_num_bits(modulus);
+	parent = fdt_subnode_offset(keydest, 0, FIT_SIG_NODENAME);
+	if (parent == -FDT_ERR_NOTFOUND) {
+		parent = fdt_add_subnode(keydest, 0, FIT_SIG_NODENAME);
+		if (parent < 0) {
+			fprintf(stderr, "Couldn't create signature node: %s\n",
+				fdt_strerror(parent));
+			return -EINVAL;
+		}
+	}
+
+	/* Either create or overwrite the named key node */
+	snprintf(name, sizeof(name), "key-%s", info->keyname);
+	node = fdt_subnode_offset(keydest, parent, name);
+	if (node == -FDT_ERR_NOTFOUND) {
+		node = fdt_add_subnode(keydest, parent, name);
+		if (node < 0) {
+			fprintf(stderr, "Could not create key subnode: %s\n",
+				fdt_strerror(node));
+			return -EINVAL;
+		}
+	} else if (node < 0) {
+		fprintf(stderr, "Cannot select keys parent: %s\n",
+			fdt_strerror(node));
+		return -ENOSPC;
+	}
+
+	ret = fdt_setprop_string(keydest, node, "key-name-hint",
+				 info->keyname);
+	ret |= fdt_setprop_u32(keydest, node, "rsa,num-bits", bits);
+	ret |= fdt_setprop_u32(keydest, node, "rsa,n0-inverse", n0_inv);
+	ret |= fdt_add_bignum(keydest, node, "rsa,modulus", modulus, bits);
+	ret |= fdt_add_bignum(keydest, node, "rsa,r-squared", r_squared, bits);
+	ret |= fdt_setprop_string(keydest, node, FIT_ALGO_PROP,
+				  info->algo->name);
+	if (info->require_keys) {
+		fdt_setprop_string(keydest, node, "required",
+				   info->require_keys);
+	}
+	BN_free(modulus);
+	BN_free(r_squared);
+	if (ret)
+		return -EIO;
+
+	return 0;
+}
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
new file mode 100644
index 0000000..6a02689
--- /dev/null
+++ b/lib/rsa/rsa-verify.c
@@ -0,0 +1,385 @@
+/*
+ * Copyright (c) 2013, Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <fdtdec.h>
+#include <rsa.h>
+#include <sha1.h>
+#include <asm/byteorder.h>
+#include <asm/errno.h>
+#include <asm/unaligned.h>
+
+/**
+ * struct rsa_public_key - holder for a public key
+ *
+ * An RSA public key consists of a modulus (typically called N), the inverse
+ * and R^2, where R is 2^(# key bits).
+ */
+struct rsa_public_key {
+	uint len;		/* Length of modulus[] in number of uint32_t */
+	uint32_t n0inv;		/* -1 / modulus[0] mod 2^32 */
+	uint32_t *modulus;	/* modulus as little endian array */
+	uint32_t *rr;		/* R^2 as little endian array */
+};
+
+#define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
+
+#define RSA2048_BYTES	(2048 / 8)
+
+/* This is the minimum/maximum key size we support, in bits */
+#define RSA_MIN_KEY_BITS	2048
+#define RSA_MAX_KEY_BITS	2048
+
+/* This is the maximum signature length that we support, in bits */
+#define RSA_MAX_SIG_BITS	2048
+
+static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
+	0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
+	0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
+	0x05, 0x00, 0x04, 0x14
+};
+
+/**
+ * subtract_modulus() - subtract modulus from the given value
+ *
+ * @key:	Key containing modulus to subtract
+ * @num:	Number to subtract modulus from, as little endian word array
+ */
+static void subtract_modulus(const struct rsa_public_key *key, uint32_t num[])
+{
+	int64_t acc = 0;
+	uint i;
+
+	for (i = 0; i < key->len; i++) {
+		acc += (uint64_t)num[i] - key->modulus[i];
+		num[i] = (uint32_t)acc;
+		acc >>= 32;
+	}
+}
+
+/**
+ * greater_equal_modulus() - check if a value is >= modulus
+ *
+ * @key:	Key containing modulus to check
+ * @num:	Number to check against modulus, as little endian word array
+ * @return 0 if num < modulus, 1 if num >= modulus
+ */
+static int greater_equal_modulus(const struct rsa_public_key *key,
+				 uint32_t num[])
+{
+	uint32_t i;
+
+	for (i = key->len - 1; i >= 0; i--) {
+		if (num[i] < key->modulus[i])
+			return 0;
+		if (num[i] > key->modulus[i])
+			return 1;
+	}
+
+	return 1;  /* equal */
+}
+
+/**
+ * montgomery_mul_add_step() - Perform montgomery multiply-add step
+ *
+ * Operation: montgomery result[] += a * b[] / n0inv % modulus
+ *
+ * @key:	RSA key
+ * @result:	Place to put result, as little endian word array
+ * @a:		Multiplier
+ * @b:		Multiplicand, as little endian word array
+ */
+static void montgomery_mul_add_step(const struct rsa_public_key *key,
+		uint32_t result[], const uint32_t a, const uint32_t b[])
+{
+	uint64_t acc_a, acc_b;
+	uint32_t d0;
+	uint i;
+
+	acc_a = (uint64_t)a * b[0] + result[0];
+	d0 = (uint32_t)acc_a * key->n0inv;
+	acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a;
+	for (i = 1; i < key->len; i++) {
+		acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i];
+		acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] +
+				(uint32_t)acc_a;
+		result[i - 1] = (uint32_t)acc_b;
+	}
+
+	acc_a = (acc_a >> 32) + (acc_b >> 32);
+
+	result[i - 1] = (uint32_t)acc_a;
+
+	if (acc_a >> 32)
+		subtract_modulus(key, result);
+}
+
+/**
+ * montgomery_mul() - Perform montgomery mutitply
+ *
+ * Operation: montgomery result[] = a[] * b[] / n0inv % modulus
+ *
+ * @key:	RSA key
+ * @result:	Place to put result, as little endian word array
+ * @a:		Multiplier, as little endian word array
+ * @b:		Multiplicand, as little endian word array
+ */
+static void montgomery_mul(const struct rsa_public_key *key,
+		uint32_t result[], uint32_t a[], const uint32_t b[])
+{
+	uint i;
+
+	for (i = 0; i < key->len; ++i)
+		result[i] = 0;
+	for (i = 0; i < key->len; ++i)
+		montgomery_mul_add_step(key, result, a[i], b);
+}
+
+/**
+ * pow_mod() - in-place public exponentiation
+ *
+ * @key:	RSA key
+ * @inout:	Big-endian word array containing value and result
+ */
+static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
+{
+	uint32_t *result, *ptr;
+	uint i;
+
+	/* Sanity check for stack size - key->len is in 32-bit words */
+	if (key->len > RSA_MAX_KEY_BITS / 32) {
+		debug("RSA key words %u exceeds maximum %d\n", key->len,
+		      RSA_MAX_KEY_BITS / 32);
+		return -EINVAL;
+	}
+
+	uint32_t val[key->len], acc[key->len], tmp[key->len];
+	result = tmp;  /* Re-use location. */
+
+	/* Convert from big endian byte array to little endian word array. */
+	for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--)
+		val[i] = get_unaligned_be32(ptr);
+
+	montgomery_mul(key, acc, val, key->rr);  /* axx = a * RR / R mod M */
+	for (i = 0; i < 16; i += 2) {
+		montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod M */
+		montgomery_mul(key, acc, tmp, tmp); /* acc = tmp^2 / R mod M */
+	}
+	montgomery_mul(key, result, acc, val);  /* result = XX * a / R mod M */
+
+	/* Make sure result < mod; result is@most 1x mod too large. */
+	if (greater_equal_modulus(key, result))
+		subtract_modulus(key, result);
+
+	/* Convert to bigendian byte array */
+	for (i = key->len - 1, ptr = inout; (int)i >= 0; i--, ptr++)
+		put_unaligned_be32(result[i], ptr);
+
+	return 0;
+}
+
+static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
+		const uint32_t sig_len, const uint8_t *hash)
+{
+	const uint8_t *padding;
+	int pad_len;
+	int ret;
+
+	if (!key || !sig || !hash)
+		return -EIO;
+
+	if (sig_len != (key->len * sizeof(uint32_t))) {
+		debug("Signature is of incorrect length %d\n", sig_len);
+		return -EINVAL;
+	}
+
+	/* Sanity check for stack size */
+	if (sig_len > RSA_MAX_SIG_BITS / 8) {
+		debug("Signature length %u exceeds maximum %d\n", sig_len,
+		      RSA_MAX_SIG_BITS / 8);
+		return -EINVAL;
+	}
+
+	uint32_t buf[sig_len / sizeof(uint32_t)];
+
+	memcpy(buf, sig, sig_len);
+
+	ret = pow_mod(key, buf);
+	if (ret)
+		return ret;
+
+	/* Determine padding to use depending on the signature type. */
+	padding = padding_sha1_rsa2048;
+	pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
+
+	/* Check pkcs1.5 padding bytes. */
+	if (memcmp(buf, padding, pad_len)) {
+		debug("In RSAVerify(): Padding check failed!\n");
+		return -EINVAL;
+	}
+
+	/* Check hash. */
+	if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) {
+		debug("In RSAVerify(): Hash check failed!\n");
+		return -EACCES;
+	}
+
+	return 0;
+}
+
+static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int len)
+{
+	int i;
+
+	for (i = 0; i < len; i++)
+		dst[i] = fdt32_to_cpu(src[len - 1 - i]);
+}
+
+static int rsa_verify_with_keynode(struct image_sign_info *info,
+		const void *hash, uint8_t *sig, uint sig_len, int node)
+{
+	const void *blob = info->fdt_blob;
+	struct rsa_public_key key;
+	const void *modulus, *rr;
+	int ret;
+
+	if (node < 0) {
+		debug("%s: Skipping invalid node", __func__);
+		return -EBADF;
+	}
+	if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) {
+		debug("%s: Missing rsa,n0-inverse", __func__);
+		return -EFAULT;
+	}
+	key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0);
+	key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0);
+	modulus = fdt_getprop(blob, node, "rsa,modulus", NULL);
+	rr = fdt_getprop(blob, node, "rsa,r-squared", NULL);
+	if (!key.len || !modulus || !rr) {
+		debug("%s: Missing RSA key info", __func__);
+		return -EFAULT;
+	}
+
+	/* Sanity check for stack size */
+	if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) {
+		debug("RSA key bits %u outside allowed range %d..%d\n",
+		      key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS);
+		return -EFAULT;
+	}
+	key.len /= sizeof(uint32_t) * 8;
+	uint32_t key1[key.len], key2[key.len];
+
+	key.modulus = key1;
+	key.rr = key2;
+	rsa_convert_big_endian(key.modulus, modulus, key.len);
+	rsa_convert_big_endian(key.rr, rr, key.len);
+	if (!key.modulus || !key.rr) {
+		debug("%s: Out of memory", __func__);
+		return -ENOMEM;
+	}
+
+	debug("key length %d\n", key.len);
+	ret = rsa_verify_key(&key, sig, sig_len, hash);
+	if (ret) {
+		printf("%s: RSA failed to verify: %d\n", __func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+int rsa_verify(struct image_sign_info *info,
+	       const struct image_region region[], int region_count,
+	       uint8_t *sig, uint sig_len)
+{
+	const void *blob = info->fdt_blob;
+	uint8_t hash[SHA1_SUM_LEN];
+	int ndepth, noffset;
+	int sig_node, node;
+	char name[100];
+	sha1_context ctx;
+	int ret, i;
+
+	sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found\n", __func__);
+		return -ENOENT;
+	}
+
+	sha1_starts(&ctx);
+	for (i = 0; i < region_count; i++)
+		sha1_update(&ctx, region[i].data, region[i].size);
+	sha1_finish(&ctx, hash);
+
+	/* See if we must use a particular key */
+	if (info->required_keynode != -1) {
+		ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+			info->required_keynode);
+		if (!ret)
+			return ret;
+	}
+
+	/* Look for a key that matches our hint */
+	snprintf(name, sizeof(name), "key-%s", info->keyname);
+	node = fdt_subnode_offset(blob, sig_node, name);
+	ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node);
+	if (!ret)
+		return ret;
+
+	/* No luck, so try each of the keys in turn */
+	for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth);
+			(noffset >= 0) && (ndepth > 0);
+			noffset = fdt_next_node(info->fit, noffset, &ndepth)) {
+		if (ndepth == 1 && noffset != node) {
+			ret = rsa_verify_with_keynode(info, hash, sig, sig_len,
+						      noffset);
+			if (!ret)
+				break;
+		}
+	}
+
+	return ret;
+}
diff --git a/tools/Makefile b/tools/Makefile
index a58bb98..a9a14ed 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -123,6 +123,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
@@ -157,8 +160,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/,$(RSA_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))
 
 # We cannot check CONFIG_FIT_SIGNATURE here since it is not set on the host
 FIT_SIG_OBJ_FILES	:= image-sig.o
@@ -228,8 +233,9 @@ $(obj)mkimage$(SFX):	$(obj)aisimage.o \
 			$(obj)omapimage.o \
 			$(obj)sha1.o \
 			$(obj)ublimage.o \
-			$(LIBFDT_OBJS)
-	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^
+			$(LIBFDT_OBJS) \
+			$(RSA_OBJS)
+	$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
 	$(HOSTSTRIP) $@
 
 $(obj)mk$(BOARD)spl$(SFX):	$(obj)mkexynosspl.o
@@ -265,6 +271,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),)
 	@:
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 34/45] mkimage: Put FIT loading in function and tidy error handling
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (32 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 33/45] image: Add RSA support for image signing Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 35/45] mkimage: Add -k option to specify key directory Simon Glass
                   ` (12 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

The fit_handle_file() function is quite 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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add comment about why mkimage needs to open FIT with O_RDWR
- Fix checkpatch checks about parenthesis alignment
- Fix spelling of quite

 tools/fit_image.c | 96 +++++++++++++++++++++++++++++++++----------------------
 1 file changed, 57 insertions(+), 39 deletions(-)

diff --git a/tools/fit_image.c b/tools/fit_image.c
index e0675d7..ef6ef44 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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 (we need to write hashes/signatures) */
+	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);
-	}
-
-	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);
+		goto err_system;
 	}
 
-	/* 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)
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 35/45] mkimage: Add -k option to specify key directory
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (33 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 34/45] mkimage: Put FIT loading in function and tidy error handling Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 36/45] mkimage: Add -K to write public keys to an FDT blob Simon Glass
                   ` (11 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de> (v1)
---
Changes in v2:
- Adjust mkimage help to separate out signing options
- Fix checkpatch warnings about split strings

 doc/mkimage.1     | 25 ++++++++++++++++++++++---
 tools/fit_image.c |  2 +-
 tools/mkimage.c   | 15 ++++++++++++++-
 tools/mkimage.h   |  1 +
 4 files changed, 38 insertions(+), 5 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 39652c8..6740fb1 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -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 <iwamatsu@nigauri.org>
-and Wolfgang Denk <wd@denx.de>
+and Wolfgang Denk <wd@denx.de>. It was updated for image signing by
+Simon Glass <sjg@chromium.org>.
diff --git a/tools/fit_image.c b/tools/fit_image.c
index ef6ef44..339e0f8 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index e43b09f..def7df2 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -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,16 @@ 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",
+	fprintf(stderr, "       %s [-D dtc_options] -f fit-image.its fit-image\n",
 		params.cmdname);
+	fprintf(stderr, "          -D => set options for device tree compiler\n"
+			"          -f => input filename for FIT source\n");
+#ifdef CONFIG_FIT_SIGNATURE
+	fprintf(stderr, "Signing / verified boot options: [-k keydir]\n"
+			"          -k => set directory containing private keys\n");
+#else
+	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
+#endif
 	fprintf (stderr, "       %s -V ==> print version information and exit\n",
 		params.cmdname);
 
diff --git a/tools/mkimage.h b/tools/mkimage.h
index e07a615..2a5f115 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -75,6 +75,7 @@ struct mkimage_params {
 	char *datafile;
 	char *imagefile;
 	char *cmdname;
+	const char *keydir;	/* Directory holding private keys */
 };
 
 /*
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 36/45] mkimage: Add -K to write public keys to an FDT blob
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (34 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 35/45] mkimage: Add -k option to specify key directory Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 37/45] mkimage: Add -F option to modify an existing .fit file Simon Glass
                   ` (10 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Adjust mkimage help to separate out signing options
- Rebase on previous patches

 doc/mkimage.1     | 16 ++++++++++++++++
 tools/fit_image.c | 21 +++++++++++++++++++--
 tools/mkimage.c   | 10 ++++++++--
 tools/mkimage.h   |  1 +
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 6740fb1..8185ff5 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -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
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 339e0f8..b17fa2d 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index def7df2..3760392 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -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 ();
@@ -633,8 +638,9 @@ usage ()
 	fprintf(stderr, "          -D => set options for device tree compiler\n"
 			"          -f => input filename for FIT source\n");
 #ifdef CONFIG_FIT_SIGNATURE
-	fprintf(stderr, "Signing / verified boot options: [-k keydir]\n"
-			"          -k => set directory containing private keys\n");
+	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb]\n"
+			"          -k => set directory containing private keys\n"
+			"          -K => write public keys to this .dtb file\n");
 #else
 	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
 #endif
diff --git a/tools/mkimage.h b/tools/mkimage.h
index 2a5f115..41bec21 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -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 */
 };
 
 /*
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 37/45] mkimage: Add -F option to modify an existing .fit file
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (35 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 36/45] mkimage: Add -K to write public keys to an FDT blob Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 38/45] mkimage: Add -c option to specify a comment for key signing Simon Glass
                   ` (9 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Adjust mkimage help to separate out signing options
- Fix checkpatch checks about parenthesis alignment
- Rebase on previous patches

 doc/mkimage.1     | 20 ++++++++++++++++++++
 tools/fit_image.c | 18 ++++++++++++------
 tools/mkimage.c   |  9 ++++++---
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index 8185ff5..f9c733a 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -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
diff --git a/tools/fit_image.c b/tools/fit_image.c
index b17fa2d..645e93c 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -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;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 3760392..e2b82d0 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -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':
@@ -633,14 +635,15 @@ 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",
+	fprintf(stderr, "       %s [-D dtc_options] [-f fit-image.its|-F] fit-image\n",
 		params.cmdname);
 	fprintf(stderr, "          -D => set options for device tree compiler\n"
 			"          -f => input filename for FIT source\n");
 #ifdef CONFIG_FIT_SIGNATURE
 	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb]\n"
 			"          -k => set directory containing private keys\n"
-			"          -K => write public keys to this .dtb file\n");
+			"          -K => write public keys to this .dtb file\n"
+			"          -F => re-sign existing FIT image\n");
 #else
 	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
 #endif
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 38/45] mkimage: Add -c option to specify a comment for key signing
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (36 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 37/45] mkimage: Add -F option to modify an existing .fit file Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 39/45] mkimage: Add -r option to specify keys that must be verified Simon Glass
                   ` (8 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Adjust mkimage help to separate out signing options
- Rebase on previous patches

 doc/mkimage.1     | 6 ++++++
 tools/fit_image.c | 4 ++--
 tools/mkimage.c   | 8 +++++++-
 tools/mkimage.h   | 1 +
 4 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index f9c733a..b67a351 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -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.
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 645e93c..d48f571 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -153,9 +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,
-				      NULL, 0)) {
+				      params->comment, 0)) {
 		fprintf (stderr, "%s Can't add hashes to FIT blob",
-				params->cmdname);
+			 params->cmdname);
 		goto err_add_hashes;
 	}
 
diff --git a/tools/mkimage.c b/tools/mkimage.c
index e2b82d0..b3b45a4 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -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 =
@@ -640,9 +645,10 @@ usage ()
 	fprintf(stderr, "          -D => set options for device tree compiler\n"
 			"          -f => input filename for FIT source\n");
 #ifdef CONFIG_FIT_SIGNATURE
-	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb]\n"
+	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>]\n"
 			"          -k => set directory containing private keys\n"
 			"          -K => write public keys to this .dtb file\n"
+			"          -c => add comment in signature node\n"
 			"          -F => re-sign existing FIT image\n");
 #else
 	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
diff --git a/tools/mkimage.h b/tools/mkimage.h
index 41bec21..4391ca8 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -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 */
 };
 
 /*
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 39/45] mkimage: Add -r option to specify keys that must be verified
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (37 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 38/45] mkimage: Add -c option to specify a comment for key signing Simon Glass
@ 2013-03-18 23:51 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 40/45] libfdt: Add fdt_find_regions() Simon Glass
                   ` (7 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:51 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Adjust mkimage help to separate out signing options
- Rebase on previous patches

 doc/mkimage.1     | 6 ++++++
 tools/fit_image.c | 9 +++++----
 tools/mkimage.c   | 8 ++++++--
 tools/mkimage.h   | 1 +
 4 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/doc/mkimage.1 b/doc/mkimage.1
index b67a351..14374da 100644
--- a/doc/mkimage.1
+++ b/doc/mkimage.1
@@ -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:
diff --git a/tools/fit_image.c b/tools/fit_image.c
index d48f571..281c2bd 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -152,10 +152,11 @@ static int fit_handle_file (struct mkimage_params *params)
 		goto err_mmap;
 
 	/* 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",
-			 params->cmdname);
+	if (fit_add_verification_data(params->keydir,
+				      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;
 	}
 
diff --git a/tools/mkimage.c b/tools/mkimage.c
index b3b45a4..d312844 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -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();
@@ -645,11 +648,12 @@ usage ()
 	fprintf(stderr, "          -D => set options for device tree compiler\n"
 			"          -f => input filename for FIT source\n");
 #ifdef CONFIG_FIT_SIGNATURE
-	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>]\n"
+	fprintf(stderr, "Signing / verified boot options: [-k keydir] [-K dtb] [ -c <comment>] [-r]\n"
 			"          -k => set directory containing private keys\n"
 			"          -K => write public keys to this .dtb file\n"
 			"          -c => add comment in signature node\n"
-			"          -F => re-sign existing FIT image\n");
+			"          -F => re-sign existing FIT image\n"
+			"          -r => mark keys used as 'required' in dtb\n");
 #else
 	fprintf(stderr, "Signing / verified boot not supported (CONFIG_FIT_SIGNATURE undefined)\n");
 #endif
diff --git a/tools/mkimage.h b/tools/mkimage.h
index 4391ca8..d82be17 100644
--- a/tools/mkimage.h
+++ b/tools/mkimage.h
@@ -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' */
 };
 
 /*
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 40/45] libfdt: Add fdt_find_regions()
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (38 preceding siblings ...)
  2013-03-18 23:51 ` [U-Boot] [PATCH v2 39/45] mkimage: Add -r option to specify keys that must be verified Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 41/45] image: Add support for signing of FIT configurations Simon Glass
                   ` (6 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Fix checkpatch checks about parenthesis alignment

 include/libfdt.h     |  64 +++++++++++++++++++++++++
 lib/libfdt/fdt_wip.c | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 193 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index 50c90d6..3e96fe1 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -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 */
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 63e67b7..b9e3c4a 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -120,3 +120,132 @@ int fdt_nop_node(void *fdt, int nodeoffset)
 			endoffset - nodeoffset);
 	return 0;
 }
+
+#define FDT_MAX_DEPTH	32
+
+static int str_in_list(const char *str, char * const list[], int count)
+{
+	int i;
+
+	for (i = 0; i < count; i++)
+		if (!strcmp(list[i], str))
+			return 1;
+
+	return 0;
+}
+
+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)
+{
+	int stack[FDT_MAX_DEPTH];
+	char *end;
+	int nextoffset = 0;
+	uint32_t tag;
+	int count = 0;
+	int start = -1;
+	int depth = -1;
+	int want = 0;
+	int base = fdt_off_dt_struct(fdt);
+
+	end = path;
+	*end = '\0';
+	do {
+		const struct fdt_property *prop;
+		const char *name;
+		const char *str;
+		int include = 0;
+		int stop_at = 0;
+		int offset;
+		int len;
+
+		offset = nextoffset;
+		tag = fdt_next_tag(fdt, offset, &nextoffset);
+		stop_at = nextoffset;
+
+		switch (tag) {
+		case FDT_PROP:
+			include = want >= 2;
+			stop_at = offset;
+			prop = fdt_get_property_by_offset(fdt, offset, NULL);
+			str = fdt_string(fdt, fdt32_to_cpu(prop->nameoff));
+			if (str_in_list(str, exc_prop, exc_prop_count))
+				include = 0;
+			break;
+
+		case FDT_NOP:
+			include = want >= 2;
+			stop_at = offset;
+			break;
+
+		case FDT_BEGIN_NODE:
+			depth++;
+			if (depth == FDT_MAX_DEPTH)
+				return -FDT_ERR_BADSTRUCTURE;
+			name = fdt_get_name(fdt, offset, &len);
+			if (end - path + 2 + len >= path_len)
+				return -FDT_ERR_NOSPACE;
+			if (end != path + 1)
+				*end++ = '/';
+			strcpy(end, name);
+			end += len;
+			stack[depth] = want;
+			if (want == 1)
+				stop_at = offset;
+			if (str_in_list(path, inc, inc_count))
+				want = 2;
+			else if (want)
+				want--;
+			else
+				stop_at = offset;
+			include = want;
+			break;
+
+		case FDT_END_NODE:
+			include = want;
+			want = stack[depth--];
+			while (end > path && *--end != '/')
+				;
+			*end = '\0';
+			break;
+
+		case FDT_END:
+			include = 1;
+			break;
+		}
+
+		if (include && start == -1) {
+			/* Should we merge with previous? */
+			if (count && count <= max_regions &&
+			    offset == region[count - 1].offset +
+					region[count - 1].size - base)
+				start = region[--count].offset - base;
+			else
+				start = offset;
+		}
+
+		if (!include && start != -1) {
+			if (count < max_regions) {
+				region[count].offset = base + start;
+				region[count].size = stop_at - start;
+			}
+			count++;
+			start = -1;
+		}
+	} while (tag != FDT_END);
+
+	if (nextoffset != fdt_size_dt_struct(fdt))
+		return -FDT_ERR_BADLAYOUT;
+
+	/* Add a region for the END tag and the string table */
+	if (count < max_regions) {
+		region[count].offset = base + start;
+		region[count].size = nextoffset - start;
+		if (add_string_tab)
+			region[count].size += fdt_size_dt_strings(fdt);
+	}
+	count++;
+
+	return count;
+}
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 41/45] image: Add support for signing of FIT configurations
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (39 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 40/45] libfdt: Add fdt_find_regions() Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 42/45] image: Remove remaining #ifdefs in image-fit.c Simon Glass
                   ` (5 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

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.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Fix checkpatch checks about parenthesis alignment
- Fix checkpatch warnings about split strings
- Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
- Update README to fix typos and clarify some points
- Use stack instead of calloc() within U-Boot's signature verification code

 common/cmd_bootm.c              |  12 ++
 common/image-sig.c              | 235 ++++++++++++++++++++++++++-
 doc/uImage.FIT/sign-configs.its |  45 ++++++
 doc/uImage.FIT/signature.txt    | 168 ++++++++++++++++++-
 include/image.h                 |  17 ++
 tools/image-host.c              | 345 +++++++++++++++++++++++++++++++++++++++-
 6 files changed, 819 insertions(+), 3 deletions(-)
 create mode 100644 doc/uImage.FIT/sign-configs.its

diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index c03e88f..1f33ee6 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -984,6 +984,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,
diff --git a/common/image-sig.c b/common/image-sig.c
index 1bdb4bf..dc783b2 100644
--- a/common/image-sig.c
+++ b/common/image-sig.c
@@ -25,10 +25,11 @@
 #include <malloc.h>
 DECLARE_GLOBAL_DATA_PTR;
 #endif /* !USE_HOSTCC*/
-#include <errno.h>
 #include <image.h>
 #include <rsa.h>
 
+#define IMAGE_MAX_HASHED_NODES		100
+
 struct image_sig_algo image_sig_algos[] = {
 	{
 		"sha1,rsa2048",
@@ -50,6 +51,50 @@ struct image_sig_algo *image_get_sig_algo(const char *name)
 	return NULL;
 }
 
+/**
+ * fit_region_make_list() - Make a list of image regions
+ *
+ * Given a list of fdt_regions, create a list of image_regions. This is a
+ * simple conversion routine since the FDT and image code use different
+ * structures.
+ *
+ * @fit: FIT image
+ * @fdt_regions: Pointer to FDT regions
+ * @count: Number of FDT regions
+ * @region: Pointer to image regions, which must hold @count records. If
+ * region is NULL, then (except for an SPL build) the array will be
+ * allocated.
+ * @return: Pointer to image regions
+ */
+struct image_region *fit_region_make_list(const void *fit,
+		struct fdt_region *fdt_regions, int count,
+		struct image_region *region)
+{
+	int i;
+
+	debug("Hash regions:\n");
+	debug("%10s %10s\n", "Offset", "Size");
+
+	/*
+	 * Use malloc() except in SPL (to save code size). In SPL the caller
+	 * must allocate the array.
+	 */
+#ifndef CONFIG_SPL_BUILD
+	if (!region)
+		region = calloc(sizeof(*region), count);
+#endif
+	if (!region)
+		return NULL;
+	for (i = 0; i < count; i++) {
+		debug("%10x %10x\n", fdt_regions[i].offset,
+		      fdt_regions[i].size);
+		region[i].data = fit + fdt_regions[i].offset;
+		region[i].size = fdt_regions[i].size;
+	}
+
+	return region;
+}
+
 static int fit_image_setup_verify(struct image_sign_info *info,
 		const void *fit, int noffset, int required_keynode,
 		char **err_msgp)
@@ -195,3 +240,191 @@ int fit_image_verify_required_sigs(const void *fit, int image_noffset,
 
 	return 0;
 }
+
+int fit_config_check_sig(const void *fit, int noffset, int required_keynode,
+			 char **err_msgp)
+{
+	char * const exc_prop[] = {"data"};
+	const char *prop, *end, *name;
+	struct image_sign_info info;
+	const uint32_t *strings;
+	uint8_t *fit_value;
+	int fit_value_len;
+	int max_regions;
+	int i, prop_len;
+	char path[200];
+	int count;
+
+	debug("%s: fdt=%p, conf='%s', sig='%s'\n", __func__, gd_fdt_blob(),
+	      fit_get_name(fit, noffset, NULL),
+	      fit_get_name(gd_fdt_blob(), required_keynode, NULL));
+	*err_msgp = NULL;
+	if (fit_image_setup_verify(&info, fit, noffset, required_keynode,
+				   err_msgp))
+		return -1;
+
+	if (fit_image_hash_get_value(fit, noffset, &fit_value,
+				     &fit_value_len)) {
+		*err_msgp = "Can't get hash value property";
+		return -1;
+	}
+
+	/* Count the number of strings in the property */
+	prop = fdt_getprop(fit, noffset, "hashed-nodes", &prop_len);
+	end = prop ? prop + prop_len : prop;
+	for (name = prop, count = 0; name < end; name++)
+		if (!*name)
+			count++;
+	if (!count) {
+		*err_msgp = "Can't get hashed-nodes property";
+		return -1;
+	}
+
+	/* Add a sanity check here since we are using the stack */
+	if (count > IMAGE_MAX_HASHED_NODES) {
+		*err_msgp = "Number of hashed nodes exceeds maximum";
+		return -1;
+	}
+
+	/* Create a list of node names from those strings */
+	char *node_inc[count];
+
+	debug("Hash nodes (%d):\n", count);
+	for (name = prop, i = 0; name < end; name += strlen(name) + 1, i++) {
+		debug("   '%s'\n", name);
+		node_inc[i] = (char *)name;
+	}
+
+	/*
+	 * Each node can generate one region for each sub-node. Allow for
+	 * 7 sub-nodes (hash at 1, signature@1, etc.) and some extra.
+	 */
+	max_regions = 20 + count * 7;
+	struct fdt_region fdt_regions[max_regions];
+
+	/* Get a list of regions to hash */
+	count = fdt_find_regions(fit, node_inc, count,
+			exc_prop, ARRAY_SIZE(exc_prop),
+			fdt_regions, max_regions - 1,
+			path, sizeof(path), 0);
+	if (count < 0) {
+		*err_msgp = "Failed to hash configuration";
+		return -1;
+	}
+	if (count == 0) {
+		*err_msgp = "No data to hash";
+		return -1;
+	}
+	if (count >= max_regions - 1) {
+		*err_msgp = "Too many hash regions";
+		return -1;
+	}
+
+	/* Add the strings */
+	strings = fdt_getprop(fit, noffset, "hashed-strings", NULL);
+	if (strings) {
+		fdt_regions[count].offset = fdt_off_dt_strings(fit) +
+				fdt32_to_cpu(strings[0]);
+		fdt_regions[count].size = fdt32_to_cpu(strings[1]);
+		count++;
+	}
+
+	/* Allocate the region list on the stack */
+	struct image_region region[count];
+
+	fit_region_make_list(fit, fdt_regions, count, region);
+	if (info.algo->verify(&info, region, count, fit_value,
+			      fit_value_len)) {
+		*err_msgp = "Verification failed";
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_config_verify_sig(const void *fit, int conf_noffset,
+		const void *sig_blob, int sig_offset)
+{
+	int noffset;
+	int ndepth;
+	char *err_msg = "";
+	int verified = 0;
+	int ret;
+
+	/* Process all hash subnodes of the component conf node */
+	for (ndepth = 0,
+			noffset = fdt_next_subnode(fit, conf_noffset, &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		const char *name = fit_get_name(fit, noffset, NULL);
+
+		if (!strncmp(name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_config_check_sig(fit, noffset, sig_offset,
+						   &err_msg);
+			if (ret) {
+				puts("- ");
+			} else {
+				puts("+ ");
+				verified = 1;
+				break;
+			}
+		}
+	}
+
+	if (noffset == -FDT_ERR_TRUNCATED || noffset == -FDT_ERR_BADSTRUCTURE) {
+		err_msg = "Corrupted or truncated tree";
+		goto error;
+	}
+
+	return verified ? 0 : -EPERM;
+
+error:
+	printf(" error!\n%s for '%s' hash node in '%s' config node\n",
+	       err_msg, fit_get_name(fit, noffset, NULL),
+	       fit_get_name(fit, conf_noffset, NULL));
+	return -1;
+}
+
+int fit_config_verify_required_sigs(const void *fit, int conf_noffset,
+		const void *sig_blob)
+{
+	int ndepth, noffset;
+	int sig_node;
+
+	/* Work out what we need to verify */
+	sig_node = fdt_subnode_offset(sig_blob, 0, FIT_SIG_NODENAME);
+	if (sig_node < 0) {
+		debug("%s: No signature node found: %s\n", __func__,
+		      fdt_strerror(sig_node));
+		return 0;
+	}
+
+	for (ndepth = 0, noffset = fdt_next_subnode(sig_blob, sig_node,
+						     &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(sig_blob, noffset,
+						   &ndepth)) {
+		const char *required;
+		int ret;
+
+		required = fdt_getprop(sig_blob, noffset, "required", NULL);
+		if (!required || strcmp(required, "conf"))
+			continue;
+		ret = fit_config_verify_sig(fit, conf_noffset, sig_blob,
+					    noffset);
+		if (ret) {
+			printf("Failed to verify required signature '%s'\n",
+			       fit_get_name(sig_blob, noffset, NULL));
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+int fit_config_verify(const void *fit, int conf_noffset)
+{
+	return !fit_config_verify_required_sigs(fit, conf_noffset,
+						gd_fdt_blob());
+}
diff --git a/doc/uImage.FIT/sign-configs.its b/doc/uImage.FIT/sign-configs.its
new file mode 100644
index 0000000..3c17f04
--- /dev/null
+++ b/doc/uImage.FIT/sign-configs.its
@@ -0,0 +1,45 @@
+/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 = "lzo";
+			load = <0x4>;
+			entry = <0x8>;
+			kernel-version = <1>;
+			hash at 1 {
+				algo = "sha1";
+			};
+		};
+		fdt at 1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash at 1 {
+				algo = "sha1";
+			};
+		};
+	};
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
index 0d145e0..bc9f3fa 100644
--- a/doc/uImage.FIT/signature.txt
+++ b/doc/uImage.FIT/signature.txt
@@ -105,8 +105,27 @@ When the image is signed, the following properties are optional:
 
 - comment: Additional information about the signer or image
 
+For config bindings (see Signed Configurations below), the following
+additional properties are optional:
 
-Example: See sign-images.its for an example image tree source file.
+- sign-images: A list of images to sign, each being a property of the conf
+node that contains then. The default is "kernel,fdt" which means that these
+two images will be looked up in the config and signed if present.
+
+For config bindings, these properties are added by the signer:
+
+- hashed-nodes: A list of nodes which were hashed by the signer. Each is
+	a string - the full path to node. A typical value might be:
+
+	hashed-nodes = "/", "/configurations/conf at 1", "/images/kernel at 1",
+		"/images/kernel at 1/hash at 1", "/images/fdt at 1",
+		"/images/fdt at 1/hash at 1";
+
+- hashed-strings: The start and size of the string region of the FIT that
+	was hashed
+
+Example: See sign-images.its for an example image tree source file and
+sign-configs.its for config signing.
 
 
 Public Key Storage
@@ -144,6 +163,153 @@ For RSA the following are mandatory:
 - rsa,n0-inverse: -1 / modulus[0] mod 2^32
 
 
+Signed Configurations
+---------------------
+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).
+
+As an example, consider this FIT:
+
+/ {
+	images {
+		kernel at 1 {
+			data = <data for kernel1>
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				value = <...kernel signature 1...>
+			};
+		};
+		kernel at 2 {
+			data = <data for kernel2>
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				value = <...kernel signature 2...>
+			};
+		};
+		fdt at 1 {
+			data = <data for fdt1>;
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				vaue = <...fdt signature 1...>
+			};
+		};
+		fdt at 2 {
+			data = <data for fdt2>;
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				vaue = <...fdt signature 2...>
+			};
+		};
+	};
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+		};
+		conf at 1 {
+			kernel = "kernel at 2";
+			fdt = "fdt at 2";
+		};
+	};
+};
+
+Since both kernels are signed it is easy for an attacker to add a new
+configuration 3 with kernel 1 and fdt 2:
+
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+		};
+		conf at 1 {
+			kernel = "kernel at 2";
+			fdt = "fdt at 2";
+		};
+		conf at 3 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 2";
+		};
+	};
+
+With signed images, nothing protects against this. Whether it gains an
+advantage for the attacker is debatable, but it is not secure.
+
+To solved this problem, we support signed configurations. In this case it
+is the configurations that are signed, not the image. Each image has its
+own hash, and we include the hash in the configuration signature.
+
+So the above example is adjusted to look like this:
+
+/ {
+	images {
+		kernel at 1 {
+			data = <data for kernel1>
+			hash at 1 {
+				algo = "sha1";
+				value = <...kernel hash 1...>
+			};
+		};
+		kernel at 2 {
+			data = <data for kernel2>
+			hash at 1 {
+				algo = "sha1";
+				value = <...kernel hash 2...>
+			};
+		};
+		fdt at 1 {
+			data = <data for fdt1>;
+			hash at 1 {
+				algo = "sha1";
+				value = <...fdt hash 1...>
+			};
+		};
+		fdt at 2 {
+			data = <data for fdt2>;
+			hash at 1 {
+				algo = "sha1";
+				value = <...fdt hash 2...>
+			};
+		};
+	};
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				value = <...conf 1 signature...>;
+			};
+		};
+		conf at 2 {
+			kernel = "kernel at 2";
+			fdt = "fdt at 2";
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				value = <...conf 1 signature...>;
+			};
+		};
+	};
+};
+
+
+You can see that we have added hashes for all images (since they are no
+longer signed), and a signature to each configuration. In the above example,
+mkimage will sign configurations/conf at 1, the kernel and fdt that are
+pointed to by the configuration (/images/kernel at 1, /images/kernel at 1/hash at 1,
+/images/fdt at 1, /images/fdt at 1/hash at 1) and the root structure of the image
+(so that it isn't possible to add or remove root nodes). The signature is
+written into /configurations/conf at 1/signature at 1/value. It can easily be
+verified later even if the FIT has been signed with other keys in the
+meantime.
+
+
 Verification
 ------------
 FITs are verified when loaded. After the configuration is selected a list
diff --git a/include/image.h b/include/image.h
index 99015cd..cbbc17e 100644
--- a/include/image.h
+++ b/include/image.h
@@ -640,6 +640,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);
@@ -812,6 +813,22 @@ 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
+ * @region:		Place to put list of regions (NULL to allocate it)
+ * @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,
+		struct image_region *region);
 
 #ifndef USE_HOSTCC
 static inline int fit_image_check_target_arch(const void *fdt, int node)
diff --git a/tools/image-host.c b/tools/image-host.c
index 2836881..4d8430e 100644
--- a/tools/image-host.c
+++ b/tools/image-host.c
@@ -343,10 +343,329 @@ int fit_image_add_verification_data(const char *keydir, void *keydest,
 	return 0;
 }
 
+struct strlist {
+	int count;
+	char **strings;
+};
+
+static void strlist_init(struct strlist *list)
+{
+	memset(list, '\0', sizeof(*list));
+}
+
+static void strlist_free(struct strlist *list)
+{
+	int i;
+
+	for (i = 0; i < list->count; i++)
+		free(list->strings[i]);
+	free(list->strings);
+}
+
+static int strlist_add(struct strlist *list, const char *str)
+{
+	char *dup;
+
+	dup = strdup(str);
+	list->strings = realloc(list->strings,
+				(list->count + 1) * sizeof(char *));
+	if (!list || !str)
+		return -1;
+	list->strings[list->count++] = dup;
+
+	return 0;
+}
+
+static const char *fit_config_get_image_list(void *fit, int noffset,
+		int *lenp, int *allow_missingp)
+{
+	static const char default_list[] = FIT_KERNEL_PROP "\0"
+			FIT_FDT_PROP;
+	const char *prop;
+
+	/* If there is an "image" property, use that */
+	prop = fdt_getprop(fit, noffset, "sign-images", lenp);
+	if (prop) {
+		*allow_missingp = 0;
+		return *lenp ? prop : NULL;
+	}
+
+	/* Default image list */
+	*allow_missingp = 1;
+	*lenp = sizeof(default_list);
+
+	return default_list;
+}
+
+static int fit_config_get_hash_list(void *fit, int conf_noffset,
+				    int sig_offset, struct strlist *node_inc)
+{
+	int allow_missing;
+	const char *prop, *iname, *end;
+	const char *conf_name, *sig_name;
+	char name[200], path[200];
+	int image_count;
+	int ret, len;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+	sig_name = fit_get_name(fit, sig_offset, NULL);
+
+	/*
+	 * Build a list of nodes we need to hash. We always need the root
+	 * node and the configuration.
+	 */
+	strlist_init(node_inc);
+	snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH, conf_name);
+	if (strlist_add(node_inc, "/") ||
+	    strlist_add(node_inc, name))
+		goto err_mem;
+
+	/* Get a list of images that we intend to sign */
+	prop = fit_config_get_image_list(fit, conf_noffset, &len,
+					&allow_missing);
+	if (!prop)
+		return 0;
+
+	/* Locate the images */
+	end = prop + len;
+	image_count = 0;
+	for (iname = prop; iname < end; iname += strlen(iname) + 1) {
+		int ndepth, noffset;
+		int image_noffset;
+		int hash_count;
+
+		image_noffset = fit_conf_get_prop_node(fit, conf_noffset,
+						       iname);
+		if (image_noffset < 0) {
+			printf("Failed to find image '%s' in  configuration '%s/%s'\n",
+			       iname, conf_name, sig_name);
+			if (allow_missing)
+				continue;
+
+			return -ENOENT;
+		}
+
+		ret = fdt_get_path(fit, image_noffset, path, sizeof(path));
+		if (ret < 0)
+			goto err_path;
+		if (strlist_add(node_inc, path))
+			goto err_mem;
+
+		snprintf(name, sizeof(name), "%s/%s", FIT_CONFS_PATH,
+			 conf_name);
+
+		/* Add all this image's hashes */
+		hash_count = 0;
+		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);
+
+			if (strncmp(name, FIT_HASH_NODENAME,
+				    strlen(FIT_HASH_NODENAME)))
+				continue;
+			ret = fdt_get_path(fit, noffset, path, sizeof(path));
+			if (ret < 0)
+				goto err_path;
+			if (strlist_add(node_inc, path))
+				goto err_mem;
+			hash_count++;
+		}
+
+		if (!hash_count) {
+			printf("Failed to find any hash nodes in configuration '%s/%s' image '%s' - without these it is not possible to verify this image\n",
+			       conf_name, sig_name, iname);
+			return -ENOMSG;
+		}
+
+		image_count++;
+	}
+
+	if (!image_count) {
+		printf("Failed to find any images for configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMSG;
+	}
+
+	return 0;
+
+err_mem:
+	printf("Out of memory processing configuration '%s/%s'\n", conf_name,
+	       sig_name);
+	return -ENOMEM;
+
+err_path:
+	printf("Failed to get path for image '%s' in configuration '%s/%s': %s\n",
+	       iname, conf_name, sig_name, fdt_strerror(ret));
+	return -ENOENT;
+}
+
+static int fit_config_get_data(void *fit, int conf_noffset, int noffset,
+		struct image_region **regionp, int *region_countp,
+		char **region_propp, int *region_proplen)
+{
+	char * const exc_prop[] = {"data"};
+	struct strlist node_inc;
+	struct image_region *region;
+	struct fdt_region fdt_regions[100];
+	const char *conf_name, *sig_name;
+	char path[200];
+	int count, i;
+	char *region_prop;
+	int ret, len;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+	sig_name = fit_get_name(fit, conf_noffset, NULL);
+	debug("%s: conf='%s', sig='%s'\n", __func__, conf_name, sig_name);
+
+	/* Get a list of nodes we want to hash */
+	ret = fit_config_get_hash_list(fit, conf_noffset, noffset, &node_inc);
+	if (ret)
+		return ret;
+
+	/* Get a list of regions to hash */
+	count = fdt_find_regions(fit, node_inc.strings, node_inc.count,
+			exc_prop, ARRAY_SIZE(exc_prop),
+			fdt_regions, ARRAY_SIZE(fdt_regions),
+			path, sizeof(path), 1);
+	if (count < 0) {
+		printf("Failed to hash configuration '%s/%s': %s\n", conf_name,
+		       sig_name, fdt_strerror(ret));
+		return -EIO;
+	}
+	if (count == 0) {
+		printf("No data to hash for configuration '%s/%s': %s\n",
+		       conf_name, sig_name, fdt_strerror(ret));
+		return -EINVAL;
+	}
+
+	/* Build our list of data blocks */
+	region = fit_region_make_list(fit, fdt_regions, count, NULL);
+	if (!region) {
+		printf("Out of memory hashing configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMEM;
+	}
+
+	/* Create a list of all hashed properties */
+	debug("Hash nodes:\n");
+	for (i = len = 0; i < node_inc.count; i++) {
+		debug("   %s\n", node_inc.strings[i]);
+		len += strlen(node_inc.strings[i]) + 1;
+	}
+	region_prop = malloc(len);
+	if (!region_prop) {
+		printf("Out of memory setting up regions for configuration '%s/%s'\n",
+		       conf_name, sig_name);
+		return -ENOMEM;
+	}
+	for (i = len = 0; i < node_inc.count;
+	     len += strlen(node_inc.strings[i]) + 1, i++)
+		strcpy(region_prop + len, node_inc.strings[i]);
+	strlist_free(&node_inc);
+
+	*region_countp = count;
+	*regionp = region;
+	*region_propp = region_prop;
+	*region_proplen = len;
+
+	return 0;
+}
+
+static int fit_config_process_sig(const char *keydir, void *keydest,
+		void *fit, const char *conf_name, int conf_noffset,
+		int noffset, const char *comment, int require_keys)
+{
+	struct image_sign_info info;
+	const char *node_name;
+	struct image_region *region;
+	char *region_prop;
+	int region_proplen;
+	int region_count;
+	uint8_t *value;
+	uint value_len;
+	int ret;
+
+	node_name = fit_get_name(fit, noffset, NULL);
+	if (fit_config_get_data(fit, conf_noffset, noffset, &region,
+				&region_count, &region_prop, &region_proplen))
+		return -1;
+
+	if (fit_image_setup_sig(&info, keydir, fit, conf_name, noffset,
+				require_keys ? "conf" : NULL))
+		return -1;
+
+	ret = info.algo->sign(&info, region, region_count, &value, &value_len);
+	free(region);
+	if (ret) {
+		printf("Failed to sign '%s' signature node in '%s' conf node\n",
+		       node_name, conf_name);
+
+		/* We allow keys to be missing */
+		if (ret == -ENOENT)
+			return 0;
+		return -1;
+	}
+
+	if (fit_image_write_sig(fit, noffset, value, value_len, comment,
+				region_prop, region_proplen)) {
+		printf("Can't write signature for '%s' signature node in '%s' conf node\n",
+		       node_name, conf_name);
+		return -1;
+	}
+	free(value);
+	free(region_prop);
+
+	/* Get keyname again, as FDT has changed and invalidated our pointer */
+	info.keyname = fdt_getprop(fit, noffset, "key-name-hint", NULL);
+
+	/* Write the public key into the supplied FDT file */
+	if (keydest && info.algo->add_verify_data(&info, keydest)) {
+		printf("Failed to add verification data for '%s' signature node in '%s' image node\n",
+		       node_name, conf_name);
+		return -1;
+	}
+
+	return 0;
+}
+
+static int fit_config_add_verification_data(const char *keydir, void *keydest,
+		void *fit, int conf_noffset, const char *comment,
+		int require_keys)
+{
+	const char *conf_name;
+	int noffset;
+	int ndepth;
+
+	conf_name = fit_get_name(fit, conf_noffset, NULL);
+
+	/* Process all hash subnodes of the configuration node */
+	for (ndepth = 0,
+			noffset = fdt_next_subnode(fit, conf_noffset, &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		const char *node_name;
+		int ret = 0;
+
+		node_name = fit_get_name(fit, noffset, NULL);
+		if (!strncmp(node_name, FIT_SIG_NODENAME,
+			     strlen(FIT_SIG_NODENAME))) {
+			ret = fit_config_process_sig(keydir, keydest,
+				fit, conf_name, conf_noffset, noffset, comment,
+				require_keys);
+		}
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
 			      const char *comment, int require_keys)
 {
-	int images_noffset;
+	int images_noffset, confs_noffset;
 	int noffset;
 	int ndepth;
 	int ret;
@@ -375,5 +694,29 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
 			return ret;
 	}
 
+	/* If there are no keys, we can't sign configurations */
+	if (!IMAGE_ENABLE_SIGN || !keydir)
+		return 0;
+
+	/* Find configurations parent node offset */
+	confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH);
+	if (confs_noffset < 0) {
+		printf("Can't find images parent node '%s' (%s)\n",
+		       FIT_IMAGES_PATH, fdt_strerror(confs_noffset));
+		return -ENOENT;
+	}
+
+	/* Process its subnodes, print out component images details */
+	for (ndepth = 0,
+			noffset = fdt_next_subnode(fit, confs_noffset, &ndepth);
+			noffset >= 0;
+			noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
+		ret = fit_config_add_verification_data(keydir, keydest,
+						       fit, noffset, comment,
+						       require_keys);
+		if (ret)
+			return ret;
+	}
+
 	return 0;
 }
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 42/45] image: Remove remaining #ifdefs in image-fit.c
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (40 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 41/45] image: Add support for signing of FIT configurations Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 43/45] image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL Simon Glass
                   ` (4 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

There are only two left. One is unnecessary and the other can be moved
to the header file.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add new patch to remove #ifdefs in image-fit.c

 common/image-fit.c | 9 ++-------
 common/image.c     | 7 +------
 include/image.h    | 2 ++
 3 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/common/image-fit.c b/common/image-fit.c
index 30790d3..29ea4c9 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -151,11 +151,8 @@ void fit_print_contents(const void *fit)
 	const char *p;
 	time_t timestamp;
 
-#ifdef USE_HOSTCC
-	p = "";
-#else
-	p = "   ";
-#endif
+	/* Indent string is defined in header image.h */
+	p = IMAGE_INDENT_STRING;
 
 	/* Root node properties */
 	ret = fit_get_desc(fit, 0, &desc);
@@ -1504,7 +1501,6 @@ void fit_conf_print(const void *fit, int noffset, const char *p)
  *     1, on success
  *     0, on failure
  */
-#ifndef USE_HOSTCC
 int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
 			int verify)
 {
@@ -1533,4 +1529,3 @@ int fit_check_ramdisk(const void *fit, int rd_noffset, uint8_t arch,
 	bootstage_mark(BOOTSTAGE_ID_FIT_RD_CHECK_ALL_OK);
 	return 1;
 }
-#endif /* USE_HOSTCC */
diff --git a/common/image.c b/common/image.c
index 14d1c48..f013fdc 100644
--- a/common/image.c
+++ b/common/image.c
@@ -295,12 +295,7 @@ void image_print_contents(const void *ptr)
 	const image_header_t *hdr = (const image_header_t *)ptr;
 	const char *p;
 
-#ifdef USE_HOSTCC
-	p = "";
-#else
-	p = "   ";
-#endif
-
+	p = IMAGE_INDENT_STRING;
 	printf("%sImage Name:   %.*s\n", p, IH_NMLEN, image_get_name(hdr));
 	if (IMAGE_ENABLE_TIMESTAMP) {
 		printf("%sCreated:      ", p);
diff --git a/include/image.h b/include/image.h
index cbbc17e..5766b58 100644
--- a/include/image.h
+++ b/include/image.h
@@ -47,6 +47,7 @@
 #define CONFIG_FIT_SIGNATURE
 
 #define IMAGE_ENABLE_IGNORE	0
+#define IMAGE_INDENT_STRING	""
 
 #else
 
@@ -56,6 +57,7 @@
 
 /* Take notice of the 'ignore' property for hashes */
 #define IMAGE_ENABLE_IGNORE	1
+#define IMAGE_INDENT_STRING	"   "
 
 #endif /* USE_HOSTCC */
 
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 43/45] image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (41 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 42/45] image: Remove remaining #ifdefs in image-fit.c Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 44/45] sandbox: Allow -c argument to provide a command list Simon Glass
                   ` (3 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

This code is very large, and in SPL it isn't always useful to print
out image information (in fact there might not even be a console
active). So disable this feature unless this option is set.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Add new patch to control FIT image printing in SPL
- Fix checkpatch warnings about space after cast

 README             |  6 ++++++
 common/image-fit.c |  8 +++++---
 include/image.h    | 33 +++++++++++++++++++++++++++++++--
 3 files changed, 42 insertions(+), 5 deletions(-)

diff --git a/README b/README
index d8ccc3e..d98fd98 100644
--- a/README
+++ b/README
@@ -2909,6 +2909,12 @@ FIT uImage format:
 		use an arch-specific makefile fragment instead, for
 		example if more than one image needs to be produced.
 
+		CONFIG_FIT_SPL_PRINT
+		Printing information about a FIT image adds quite a bit of
+		code to SPL. So this is normally disabled in SPL. Use this
+		option to re-enable it. This will affect the output of the
+		bootm command when booting a FIT image.
+
 Modem Support:
 --------------
 
diff --git a/common/image-fit.c b/common/image-fit.c
index 29ea4c9..b7ff0da 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -126,6 +126,7 @@ static void fit_get_debug(const void *fit, int noffset,
 	      fdt_strerror(err));
 }
 
+#if !defined(CONFIG_SPL_BUILD) || defined(CONFIG_FIT_SPL_PRINT)
 /**
  * fit_print_contents - prints out the contents of the FIT format image
  * @fit: pointer to the FIT format image header
@@ -422,6 +423,7 @@ void fit_image_print(const void *fit, int image_noffset, const char *p)
 		}
 	}
 }
+#endif
 
 /**
  * fit_get_desc - get node description property
@@ -872,16 +874,16 @@ int fit_set_timestamp(void *fit, int noffset, time_t timestamp)
 int calculate_hash(const void *data, int data_len, const char *algo,
 			uint8_t *value, int *value_len)
 {
-	if (strcmp(algo, "crc32") == 0) {
+	if (IMAGE_ENABLE_CRC32 && strcmp(algo, "crc32") == 0) {
 		*((uint32_t *)value) = crc32_wd(0, data, data_len,
 							CHUNKSZ_CRC32);
 		*((uint32_t *)value) = cpu_to_uimage(*((uint32_t *)value));
 		*value_len = 4;
-	} else if (strcmp(algo, "sha1") == 0) {
+	} else if (IMAGE_ENABLE_SHA1 && strcmp(algo, "sha1") == 0) {
 		sha1_csum_wd((unsigned char *)data, data_len,
 			     (unsigned char *)value, CHUNKSZ_SHA1);
 		*value_len = 20;
-	} else if (strcmp(algo, "md5") == 0) {
+	} else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) {
 		md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5);
 		*value_len = 16;
 	} else {
diff --git a/include/image.h b/include/image.h
index 5766b58..3a70404 100644
--- a/include/image.h
+++ b/include/image.h
@@ -64,8 +64,37 @@
 #if defined(CONFIG_FIT)
 #include <libfdt.h>
 #include <fdt_support.h>
-#define CONFIG_MD5		/* FIT images need MD5 support */
-#define CONFIG_SHA1		/* and SHA1 */
+# ifdef CONFIG_SPL_BUILD
+#  ifdef CONFIG_SPL_CRC32_SUPPORT
+#   define IMAGE_ENABLE_CRC32	1
+#  endif
+#  ifdef CONFIG_SPL_MD5_SUPPORT
+#   define IMAGE_ENABLE_MD5	1
+#  endif
+#  ifdef CONFIG_SPL_SHA1_SUPPORT
+#   define IMAGE_ENABLE_SHA1	1
+#  endif
+# else
+#  define CONFIG_CRC32		/* FIT images need CRC32 support */
+#  define CONFIG_MD5		/* and MD5 */
+#  define CONFIG_SHA1		/* and SHA1 */
+#  define IMAGE_ENABLE_CRC32	1
+#  define IMAGE_ENABLE_MD5	1
+#  define IMAGE_ENABLE_SHA1	1
+# endif
+
+#ifndef IMAGE_ENABLE_CRC32
+#define IMAGE_ENABLE_CRC32	0
+#endif
+
+#ifndef IMAGE_ENABLE_MD5
+#define IMAGE_ENABLE_MD5	0
+#endif
+
+#ifndef IMAGE_ENABLE_SHA1
+#define IMAGE_ENABLE_SHA1	0
+#endif
+
 #endif
 
 /*
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 44/45] sandbox: Allow -c argument to provide a command list
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (42 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 43/45] image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 45/45] Add verified boot information and test Simon Glass
                   ` (2 subsequent siblings)
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

This allows passing of entire scripts to sandbox with the -c argument,
which is useful for testing. Commands can be delimited with a newline
or semicolon.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Marek Vasut <marex@denx.de>
---
Changes in v2:
- Move sandbox's command list patch from a later series

 arch/sandbox/cpu/start.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/sandbox/cpu/start.c b/arch/sandbox/cpu/start.c
index 2fcec8b..ae6e16c 100644
--- a/arch/sandbox/cpu/start.c
+++ b/arch/sandbox/cpu/start.c
@@ -90,7 +90,7 @@ int sandbox_main_loop_init(void)
 
 	/* Execute command if required */
 	if (state->cmd) {
-		run_command(state->cmd, 0);
+		run_command_list(state->cmd, -1, 0);
 		os_exit(state->exit_type);
 	}
 
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 45/45] Add verified boot information and test
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (43 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 44/45] sandbox: Allow -c argument to provide a command list Simon Glass
@ 2013-03-18 23:52 ` Simon Glass
  2013-04-02  0:13 ` [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Kim Phillips
  2013-04-15  8:38 ` Jagan Teki
  46 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-03-18 23:52 UTC (permalink / raw)
  To: u-boot

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

The test signs a FIT image and verifies it, then signs a FIT configuration
and verifies it. Then it corrupts the signature to check that this is
detected.

Signed-off-by: Simon Glass <sjg@chromium.org>
---
Changes in v2:
- Update README to fix typos
- Use U-Boot's -c option instead of hard-coding a boot script

 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         | 126 +++++++++++++++++++++++++++++++++++++++
 7 files changed, 334 insertions(+)
 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

diff --git a/doc/uImage.FIT/verified-boot.txt b/doc/uImage.FIT/verified-boot.txt
new file mode 100644
index 0000000..3c83fbc
--- /dev/null
+++ b/doc/uImage.FIT/verified-boot.txt
@@ -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 go on 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 contained 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
+public key. Multiple keys and multiple signatures are supported.
+
+See signature.txt for more information.
+
+
+Simon Glass
+sjg at chromium.org
+1-1-13
diff --git a/test/vboot/.gitignore b/test/vboot/.gitignore
new file mode 100644
index 0000000..4631242
--- /dev/null
+++ b/test/vboot/.gitignore
@@ -0,0 +1,3 @@
+/*.dtb
+/test.fit
+/dev-keys
diff --git a/test/vboot/sandbox-kernel.dts b/test/vboot/sandbox-kernel.dts
new file mode 100644
index 0000000..a1e853c
--- /dev/null
+++ b/test/vboot/sandbox-kernel.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
diff --git a/test/vboot/sandbox-u-boot.dts b/test/vboot/sandbox-u-boot.dts
new file mode 100644
index 0000000..a1e853c
--- /dev/null
+++ b/test/vboot/sandbox-u-boot.dts
@@ -0,0 +1,7 @@
+/dts-v1/;
+
+/ {
+	model = "Sandbox Verified Boot Test";
+	compatible = "sandbox";
+
+};
diff --git a/test/vboot/sign-configs.its b/test/vboot/sign-configs.its
new file mode 100644
index 0000000..db2ed79
--- /dev/null
+++ b/test/vboot/sign-configs.its
@@ -0,0 +1,45 @@
+/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>;
+			hash at 1 {
+				algo = "sha1";
+			};
+		};
+		fdt at 1 {
+			description = "snow";
+			data = /incbin/("sandbox-kernel.dtb");
+			type = "flat_dt";
+			arch = "sandbox";
+			compression = "none";
+			fdt-version = <1>;
+			hash at 1 {
+				algo = "sha1";
+			};
+		};
+	};
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			kernel = "kernel at 1";
+			fdt = "fdt at 1";
+			signature at 1 {
+				algo = "sha1,rsa2048";
+				key-name-hint = "dev";
+				sign-images = "fdt", "kernel";
+			};
+		};
+	};
+};
diff --git a/test/vboot/sign-images.its b/test/vboot/sign-images.its
new file mode 100644
index 0000000..f69326a
--- /dev/null
+++ b/test/vboot/sign-images.its
@@ -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";
+		};
+	};
+};
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
new file mode 100755
index 0000000..2922e3d
--- /dev/null
+++ b/test/vboot/vboot_test.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+#
+# Copyright (c) 2013, Google Inc.
+#
+# Simple Verified Boot Test Script
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+
+set -e
+
+# Run U-Boot and report the result
+# Args:
+#	$1:	Test message
+run_uboot() {
+	echo -n "Test Verified Boot Run: $1: "
+	${uboot} -d sandbox-u-boot.dtb >${tmp} -c '
+sb load host 0 100 test.fit;
+fdt addr 100;
+bootm 100;
+reset'
+	if ! grep -q "$2" ${tmp}; then
+		echo
+		echo "Verified boot key check failed, output follows:"
+		cat ${tmp}
+		false
+	else
+		echo "OK"
+	fi
+}
+
+echo "Simple Verified Boot Test"
+echo "========================="
+echo
+echo "Please see doc/uImage.FIT/verified-boot.txt for more information"
+echo
+
+err=0
+tmp=/tmp/vboot_test.$$
+
+dir=$(dirname $0)
+
+if [ -z ${O} ]; then
+	O=.
+fi
+O=$(readlink -f ${O})
+
+dtc="-I dts -O dtb -p 2000"
+uboot="${O}/u-boot"
+mkimage="${O}/tools/mkimage"
+keys="${dir}/dev-keys"
+echo ${mkimage} -D "${dtc}"
+
+echo "Build keys"
+mkdir -p ${keys}
+
+# Create an RSA key pair
+openssl genrsa -F4 -out ${keys}/dev.key 2048 2>/dev/null
+
+# Create a certificate containing the public key
+openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
+
+pushd ${dir} >/dev/null
+
+# Copmile our device tree files for kernel and U-Boot (CONFIG_OF_CONTROL)
+dtc -p 0x1000 sandbox-kernel.dts -O dtb -o sandbox-kernel.dtb
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+# Create a number kernel image with zeroes
+head -c 5000 /dev/zero >test-kernel.bin
+
+# Build the FIT, but don't sign anything yet
+echo Build FIT with signed images
+${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
+
+run_uboot "unsigned signatures:" "dev-"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed images" "dev+"
+
+
+# Create a fresh .dtb without the public keys
+dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
+
+echo Build FIT with signed configuration
+${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
+
+run_uboot "unsigned config" "sha1+ OK"
+
+# Sign images with our dev keys
+echo Sign images
+${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+
+run_uboot "signed config" "dev+"
+
+# Increment the first byte of the signature, which should cause failure
+sig=$(fdtget -t bx test.fit /configurations/conf at 1/signature at 1 value)
+newbyte=$(printf %x $((0x${sig:0:2} + 1)))
+sig="${newbyte} ${sig:2}"
+fdtput -t bx test.fit /configurations/conf at 1/signature at 1 value ${sig}
+
+run_uboot "signed config with bad hash" "Bad Data Hash"
+
+popd >/dev/null
+
+echo
+if ${ok}; then
+	echo "Test passed"
+else
+	echo "Test failed"
+fi
-- 
1.8.1.3

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (44 preceding siblings ...)
  2013-03-18 23:52 ` [U-Boot] [PATCH v2 45/45] Add verified boot information and test Simon Glass
@ 2013-04-02  0:13 ` Kim Phillips
  2013-04-20 23:03   ` Simon Glass
  2013-04-15  8:38 ` Jagan Teki
  46 siblings, 1 reply; 56+ messages in thread
From: Kim Phillips @ 2013-04-02  0:13 UTC (permalink / raw)
  To: u-boot

On Mon, 18 Mar 2013 16:51:20 -0700
Simon Glass <sjg@chromium.org> wrote:

> I have received a number of off-list comments - please do copy the list when
> replying so that everyone can see your comments.

I don't have time to fully review 45 patches, let alone the subject
matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
some things that bugged me:

Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":

- Where's our libfdt maintainer?  libfdt patches should be submitted
to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
fdt_find_regions()" also suffers from this problem.

- can we improve on the readability of that for loop - the improved
one the patch gives us is this:

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

whereas perhaps something like this:

ndepth = 0;
noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
while (noffset >= 0) {
	// body
        noffset = fdt_next_subnode(fit, noffset, &ndepth);
}

would be much easier to quickly visually parse?

this would also affect:

Re: "[PATCH v2 12/45] image: Move hash checking into its own function":
- which also adds lines like these:

> +		*err_msgp = " error!\nCan't get hash algo "
> +				"property";

upon which a subsequent patch ("[PATCH v2 13/45] image: Move error!
string to common place", if I'm not mistaken) corrects.  Are you
intentionally trying to make people review the same code twice??

Re: "[PATCH v2 07/45] image: Split FIT code into new image-fit.c"
- after the code is split, it appears the rest of the patchseries
works on improving image-fit.c instead of updating equivalent code
still existing in image.c, IIRC, "[PATCH v2 13/45] image: Move error!
string to common place"
- I also found it odd that git format-patch -M on this doesn't
produce a shorter patch with "% equivalent" statistics: what else
changed?

Re: "[PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit":
- I personally appreciate it when authors of such large patchseries
put the trivial stuff first, as if to follow the logical progression
of the complexity (and therefore acceptability) of the patches in
the series.  Make things like this the first patch in the series -
that way maintainers can be tempted to start applying obvious
patches from early patchseries versions.  This also applies to
patches like [PATCH v2 24/45] Revert "fdt- Tell the FDT library
where the device tree is", and:

Re: "[PATCH v2 25/45] Add stdarg to vsprintf.h":
- which contains the text "TODO: Probably should drop this patch?".
Well?  Did you mean this series to be an RFC?

I'm stopping my already brief review here - please clean this up.

Kim

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
                   ` (45 preceding siblings ...)
  2013-04-02  0:13 ` [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Kim Phillips
@ 2013-04-15  8:38 ` Jagan Teki
  2013-04-17 14:20   ` Simon Glass
  46 siblings, 1 reply; 56+ messages in thread
From: Jagan Teki @ 2013-04-15  8:38 UTC (permalink / raw)
  To: u-boot

Hi Simon,

I am new to this verification boot concept, could you please clarify
my questions.

On Tue, Mar 19, 2013 at 5:21 AM, Simon Glass <sjg@chromium.org> wrote:
> 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

1. Who is doing RSA encryption for images?
    does RSA lib will do with the help of mkimage, if so where can the
lib will get the private key. ?
2. This RSA alogo will encrypt the entire (image+hash) or only encrypt
the hash on each individual image?
3. How can we provide the public key using u-boot devicetree, is there
any other way to provide this key other than dtb?
4. Suppose some one/other tool does an encryption which consists of
encrypted image+public key, so does your rsa code
    will verify and boot?

Thanks,
Jagan.

> cannot be changed after manufacture. Some notes are provided in the
> documentaion on how this can be achieved. The implementation is fairly
> efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
> to SPL size which is manageable on modern SoCs.
>
> 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 related to adding image support for sandbox. A follow-on series is
> somewhat more agressive in further refactoring the FIT image support to
> clean it up improve maintainability.
>
> Rollback prevention has been added in a separate TPM patch. This ensures
> that an attacker cannot boot your system with an old image that has been
> compromised. Support for this is not built into bootm, but instead must
> be scripted in U-Boot. It is possible that a standard scheme for this could
> be devised by adding version number tags to the signing procedure. However
> scripts do provide more flexibility. The TPM patch is here:
>
> http://patchwork.ozlabs.org/patch/224163/
>
> This series is available at:
>
> http://git.denx.de/u-boot-x86.git
>
> in the branch 'vboot'.
>
> I have received a number of off-list comments - please do copy the list when
> replying so that everyone can see your comments.
>
> Changes in v2:
> - Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
> - Add comment about why mkimage needs to open FIT with O_RDWR
> - Add new patch to control FIT image printing in SPL
> - Add new patch to remove #ifdefs in image-fit.c
> - Add sanity checks on key sizes in RSA (improves security)
> - Adjust how signing enable works in image.h
> - Adjust mkimage help to separate out signing options
> - Allow the control FDT to be set even if there is currently no control FDT
> - Avoid using malloc in RSA routines (for smaller SPL code size)
> - Build signing support unconditionally in mkimage
> - Change hash_block() to use an unsigned int len
> - Clarify use of output_size parameter to hash_block()
> - Correct bug in setting control FDT
> - Fix FDT error handling in fit_image_write_sig()
> - Fix checkpatch checks about parenthesis alignment
> - Fix checkpatch warnings about space after cast
> - Fix checkpatch warnings about split strings
> - Fix line continuation problem
> - Fix spelling of multiply in rsa-verify.c
> - Fix spelling of quite
> - Fix typo "os defined" -> "is defined"
> - Move sandbox's command list patch from a later series
> - Only build RSA support into mkimage if CONFIG_RSA is defined
> - Put err_msgp strings on a single line
> - Put params before description in fit_conf_get_prop_node() comment
> - Rebase on previous patches
> - Rebase to use updated fdt_valid() function
> - Rename commit message to say "function" instead of "function"
> - Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
> - Revert the whole change including the set_working_fdt_addr() part
> - Support RSA library version without ERR_remove_thread_state()
> - Tweak tools/Makefile to make image signing optional
> - Update README to fix typos
> - Update README to fix typos and clarify some points
> - Use U-Boot's -c option instead of hard-coding a boot script
> - Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)
> - Use stack instead of calloc() within U-Boot's signature verification code
> - fdt_valid() sets the FDT pointer to NULL on error, to simplify callers
> - gd->fdt_blob is now available on all archs (generic board landed)
>
> Simon Glass (45):
>   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 function
>   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: 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
>   image: Remove remaining #ifdefs in image-fit.c
>   image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
>   sandbox: Allow -c argument to provide a command list
>   Add verified boot information and test
>
>  Makefile                         |    1 +
>  README                           |   21 +
>  arch/sandbox/cpu/cpu.c           |    5 +
>  arch/sandbox/cpu/start.c         |    9 +-
>  arch/sandbox/include/asm/io.h    |    2 +
>  arch/sandbox/include/asm/state.h |    1 +
>  arch/sandbox/lib/board.c         |   38 +-
>  common/Makefile                  |    2 +
>  common/cmd_bootm.c               |   37 +-
>  common/cmd_fdt.c                 |   87 +-
>  common/cmd_fpga.c                |    2 +-
>  common/cmd_nvedit.c              |   19 +-
>  common/cmd_source.c              |    2 +-
>  common/cmd_ximg.c                |    2 +-
>  common/hash.c                    |   23 +
>  common/image-fit.c               | 1533 ++++++++++++++++++++++++++++++++++
>  common/image-sig.c               |  430 ++++++++++
>  common/image.c                   | 1686 +-------------------------------------
>  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     |  382 +++++++++
>  doc/uImage.FIT/verified-boot.txt |  104 +++
>  include/bootstage.h              |    5 +-
>  include/common.h                 |   18 +
>  include/configs/sandbox.h        |    6 +
>  include/hash.h                   |   22 +
>  include/image.h                  |  265 +++++-
>  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                 |   48 ++
>  lib/rsa/rsa-sign.c               |  460 +++++++++++
>  lib/rsa/rsa-verify.c             |  385 +++++++++
>  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         |  126 +++
>  tools/Makefile                   |   23 +-
>  tools/aisimage.c                 |    1 -
>  tools/fit_image.c                |  136 +--
>  tools/image-host.c               |  722 ++++++++++++++++
>  tools/mkimage.c                  |   36 +-
>  tools/mkimage.h                  |    6 +
>  53 files changed, 5485 insertions(+), 1783 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
>
> --
> 1.8.1.3
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-15  8:38 ` Jagan Teki
@ 2013-04-17 14:20   ` Simon Glass
  2013-04-17 18:26     ` Jagan Teki
  0 siblings, 1 reply; 56+ messages in thread
From: Simon Glass @ 2013-04-17 14:20 UTC (permalink / raw)
  To: u-boot

Hi,

On Mon, Apr 15, 2013 at 1:38 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> Hi Simon,
>
> I am new to this verification boot concept, could you please clarify
> my questions.
>
> On Tue, Mar 19, 2013 at 5:21 AM, Simon Glass <sjg@chromium.org> wrote:
>> 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
>
> 1. Who is doing RSA encryption for images?
>     does RSA lib will do with the help of mkimage, if so where can the
> lib will get the private key. ?

There is a script in test/vboot which shows how this is done.
Basically we use openrsa tools to create a private key.

> 2. This RSA alogo will encrypt the entire (image+hash) or only encrypt
> the hash on each individual image?

Be careful with terminology - we don't actually encrypt the images -
we only sign them. Signing means that we hash the image and (if you
like) encrypt the hash.

We provide two options:

a. Sign each image independently - here we sign the image data
b. Sign the configuration, in which case we don't actually sign the
image data, only their hashes

> 3. How can we provide the public key using u-boot devicetree, is there
> any other way to provide this key other than dtb?

This is describes in the documentation. We use mkimage to add the
public key to your device tree. There is no other way currently
implemented - at present you need CONFIG_OF_CONTROL. However, with
generic board it should be a simple matter to add this for most
boards. The device tree is convenient because it supports
structured/tagged data, making it clean and easy to store the
information.

> 4. Suppose some one/other tool does an encryption which consists of
> encrypted image+public key, so does your rsa code
>     will verify and boot?

You don't need to use mkimage - you can certainly create your own tool
which does the same thing. Provided you achieve the same result then
bootm will still verify and boot.

Regards,
Simon

>
> Thanks,
> Jagan.
>
>> cannot be changed after manufacture. Some notes are provided in the
>> documentaion on how this can be achieved. The implementation is fairly
>> efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
>> to SPL size which is manageable on modern SoCs.
>>
>> 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 related to adding image support for sandbox. A follow-on series is
>> somewhat more agressive in further refactoring the FIT image support to
>> clean it up improve maintainability.
>>
>> Rollback prevention has been added in a separate TPM patch. This ensures
>> that an attacker cannot boot your system with an old image that has been
>> compromised. Support for this is not built into bootm, but instead must
>> be scripted in U-Boot. It is possible that a standard scheme for this could
>> be devised by adding version number tags to the signing procedure. However
>> scripts do provide more flexibility. The TPM patch is here:
>>
>> http://patchwork.ozlabs.org/patch/224163/
>>
>> This series is available at:
>>
>> http://git.denx.de/u-boot-x86.git
>>
>> in the branch 'vboot'.
>>
>> I have received a number of off-list comments - please do copy the list when
>> replying so that everyone can see your comments.
>>
>> Changes in v2:
>> - Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
>> - Add comment about why mkimage needs to open FIT with O_RDWR
>> - Add new patch to control FIT image printing in SPL
>> - Add new patch to remove #ifdefs in image-fit.c
>> - Add sanity checks on key sizes in RSA (improves security)
>> - Adjust how signing enable works in image.h
>> - Adjust mkimage help to separate out signing options
>> - Allow the control FDT to be set even if there is currently no control FDT
>> - Avoid using malloc in RSA routines (for smaller SPL code size)
>> - Build signing support unconditionally in mkimage
>> - Change hash_block() to use an unsigned int len
>> - Clarify use of output_size parameter to hash_block()
>> - Correct bug in setting control FDT
>> - Fix FDT error handling in fit_image_write_sig()
>> - Fix checkpatch checks about parenthesis alignment
>> - Fix checkpatch warnings about space after cast
>> - Fix checkpatch warnings about split strings
>> - Fix line continuation problem
>> - Fix spelling of multiply in rsa-verify.c
>> - Fix spelling of quite
>> - Fix typo "os defined" -> "is defined"
>> - Move sandbox's command list patch from a later series
>> - Only build RSA support into mkimage if CONFIG_RSA is defined
>> - Put err_msgp strings on a single line
>> - Put params before description in fit_conf_get_prop_node() comment
>> - Rebase on previous patches
>> - Rebase to use updated fdt_valid() function
>> - Rename commit message to say "function" instead of "function"
>> - Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
>> - Revert the whole change including the set_working_fdt_addr() part
>> - Support RSA library version without ERR_remove_thread_state()
>> - Tweak tools/Makefile to make image signing optional
>> - Update README to fix typos
>> - Update README to fix typos and clarify some points
>> - Use U-Boot's -c option instead of hard-coding a boot script
>> - Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)
>> - Use stack instead of calloc() within U-Boot's signature verification code
>> - fdt_valid() sets the FDT pointer to NULL on error, to simplify callers
>> - gd->fdt_blob is now available on all archs (generic board landed)
>>
>> Simon Glass (45):
>>   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 function
>>   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: 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
>>   image: Remove remaining #ifdefs in image-fit.c
>>   image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
>>   sandbox: Allow -c argument to provide a command list
>>   Add verified boot information and test
>>
>>  Makefile                         |    1 +
>>  README                           |   21 +
>>  arch/sandbox/cpu/cpu.c           |    5 +
>>  arch/sandbox/cpu/start.c         |    9 +-
>>  arch/sandbox/include/asm/io.h    |    2 +
>>  arch/sandbox/include/asm/state.h |    1 +
>>  arch/sandbox/lib/board.c         |   38 +-
>>  common/Makefile                  |    2 +
>>  common/cmd_bootm.c               |   37 +-
>>  common/cmd_fdt.c                 |   87 +-
>>  common/cmd_fpga.c                |    2 +-
>>  common/cmd_nvedit.c              |   19 +-
>>  common/cmd_source.c              |    2 +-
>>  common/cmd_ximg.c                |    2 +-
>>  common/hash.c                    |   23 +
>>  common/image-fit.c               | 1533 ++++++++++++++++++++++++++++++++++
>>  common/image-sig.c               |  430 ++++++++++
>>  common/image.c                   | 1686 +-------------------------------------
>>  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     |  382 +++++++++
>>  doc/uImage.FIT/verified-boot.txt |  104 +++
>>  include/bootstage.h              |    5 +-
>>  include/common.h                 |   18 +
>>  include/configs/sandbox.h        |    6 +
>>  include/hash.h                   |   22 +
>>  include/image.h                  |  265 +++++-
>>  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                 |   48 ++
>>  lib/rsa/rsa-sign.c               |  460 +++++++++++
>>  lib/rsa/rsa-verify.c             |  385 +++++++++
>>  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         |  126 +++
>>  tools/Makefile                   |   23 +-
>>  tools/aisimage.c                 |    1 -
>>  tools/fit_image.c                |  136 +--
>>  tools/image-host.c               |  722 ++++++++++++++++
>>  tools/mkimage.c                  |   36 +-
>>  tools/mkimage.h                  |    6 +
>>  53 files changed, 5485 insertions(+), 1783 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
>>
>> --
>> 1.8.1.3
>>
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> http://lists.denx.de/mailman/listinfo/u-boot

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-17 14:20   ` Simon Glass
@ 2013-04-17 18:26     ` Jagan Teki
  2013-04-17 18:33       ` Simon Glass
  0 siblings, 1 reply; 56+ messages in thread
From: Jagan Teki @ 2013-04-17 18:26 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Wed, Apr 17, 2013 at 7:50 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi,
>
> On Mon, Apr 15, 2013 at 1:38 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
>> Hi Simon,
>>
>> I am new to this verification boot concept, could you please clarify
>> my questions.
>>
>> On Tue, Mar 19, 2013 at 5:21 AM, Simon Glass <sjg@chromium.org> wrote:
>>> 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
>>
>> 1. Who is doing RSA encryption for images?
>>     does RSA lib will do with the help of mkimage, if so where can the
>> lib will get the private key. ?
>
> There is a script in test/vboot which shows how this is done.
> Basically we use openrsa tools to create a private key.
>
>> 2. This RSA alogo will encrypt the entire (image+hash) or only encrypt
>> the hash on each individual image?
>
> Be careful with terminology - we don't actually encrypt the images -
> we only sign them. Signing means that we hash the image and (if you
> like) encrypt the hash.

Ok, means RSA will encrypt the image, is it?
There is a AES crypt on lib/aes, can we use aes to encrypt the image
and RSA for hash, is there any possibility in u-boot
to do aes and rsa encrypt and decrypt process and boot.

>
> We provide two options:
>
> a. Sign each image independently - here we sign the image data
> b. Sign the configuration, in which case we don't actually sign the
> image data, only their hashes

What does sign a data image means, can u please clarify.

Thanks,
Jagan.

>
>> 3. How can we provide the public key using u-boot devicetree, is there
>> any other way to provide this key other than dtb?
>
> This is describes in the documentation. We use mkimage to add the
> public key to your device tree. There is no other way currently
> implemented - at present you need CONFIG_OF_CONTROL. However, with
> generic board it should be a simple matter to add this for most
> boards. The device tree is convenient because it supports
> structured/tagged data, making it clean and easy to store the
> information.
>
>> 4. Suppose some one/other tool does an encryption which consists of
>> encrypted image+public key, so does your rsa code
>>     will verify and boot?
>
> You don't need to use mkimage - you can certainly create your own tool
> which does the same thing. Provided you achieve the same result then
> bootm will still verify and boot.
>
> Regards,
> Simon
>
>>
>> Thanks,
>> Jagan.
>>
>>> cannot be changed after manufacture. Some notes are provided in the
>>> documentaion on how this can be achieved. The implementation is fairly
>>> efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
>>> to SPL size which is manageable on modern SoCs.
>>>
>>> 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 related to adding image support for sandbox. A follow-on series is
>>> somewhat more agressive in further refactoring the FIT image support to
>>> clean it up improve maintainability.
>>>
>>> Rollback prevention has been added in a separate TPM patch. This ensures
>>> that an attacker cannot boot your system with an old image that has been
>>> compromised. Support for this is not built into bootm, but instead must
>>> be scripted in U-Boot. It is possible that a standard scheme for this could
>>> be devised by adding version number tags to the signing procedure. However
>>> scripts do provide more flexibility. The TPM patch is here:
>>>
>>> http://patchwork.ozlabs.org/patch/224163/
>>>
>>> This series is available at:
>>>
>>> http://git.denx.de/u-boot-x86.git
>>>
>>> in the branch 'vboot'.
>>>
>>> I have received a number of off-list comments - please do copy the list when
>>> replying so that everyone can see your comments.
>>>
>>> Changes in v2:
>>> - Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
>>> - Add comment about why mkimage needs to open FIT with O_RDWR
>>> - Add new patch to control FIT image printing in SPL
>>> - Add new patch to remove #ifdefs in image-fit.c
>>> - Add sanity checks on key sizes in RSA (improves security)
>>> - Adjust how signing enable works in image.h
>>> - Adjust mkimage help to separate out signing options
>>> - Allow the control FDT to be set even if there is currently no control FDT
>>> - Avoid using malloc in RSA routines (for smaller SPL code size)
>>> - Build signing support unconditionally in mkimage
>>> - Change hash_block() to use an unsigned int len
>>> - Clarify use of output_size parameter to hash_block()
>>> - Correct bug in setting control FDT
>>> - Fix FDT error handling in fit_image_write_sig()
>>> - Fix checkpatch checks about parenthesis alignment
>>> - Fix checkpatch warnings about space after cast
>>> - Fix checkpatch warnings about split strings
>>> - Fix line continuation problem
>>> - Fix spelling of multiply in rsa-verify.c
>>> - Fix spelling of quite
>>> - Fix typo "os defined" -> "is defined"
>>> - Move sandbox's command list patch from a later series
>>> - Only build RSA support into mkimage if CONFIG_RSA is defined
>>> - Put err_msgp strings on a single line
>>> - Put params before description in fit_conf_get_prop_node() comment
>>> - Rebase on previous patches
>>> - Rebase to use updated fdt_valid() function
>>> - Rename commit message to say "function" instead of "function"
>>> - Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
>>> - Revert the whole change including the set_working_fdt_addr() part
>>> - Support RSA library version without ERR_remove_thread_state()
>>> - Tweak tools/Makefile to make image signing optional
>>> - Update README to fix typos
>>> - Update README to fix typos and clarify some points
>>> - Use U-Boot's -c option instead of hard-coding a boot script
>>> - Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)
>>> - Use stack instead of calloc() within U-Boot's signature verification code
>>> - fdt_valid() sets the FDT pointer to NULL on error, to simplify callers
>>> - gd->fdt_blob is now available on all archs (generic board landed)
>>>
>>> Simon Glass (45):
>>>   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 function
>>>   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: 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
>>>   image: Remove remaining #ifdefs in image-fit.c
>>>   image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
>>>   sandbox: Allow -c argument to provide a command list
>>>   Add verified boot information and test
>>>
>>>  Makefile                         |    1 +
>>>  README                           |   21 +
>>>  arch/sandbox/cpu/cpu.c           |    5 +
>>>  arch/sandbox/cpu/start.c         |    9 +-
>>>  arch/sandbox/include/asm/io.h    |    2 +
>>>  arch/sandbox/include/asm/state.h |    1 +
>>>  arch/sandbox/lib/board.c         |   38 +-
>>>  common/Makefile                  |    2 +
>>>  common/cmd_bootm.c               |   37 +-
>>>  common/cmd_fdt.c                 |   87 +-
>>>  common/cmd_fpga.c                |    2 +-
>>>  common/cmd_nvedit.c              |   19 +-
>>>  common/cmd_source.c              |    2 +-
>>>  common/cmd_ximg.c                |    2 +-
>>>  common/hash.c                    |   23 +
>>>  common/image-fit.c               | 1533 ++++++++++++++++++++++++++++++++++
>>>  common/image-sig.c               |  430 ++++++++++
>>>  common/image.c                   | 1686 +-------------------------------------
>>>  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     |  382 +++++++++
>>>  doc/uImage.FIT/verified-boot.txt |  104 +++
>>>  include/bootstage.h              |    5 +-
>>>  include/common.h                 |   18 +
>>>  include/configs/sandbox.h        |    6 +
>>>  include/hash.h                   |   22 +
>>>  include/image.h                  |  265 +++++-
>>>  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                 |   48 ++
>>>  lib/rsa/rsa-sign.c               |  460 +++++++++++
>>>  lib/rsa/rsa-verify.c             |  385 +++++++++
>>>  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         |  126 +++
>>>  tools/Makefile                   |   23 +-
>>>  tools/aisimage.c                 |    1 -
>>>  tools/fit_image.c                |  136 +--
>>>  tools/image-host.c               |  722 ++++++++++++++++
>>>  tools/mkimage.c                  |   36 +-
>>>  tools/mkimage.h                  |    6 +
>>>  53 files changed, 5485 insertions(+), 1783 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
>>>
>>> --
>>> 1.8.1.3
>>>
>>> _______________________________________________
>>> U-Boot mailing list
>>> U-Boot at lists.denx.de
>>> http://lists.denx.de/mailman/listinfo/u-boot

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-17 18:26     ` Jagan Teki
@ 2013-04-17 18:33       ` Simon Glass
  0 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-04-17 18:33 UTC (permalink / raw)
  To: u-boot

Hi Jagan,

On Wed, Apr 17, 2013 at 11:26 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
> Hi Simon,
>
> On Wed, Apr 17, 2013 at 7:50 PM, Simon Glass <sjg@chromium.org> wrote:
>> Hi,
>>
>> On Mon, Apr 15, 2013 at 1:38 AM, Jagan Teki <jagannadh.teki@gmail.com> wrote:
>>> Hi Simon,
>>>
>>> I am new to this verification boot concept, could you please clarify
>>> my questions.
>>>
>>> On Tue, Mar 19, 2013 at 5:21 AM, Simon Glass <sjg@chromium.org> wrote:
>>>> 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
>>>
>>> 1. Who is doing RSA encryption for images?
>>>     does RSA lib will do with the help of mkimage, if so where can the
>>> lib will get the private key. ?
>>
>> There is a script in test/vboot which shows how this is done.
>> Basically we use openrsa tools to create a private key.
>>
>>> 2. This RSA alogo will encrypt the entire (image+hash) or only encrypt
>>> the hash on each individual image?
>>
>> Be careful with terminology - we don't actually encrypt the images -
>> we only sign them. Signing means that we hash the image and (if you
>> like) encrypt the hash.
>
> Ok, means RSA will encrypt the image, is it?

No, RSA encrypting the image would be very slow. We only encrypt the
hash of the image - this is typically called 'signing the image'.

> There is a AES crypt on lib/aes, can we use aes to encrypt the image
> and RSA for hash, is there any possibility in u-boot
> to do aes and rsa encrypt and decrypt process and boot.

You could use AES to encrypt the image, but that is not supported by
my implementation. You could probably implement this quite easily
since U-Boot already supports AES and already supports decompressing
images, which is sort-of similar.

If you are asking to use AES instead of RSA for the signing, then I'm
not sure what you are trying to achieve. AES requires a shared private
key, and if you have that, you may as well just have a shared hash.
The point of using RSA is that we can sign images which the original
firmware will recognise (based on its public key) without needing to
update that public key in what is assumed to be read-only firmware.

Perhaps it would help if you stepped up a level and explained the
problem you are trying to solve?

Regards,
Simon

>
>>
>> We provide two options:
>>
>> a. Sign each image independently - here we sign the image data
>> b. Sign the configuration, in which case we don't actually sign the
>> image data, only their hashes
>
> What does sign a data image means, can u please clarify.
>
> Thanks,
> Jagan.
>
>>
>>> 3. How can we provide the public key using u-boot devicetree, is there
>>> any other way to provide this key other than dtb?
>>
>> This is describes in the documentation. We use mkimage to add the
>> public key to your device tree. There is no other way currently
>> implemented - at present you need CONFIG_OF_CONTROL. However, with
>> generic board it should be a simple matter to add this for most
>> boards. The device tree is convenient because it supports
>> structured/tagged data, making it clean and easy to store the
>> information.
>>
>>> 4. Suppose some one/other tool does an encryption which consists of
>>> encrypted image+public key, so does your rsa code
>>>     will verify and boot?
>>
>> You don't need to use mkimage - you can certainly create your own tool
>> which does the same thing. Provided you achieve the same result then
>> bootm will still verify and boot.
>>
>> Regards,
>> Simon
>>
>>>
>>> Thanks,
>>> Jagan.
>>>
>>>> cannot be changed after manufacture. Some notes are provided in the
>>>> documentaion on how this can be achieved. The implementation is fairly
>>>> efficient and fits nicely into U-Boot. FIT plus RSA adds around 18KB
>>>> to SPL size which is manageable on modern SoCs.
>>>>
>>>> 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 related to adding image support for sandbox. A follow-on series is
>>>> somewhat more agressive in further refactoring the FIT image support to
>>>> clean it up improve maintainability.
>>>>
>>>> Rollback prevention has been added in a separate TPM patch. This ensures
>>>> that an attacker cannot boot your system with an old image that has been
>>>> compromised. Support for this is not built into bootm, but instead must
>>>> be scripted in U-Boot. It is possible that a standard scheme for this could
>>>> be devised by adding version number tags to the signing procedure. However
>>>> scripts do provide more flexibility. The TPM patch is here:
>>>>
>>>> http://patchwork.ozlabs.org/patch/224163/
>>>>
>>>> This series is available at:
>>>>
>>>> http://git.denx.de/u-boot-x86.git
>>>>
>>>> in the branch 'vboot'.
>>>>
>>>> I have received a number of off-list comments - please do copy the list when
>>>> replying so that everyone can see your comments.
>>>>
>>>> Changes in v2:
>>>> - Add IMAGE_ENABLE_IGNORE to avoid #ifdef around ignore property handling
>>>> - Add comment about why mkimage needs to open FIT with O_RDWR
>>>> - Add new patch to control FIT image printing in SPL
>>>> - Add new patch to remove #ifdefs in image-fit.c
>>>> - Add sanity checks on key sizes in RSA (improves security)
>>>> - Adjust how signing enable works in image.h
>>>> - Adjust mkimage help to separate out signing options
>>>> - Allow the control FDT to be set even if there is currently no control FDT
>>>> - Avoid using malloc in RSA routines (for smaller SPL code size)
>>>> - Build signing support unconditionally in mkimage
>>>> - Change hash_block() to use an unsigned int len
>>>> - Clarify use of output_size parameter to hash_block()
>>>> - Correct bug in setting control FDT
>>>> - Fix FDT error handling in fit_image_write_sig()
>>>> - Fix checkpatch checks about parenthesis alignment
>>>> - Fix checkpatch warnings about space after cast
>>>> - Fix checkpatch warnings about split strings
>>>> - Fix line continuation problem
>>>> - Fix spelling of multiply in rsa-verify.c
>>>> - Fix spelling of quite
>>>> - Fix typo "os defined" -> "is defined"
>>>> - Move sandbox's command list patch from a later series
>>>> - Only build RSA support into mkimage if CONFIG_RSA is defined
>>>> - Put err_msgp strings on a single line
>>>> - Put params before description in fit_conf_get_prop_node() comment
>>>> - Rebase on previous patches
>>>> - Rebase to use updated fdt_valid() function
>>>> - Rename commit message to say "function" instead of "function"
>>>> - Require CONFIG_FIT_SIGNATURE in image.h for mkimage to support signing
>>>> - Revert the whole change including the set_working_fdt_addr() part
>>>> - Support RSA library version without ERR_remove_thread_state()
>>>> - Tweak tools/Makefile to make image signing optional
>>>> - Update README to fix typos
>>>> - Update README to fix typos and clarify some points
>>>> - Use U-Boot's -c option instead of hard-coding a boot script
>>>> - Use gd->arch.ram_buf instead of gd->ram_buf (now that generic board is in)
>>>> - Use stack instead of calloc() within U-Boot's signature verification code
>>>> - fdt_valid() sets the FDT pointer to NULL on error, to simplify callers
>>>> - gd->fdt_blob is now available on all archs (generic board landed)
>>>>
>>>> Simon Glass (45):
>>>>   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 function
>>>>   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: 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
>>>>   image: Remove remaining #ifdefs in image-fit.c
>>>>   image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL
>>>>   sandbox: Allow -c argument to provide a command list
>>>>   Add verified boot information and test
>>>>
>>>>  Makefile                         |    1 +
>>>>  README                           |   21 +
>>>>  arch/sandbox/cpu/cpu.c           |    5 +
>>>>  arch/sandbox/cpu/start.c         |    9 +-
>>>>  arch/sandbox/include/asm/io.h    |    2 +
>>>>  arch/sandbox/include/asm/state.h |    1 +
>>>>  arch/sandbox/lib/board.c         |   38 +-
>>>>  common/Makefile                  |    2 +
>>>>  common/cmd_bootm.c               |   37 +-
>>>>  common/cmd_fdt.c                 |   87 +-
>>>>  common/cmd_fpga.c                |    2 +-
>>>>  common/cmd_nvedit.c              |   19 +-
>>>>  common/cmd_source.c              |    2 +-
>>>>  common/cmd_ximg.c                |    2 +-
>>>>  common/hash.c                    |   23 +
>>>>  common/image-fit.c               | 1533 ++++++++++++++++++++++++++++++++++
>>>>  common/image-sig.c               |  430 ++++++++++
>>>>  common/image.c                   | 1686 +-------------------------------------
>>>>  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     |  382 +++++++++
>>>>  doc/uImage.FIT/verified-boot.txt |  104 +++
>>>>  include/bootstage.h              |    5 +-
>>>>  include/common.h                 |   18 +
>>>>  include/configs/sandbox.h        |    6 +
>>>>  include/hash.h                   |   22 +
>>>>  include/image.h                  |  265 +++++-
>>>>  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                 |   48 ++
>>>>  lib/rsa/rsa-sign.c               |  460 +++++++++++
>>>>  lib/rsa/rsa-verify.c             |  385 +++++++++
>>>>  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         |  126 +++
>>>>  tools/Makefile                   |   23 +-
>>>>  tools/aisimage.c                 |    1 -
>>>>  tools/fit_image.c                |  136 +--
>>>>  tools/image-host.c               |  722 ++++++++++++++++
>>>>  tools/mkimage.c                  |   36 +-
>>>>  tools/mkimage.h                  |    6 +
>>>>  53 files changed, 5485 insertions(+), 1783 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
>>>>
>>>> --
>>>> 1.8.1.3
>>>>
>>>> _______________________________________________
>>>> U-Boot mailing list
>>>> U-Boot at lists.denx.de
>>>> http://lists.denx.de/mailman/listinfo/u-boot

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-02  0:13 ` [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Kim Phillips
@ 2013-04-20 23:03   ` Simon Glass
  2013-04-22 23:44     ` Kim Phillips
  0 siblings, 1 reply; 56+ messages in thread
From: Simon Glass @ 2013-04-20 23:03 UTC (permalink / raw)
  To: u-boot

Hi Kim,

On Mon, Apr 1, 2013 at 5:13 PM, Kim Phillips <kim.phillips@freescale.com> wrote:
> On Mon, 18 Mar 2013 16:51:20 -0700
> Simon Glass <sjg@chromium.org> wrote:
>
>> I have received a number of off-list comments - please do copy the list when
>> replying so that everyone can see your comments.
>
> I don't have time to fully review 45 patches, let alone the subject
> matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
> some things that bugged me:
>
> Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":
>
> - Where's our libfdt maintainer?  libfdt patches should be submitted
> to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
> fdt_find_regions()" also suffers from this problem.

The fdt_next_subnode() is a pretty trivial change. I will submit it to
the dtc project.

The fdt_find_regions() was submitted to dtc as part of the dtc fdtgrep
series. I modified the form of it in response to review feedback and
that is ongoing.

>
> - can we improve on the readability of that for loop - the improved
> one the patch gives us is this:
>
>> for (ndepth = 0,
>>               noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
>>               noffset >= 0;
>>               noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
>
> whereas perhaps something like this:
>
> ndepth = 0;
> noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
> while (noffset >= 0) {
>         // body
>         noffset = fdt_next_subnode(fit, noffset, &ndepth);
> }
>
> would be much easier to quickly visually parse?

This suffers from the problem that a 'continue' will not work as
expected. I think the existing for() loop is a little better overall -
everything is in one place.

>
> this would also affect:
>
> Re: "[PATCH v2 12/45] image: Move hash checking into its own function":
> - which also adds lines like these:
>
>> +             *err_msgp = " error!\nCan't get hash algo "
>> +                             "property";
>
> upon which a subsequent patch ("[PATCH v2 13/45] image: Move error!
> string to common place", if I'm not mistaken) corrects.  Are you
> intentionally trying to make people review the same code twice??
>

No, what is happening here is that the first patch moves the code into
a function, and the second patch removes the 'error' part of the
strings, not just from that moved code but from everywhere. I find
that doing two things at once is harder to review.

I am certainly not added 'error' to the strings in one patch and
taking it away in the next :-)

> Re: "[PATCH v2 07/45] image: Split FIT code into new image-fit.c"
> - after the code is split, it appears the rest of the patchseries
> works on improving image-fit.c instead of updating equivalent code
> still existing in image.c, IIRC, "[PATCH v2 13/45] image: Move error!
> string to common place"
> - I also found it odd that git format-patch -M on this doesn't
> produce a shorter patch with "% equivalent" statistics: what else
> changed?

Are you suggesting that more patches should affect image.c? If so,
please let me know what should specifically you want done and I will
take a look. Or perhaps we can improve it once the dust clears.

>
> Re: "[PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit":
> - I personally appreciate it when authors of such large patchseries
> put the trivial stuff first, as if to follow the logical progression
> of the complexity (and therefore acceptability) of the patches in
> the series.  Make things like this the first patch in the series -
> that way maintainers can be tempted to start applying obvious
> patches from early patchseries versions.  This also applies to
> patches like [PATCH v2 24/45] Revert "fdt- Tell the FDT library
> where the device tree is", and:
>
> Re: "[PATCH v2 25/45] Add stdarg to vsprintf.h":
> - which contains the text "TODO: Probably should drop this patch?".
> Well?  Did you mean this series to be an RFC?

Yes I am going to split this up into 3-4 series. The first one
(sandbox changes) was sent earlier today. The next one will focus on
the initial improvements to the image code, and will include these
trivial patches - I will ensure that they are at the start - I agree
it is better that way.

The series was originally RFC, but in version 2 I removed that tag.
Part 25 was added to deal with HOSTCC building vsprintf.h, but I
subsequently found that we could avoid that. I will drop it from v3.

>
> I'm stopping my already brief review here - please clean this up.

Thanks for looking at this.

>
> Kim
>

Regards,
Simon

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-20 23:03   ` Simon Glass
@ 2013-04-22 23:44     ` Kim Phillips
  2013-04-23 14:50       ` Tom Rini
  0 siblings, 1 reply; 56+ messages in thread
From: Kim Phillips @ 2013-04-22 23:44 UTC (permalink / raw)
  To: u-boot

On Sat, 20 Apr 2013 16:03:20 -0700
Simon Glass <sjg@chromium.org> wrote:

> On Mon, Apr 1, 2013 at 5:13 PM, Kim Phillips <kim.phillips@freescale.com> wrote:
> > On Mon, 18 Mar 2013 16:51:20 -0700
> > Simon Glass <sjg@chromium.org> wrote:
> >
> >> I have received a number of off-list comments - please do copy the list when
> >> replying so that everyone can see your comments.
> >
> > I don't have time to fully review 45 patches, let alone the subject
> > matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
> > some things that bugged me:
> >
> > Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":
> >
> > - Where's our libfdt maintainer?  libfdt patches should be submitted
> > to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
> > fdt_find_regions()" also suffers from this problem.
> 
> The fdt_next_subnode() is a pretty trivial change. I will submit it to
> the dtc project.

Ideally we'd apply the patch directly from how it was applied to the
upstream dtc project.

> The fdt_find_regions() was submitted to dtc as part of the dtc fdtgrep
> series. I modified the form of it in response to review feedback and
> that is ongoing.

ok.

> > - can we improve on the readability of that for loop - the improved
> > one the patch gives us is this:
> >
> >> for (ndepth = 0,
> >>               noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
> >>               noffset >= 0;
> >>               noffset = fdt_next_subnode(fit, noffset, &ndepth)) {
> >
> > whereas perhaps something like this:
> >
> > ndepth = 0;
> > noffset = fdt_next_subnode(fit, image_noffset, &ndepth);
> > while (noffset >= 0) {
> >         // body
> >         noffset = fdt_next_subnode(fit, noffset, &ndepth);
> > }
> >
> > would be much easier to quickly visually parse?
> 
> This suffers from the problem that a 'continue' will not work as
> expected.

It's not like that can't be fixed - either by manually assigning
noffset before it, or by using a goto.

> I think the existing for() loop is a little better overall -
> everything is in one place.

it's ugly and comparatively unreadable, esp. given its alignment and
the ndepth initialization...

> > this would also affect:
> >
> > Re: "[PATCH v2 12/45] image: Move hash checking into its own function":
> > - which also adds lines like these:
> >
> >> +             *err_msgp = " error!\nCan't get hash algo "
> >> +                             "property";
> >
> > upon which a subsequent patch ("[PATCH v2 13/45] image: Move error!
> > string to common place", if I'm not mistaken) corrects.  Are you
> > intentionally trying to make people review the same code twice??
> 
> No, what is happening here is that the first patch moves the code into
> a function, and the second patch removes the 'error' part of the
> strings, not just from that moved code but from everywhere. I find
> that doing two things at once is harder to review.
> 
> I am certainly not added 'error' to the strings in one patch and
> taking it away in the next :-)

it sounds like the 'error' string removal should appear earlier in
the patchseries.

> > Re: "[PATCH v2 07/45] image: Split FIT code into new image-fit.c"
> > - after the code is split, it appears the rest of the patchseries
> > works on improving image-fit.c instead of updating equivalent code
> > still existing in image.c, IIRC, "[PATCH v2 13/45] image: Move error!
> > string to common place"
> > - I also found it odd that git format-patch -M on this doesn't
> > produce a shorter patch with "% equivalent" statistics: what else
> > changed?
> 
> Are you suggesting that more patches should affect image.c? If so,
> please let me know what should specifically you want done and I will
> take a look. Or perhaps we can improve it once the dust clears.

as above, I believe the answer is to make the common changes (to
both image.c and image-fit.c) earlier in the patchseries.

Thanks,

Kim

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-22 23:44     ` Kim Phillips
@ 2013-04-23 14:50       ` Tom Rini
  2013-04-25 18:51         ` Simon Glass
  0 siblings, 1 reply; 56+ messages in thread
From: Tom Rini @ 2013-04-23 14:50 UTC (permalink / raw)
  To: u-boot

On Mon, Apr 22, 2013 at 06:44:53PM -0500, Kim Phillips wrote:
> On Sat, 20 Apr 2013 16:03:20 -0700
> Simon Glass <sjg@chromium.org> wrote:
> 
> > On Mon, Apr 1, 2013 at 5:13 PM, Kim Phillips <kim.phillips@freescale.com> wrote:
> > > On Mon, 18 Mar 2013 16:51:20 -0700
> > > Simon Glass <sjg@chromium.org> wrote:
> > >
> > >> I have received a number of off-list comments - please do copy the list when
> > >> replying so that everyone can see your comments.
> > >
> > > I don't have time to fully review 45 patches, let alone the subject
> > > matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
> > > some things that bugged me:
> > >
> > > Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":
> > >
> > > - Where's our libfdt maintainer?  libfdt patches should be submitted
> > > to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
> > > fdt_find_regions()" also suffers from this problem.
> > 
> > The fdt_next_subnode() is a pretty trivial change. I will submit it to
> > the dtc project.
> 
> Ideally we'd apply the patch directly from how it was applied to the
> upstream dtc project.

And importantly, that's how we try and work this area in general.  Get
it upstream into dtc, mirror the change.  So lets get all of the fdt
related stuff there and pull it back down.

-- 
Tom
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20130423/7f5fdd9b/attachment.pgp>

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-23 14:50       ` Tom Rini
@ 2013-04-25 18:51         ` Simon Glass
  2013-05-01  4:56           ` Simon Glass
  0 siblings, 1 reply; 56+ messages in thread
From: Simon Glass @ 2013-04-25 18:51 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Tue, Apr 23, 2013 at 7:50 AM, Tom Rini <trini@ti.com> wrote:
> On Mon, Apr 22, 2013 at 06:44:53PM -0500, Kim Phillips wrote:
>> On Sat, 20 Apr 2013 16:03:20 -0700
>> Simon Glass <sjg@chromium.org> wrote:
>>
>> > On Mon, Apr 1, 2013 at 5:13 PM, Kim Phillips <kim.phillips@freescale.com> wrote:
>> > > On Mon, 18 Mar 2013 16:51:20 -0700
>> > > Simon Glass <sjg@chromium.org> wrote:
>> > >
>> > >> I have received a number of off-list comments - please do copy the list when
>> > >> replying so that everyone can see your comments.
>> > >
>> > > I don't have time to fully review 45 patches, let alone the subject
>> > > matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
>> > > some things that bugged me:
>> > >
>> > > Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":
>> > >
>> > > - Where's our libfdt maintainer?  libfdt patches should be submitted
>> > > to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
>> > > fdt_find_regions()" also suffers from this problem.
>> >
>> > The fdt_next_subnode() is a pretty trivial change. I will submit it to
>> > the dtc project.
>>
>> Ideally we'd apply the patch directly from how it was applied to the
>> upstream dtc project.
>
> And importantly, that's how we try and work this area in general.  Get
> it upstream into dtc, mirror the change.  So lets get all of the fdt
> related stuff there and pull it back down.

Yes - the major patch was sent back around the same time as the
verified boot series, along with an fdtgrep tool. I sent the
fdt_next_subnode() patch earlier today.

>
> --
> Tom

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

* [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT
  2013-04-25 18:51         ` Simon Glass
@ 2013-05-01  4:56           ` Simon Glass
  0 siblings, 0 replies; 56+ messages in thread
From: Simon Glass @ 2013-05-01  4:56 UTC (permalink / raw)
  To: u-boot

Hi Tom,

On Thu, Apr 25, 2013 at 11:51 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Tom,
>
> On Tue, Apr 23, 2013 at 7:50 AM, Tom Rini <trini@ti.com> wrote:
>> On Mon, Apr 22, 2013 at 06:44:53PM -0500, Kim Phillips wrote:
>>> On Sat, 20 Apr 2013 16:03:20 -0700
>>> Simon Glass <sjg@chromium.org> wrote:
>>>
>>> > On Mon, Apr 1, 2013 at 5:13 PM, Kim Phillips <kim.phillips@freescale.com> wrote:
>>> > > On Mon, 18 Mar 2013 16:51:20 -0700
>>> > > Simon Glass <sjg@chromium.org> wrote:
>>> > >
>>> > >> I have received a number of off-list comments - please do copy the list when
>>> > >> replying so that everyone can see your comments.
>>> > >
>>> > > I don't have time to fully review 45 patches, let alone the subject
>>> > > matter (e.g., no support for RSA in h/w, eh? ;), but I did notice
>>> > > some things that bugged me:
>>> > >
>>> > > Re: "[PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration":
>>> > >
>>> > > - Where's our libfdt maintainer?  libfdt patches should be submitted
>>> > > to the dtc project first.  It appears "[PATCH v2 40/45] libfdt: Add
>>> > > fdt_find_regions()" also suffers from this problem.
>>> >
>>> > The fdt_next_subnode() is a pretty trivial change. I will submit it to
>>> > the dtc project.
>>>
>>> Ideally we'd apply the patch directly from how it was applied to the
>>> upstream dtc project.
>>
>> And importantly, that's how we try and work this area in general.  Get
>> it upstream into dtc, mirror the change.  So lets get all of the fdt
>> related stuff there and pull it back down.
>
> Yes - the major patch was sent back around the same time as the
> verified boot series, along with an fdtgrep tool. I sent the
> fdt_next_subnode() patch earlier today.

OK this was accepted to dtc upstream in modified form. I will update
the series for U-Boot.

In case you want an update on the overall work, I have now split things into:

sandbox - http://patchwork.ozlabs.org/bundle/sjg/sandbox/ and I sent a
pull request if you want this
image1 - Allow images to work on sandbox, sent, needs this libfdt patch replaced
image2 - Introduce a common image_setup_linux() function, to send
image3 - image: Reduce code duplication and refactor, to send
vboot - Verified boot implementation based on FIT, final series, to send

I will do image1 in the next few days, and the rest hopefully next
week. I think it makes sense having vboot last.

Regards,
Simon

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

end of thread, other threads:[~2013-05-01  4:56 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-18 23:51 [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 01/45] sandbox: config: Enable CONFIG_FIT and CONFIG_CMD_FIT Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 02/45] bootstage: Don't build for HOSTCC Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 03/45] mkimage: Move ARRAY_SIZE to header file Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 04/45] libfdt: Add fdt_next_subnode() to permit easy subnode iteration Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 05/45] image: Move timestamp #ifdefs to header file Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 06/45] image: Export fit_check_ramdisk() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 07/45] image: Split FIT code into new image-fit.c Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 08/45] image: Move HOSTCC image code to tools/ Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 09/45] image: Split hash node processing into its own function Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 10/45] image: Convert fit_image_hash_set_value() to static, and rename Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 11/45] image: Rename fit_image_check_hashes() to fit_image_verify() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 12/45] image: Move hash checking into its own function Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 13/45] image: Move error! string to common place Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 14/45] image: Export fit_conf_get_prop_node() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 15/45] image: Rename fit_add_hashes() to fit_add_verification_data() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 16/45] image: Rename hash printing to fit_image_print_verification_data() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 17/45] sandbox: Add CONFIG_OF_HOSTFILE to read FDT from host file Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 18/45] fdt: Add a parameter to fdt_valid() Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 19/45] Add getenv_hex() to return an environment variable as hex Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 20/45] fdt: Allow fdt command to check and update control FDT Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 21/45] sandbox: fdt: Support fdt command for sandbox Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 22/45] env: Fix minor comment typos in cmd_nvedit Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 23/45] fdt: Skip checking FDT if the pointer is NULL Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 24/45] Revert "fdt- Tell the FDT library where the device tree is" Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 25/45] Add stdarg to vsprintf.h Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 26/45] Add minor updates to README.fdt-control Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 27/45] hash: Add a way to calculate a hash for any algortihm Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 28/45] sandbox: config: Enable FIT signatures with RSA Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 29/45] sandbox: Provide a way to map from host RAM to U-Boot RAM Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 30/45] sandbox: image: Add support for booting images in sandbox Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 31/45] image: Add signing infrastructure Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 32/45] image: Support signing of images Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 33/45] image: Add RSA support for image signing Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 34/45] mkimage: Put FIT loading in function and tidy error handling Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 35/45] mkimage: Add -k option to specify key directory Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 36/45] mkimage: Add -K to write public keys to an FDT blob Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 37/45] mkimage: Add -F option to modify an existing .fit file Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 38/45] mkimage: Add -c option to specify a comment for key signing Simon Glass
2013-03-18 23:51 ` [U-Boot] [PATCH v2 39/45] mkimage: Add -r option to specify keys that must be verified Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 40/45] libfdt: Add fdt_find_regions() Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 41/45] image: Add support for signing of FIT configurations Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 42/45] image: Remove remaining #ifdefs in image-fit.c Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 43/45] image: Add CONFIG_FIT_SPL_PRINT to control FIT image printing in SPL Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 44/45] sandbox: Allow -c argument to provide a command list Simon Glass
2013-03-18 23:52 ` [U-Boot] [PATCH v2 45/45] Add verified boot information and test Simon Glass
2013-04-02  0:13 ` [U-Boot] [PATCH v2 0/45] Verified boot implementation based on FIT Kim Phillips
2013-04-20 23:03   ` Simon Glass
2013-04-22 23:44     ` Kim Phillips
2013-04-23 14:50       ` Tom Rini
2013-04-25 18:51         ` Simon Glass
2013-05-01  4:56           ` Simon Glass
2013-04-15  8:38 ` Jagan Teki
2013-04-17 14:20   ` Simon Glass
2013-04-17 18:26     ` Jagan Teki
2013-04-17 18:33       ` Simon Glass

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