[U-Boot] [PATCH v3 0/8] common, fit, rsa: enhancements

- add sha256,rsa2048 and sha256,rsa4098 support to u-boot. - add "fdt checksign" command to u-boot cmdshell. This command checks, if a fdt is correct signed. - add hosttool "fit_info" which prints the offset and the len of a property from in a fdt file. This values can be used, to extract the data from a property (for example with "dd") - add hosttool "fit_check_sign". This does the same as the u-boot cmdshell tool "fdt sign". It checks, if fit image is correct signed
- changes for v2: - add comments from Simon Glass - add new patch: "[PATCH v2 6/8] gen: Add progressive hash API" from Hung-ying Tyan <tyanh at chromium.org> as Simon Glass mentioned
- changes for v3: - add comments from Simon Glass: - rebased against current head eeb72e67619b98d2502fe634a3a5d9953de92ad0 -> Makefile adaptions necessary introduced from kbuild changes
Heiko Schocher (8): tools/image-host: fix sign-images bug fdt: add "fdt checksign" command fit: add sha256 support rsa: add sha256-rsa2048 algorithm rsa: add sha256,rsa4096 algorithm gen: Add progressive hash API tools, fit: add fit_info host command tools, fit_check_sign: verify a signed fit image
common/cmd_fdt.c | 42 +++++- common/hash.c | 116 +++++++++++++-- common/image-fit.c | 5 + common/image-sig.c | 63 ++++++++ doc/uImage.FIT/signature.txt | 20 ++- include/fdt_support.h | 5 + include/hash.h | 48 ++++++ include/image.h | 38 ++++- include/rsa-checksum.h | 24 +++ include/rsa.h | 24 +++ lib/fdtdec.c | 20 +++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 163 +++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 +- lib/rsa/rsa-verify.c | 107 +++++--------- lib/sha256.c | 5 +- .../{sign-configs.its => sign-configs-sha1.its} | 0 test/vboot/sign-configs-sha256.its | 45 ++++++ .../{sign-images.its => sign-images-sha1.its} | 0 test/vboot/sign-images-sha256.its | 42 ++++++ test/vboot/vboot_test.sh | 86 +++++++---- tools/.gitignore | 2 + tools/Makefile | 16 +- tools/fdt_host.h | 2 + tools/fdtdec.c | 1 + tools/fit_check_sign.c | 85 +++++++++++ tools/fit_common.c | 86 +++++++++++ tools/fit_common.h | 22 +++ tools/fit_image.c | 62 +------- tools/fit_info.c | 96 ++++++++++++ tools/image-host.c | 17 ++- tools/rsa-checksum.c | 1 + tools/rsa-verify.c | 1 + tools/sha256.c | 1 + 34 files changed, 1076 insertions(+), 181 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c rename test/vboot/{sign-configs.its => sign-configs-sha1.its} (100%) create mode 100644 test/vboot/sign-configs-sha256.its rename test/vboot/{sign-images.its => sign-images-sha1.its} (100%) create mode 100644 test/vboot/sign-images-sha256.its create mode 100644 tools/fdtdec.c create mode 100644 tools/fit_check_sign.c create mode 100644 tools/fit_common.c create mode 100644 tools/fit_common.h create mode 100644 tools/fit_info.c create mode 100644 tools/rsa-checksum.c create mode 100644 tools/rsa-verify.c create mode 100644 tools/sha256.c
Cc: Simon Glass sjg@chromium.org Cc: Hung-ying Tyan tyanh@chromium.org Cc: andreas@oetken.name

property "sign-images" is never found, fix this.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
--- changes for v2: - add Acked-by from Simon Glass --- tools/image-host.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/image-host.c b/tools/image-host.c index 0d5c88c..8e185ec 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -403,7 +403,7 @@ static int fit_config_get_hash_list(void *fit, int conf_noffset, goto err_mem;
/* Get a list of images that we intend to sign */ - prop = fit_config_get_image_list(fit, conf_noffset, &len, + prop = fit_config_get_image_list(fit, sig_offset, &len, &allow_missing); if (!prop) return 0;

On Mon, Mar 03, 2014 at 12:19:23PM +0100, Heiko Schocher wrote:
property "sign-images" is never found, fix this.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
--- changes vor v2: - add comment from Simon Glass: - rename "fdt sign" to "fdt checksign" -> rename patch subject from "fdt: add "fdt sign" command" to "fdt: add "fdt checksign" command" - add error message changes for v2: add Acked-by from Simon Glass --- common/cmd_fdt.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 3a9edd6..a6744ed 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -570,7 +570,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ft_board_setup(working_fdt, gd->bd); #endif /* Create a chosen node */ - else if (argv[1][0] == 'c') { + else if (strncmp(argv[1], "cho", 3) == 0) { unsigned long initrd_start = 0, initrd_end = 0;
if ((argc != 2) && (argc != 4)) @@ -583,6 +583,41 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
fdt_chosen(working_fdt, 1); fdt_initrd(working_fdt, initrd_start, initrd_end, 1); + +#if defined(CONFIG_FIT_SIGNATURE) + } else if (strncmp(argv[1], "che", 3) == 0) { + int cfg_noffset; + int ret; + unsigned long addr; + struct fdt_header *blob; + + if (!working_fdt) + return CMD_RET_FAILURE; + + if (argc > 2) { + addr = simple_strtoul(argv[2], NULL, 16); + blob = map_sysmem(addr, 0); + } else { + blob = (struct fdt_header *)gd->fdt_blob; + } + if (!fdt_valid(&blob)) + return 1; + + gd->fdt_blob = blob; + cfg_noffset = fit_conf_get_node(working_fdt, NULL); + if (!cfg_noffset) { + printf("Could not find configuration node: %s\n", + fdt_strerror(cfg_noffset)); + return CMD_RET_FAILURE; + } + + ret = fit_config_verify(working_fdt, cfg_noffset); + if (ret == 1) + return CMD_RET_SUCCESS; + else + return CMD_RET_FAILURE; +#endif + } /* resize the fdt */ else if (strncmp(argv[1], "re", 2) == 0) { @@ -992,6 +1027,11 @@ static char fdt_help_text[] = "fdt rsvmem delete <index> - Delete a mem reserves\n" "fdt chosen [<start> <end>] - Add/update the /chosen branch in the tree\n" " <start>/<end> - initrd start/end addr\n" +#if defined(CONFIG_FIT_SIGNATURE) + "fdt checksign [<addr>] - check FIT signature\n" + " <start> - addr of key blob\n" + " default gd->fdt_blob\n" +#endif "NOTE: Dereference aliases by omiting the leading '/', " "e.g. fdt print ethernet0."; #endif

On Mon, Mar 03, 2014 at 12:19:24PM +0100, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

add sha256 support to fit images
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
--- changes for v2: - add Acked-by from Simon Glass
changes for v3: - add comment from Simon Glass: - remove const attribute - do not remove IMAGE_ENABLE_SHA256, as we have no board config file when compiling mkimage for the host - rebased against current head eeb72e67619b98d2502fe634a3a5d9953de92ad0 -> Makefile adaptions necessary introduced from kbuild changes --- common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 5 +++-- tools/Makefile | 3 ++- tools/sha256.c | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 tools/sha256.c
diff --git a/common/image-fit.c b/common/image-fit.c index b94a3fe..77f32bc 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -22,6 +22,7 @@ DECLARE_GLOBAL_DATA_PTR;
#include <bootstage.h> #include <sha1.h> +#include <sha256.h> #include <u-boot/crc.h> #include <u-boot/md5.h>
@@ -882,6 +883,10 @@ int calculate_hash(const void *data, int data_len, const char *algo, sha1_csum_wd((unsigned char *)data, data_len, (unsigned char *)value, CHUNKSZ_SHA1); *value_len = 20; + } else if (IMAGE_ENABLE_SHA256 && strcmp(algo, "sha256") == 0) { + sha256_csum_wd((unsigned char *)data, data_len, + (unsigned char *)value, CHUNKSZ_SHA256); + *value_len = SHA256_SUM_LEN; } else if (IMAGE_ENABLE_MD5 && strcmp(algo, "md5") == 0) { md5_wd((unsigned char *)data, data_len, value, CHUNKSZ_MD5); *value_len = 16; diff --git a/include/image.h b/include/image.h index 6afd57b..52969aa 100644 --- a/include/image.h +++ b/include/image.h @@ -57,13 +57,18 @@ struct lmb; # ifdef CONFIG_SPL_SHA1_SUPPORT # define IMAGE_ENABLE_SHA1 1 # endif +# ifdef CONFIG_SPL_SHA256_SUPPORT +# define IMAGE_ENABLE_SHA256 1 +# endif # else # define CONFIG_CRC32 /* FIT images need CRC32 support */ # define CONFIG_MD5 /* and MD5 */ # define CONFIG_SHA1 /* and SHA1 */ +# define CONFIG_SHA256 /* and SHA256 */ # define IMAGE_ENABLE_CRC32 1 # define IMAGE_ENABLE_MD5 1 # define IMAGE_ENABLE_SHA1 1 +# define IMAGE_ENABLE_SHA256 1 # endif
#ifndef IMAGE_ENABLE_CRC32 @@ -78,6 +83,10 @@ struct lmb; #define IMAGE_ENABLE_SHA1 0 #endif
+#ifndef IMAGE_ENABLE_SHA256 +#define IMAGE_ENABLE_SHA256 0 +#endif + #endif /* CONFIG_FIT */
#ifdef CONFIG_SYS_BOOT_RAMDISK_HIGH diff --git a/lib/sha256.c b/lib/sha256.c index 7348162..3212bab 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -258,14 +258,15 @@ void sha256_csum_wd(const unsigned char *input, unsigned int ilen, { sha256_context ctx; #if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - unsigned char *end, *curr; + const unsigned char *end; + unsigned char *curr; int chunk; #endif
sha256_starts(&ctx);
#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG) - curr = input; + curr = (unsigned char *)input; end = input + ilen; while (curr < end) { chunk = end - curr; diff --git a/tools/Makefile b/tools/Makefile index dcd49f8..c5dbc31 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -40,7 +40,6 @@ CONFIG_BUILD_ENVCRC ?= $(ENVCRC-y)
# TODO: CONFIG_CMD_LICENSE does not work hostprogs-$(CONFIG_CMD_LICENSE) += bin2header$(SFX) - hostprogs-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX) hostprogs-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX) HOSTCFLAGS_bmp_logo$(SFX).o := -pedantic @@ -85,6 +84,7 @@ dumpimage-mkimage-objs := aisimage.o \ os_support.o \ pblimage.o \ sha1.o \ + sha256.o \ ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS-y) @@ -137,6 +137,7 @@ hostprogs-$(CONFIG_STATIC_RELA) += relocate-rela$(SFX) HOSTCFLAGS_crc32.o := -pedantic HOSTCFLAGS_md5.o := -pedantic HOSTCFLAGS_sha1.o := -pedantic +HOSTCFLAGS_sha256.o := -pedantic
# Don't build by default #hostprogs-$(CONFIG_PPC) += mpc86x_clk$(SFX) diff --git a/tools/sha256.c b/tools/sha256.c new file mode 100644 index 0000000..8ca931f --- /dev/null +++ b/tools/sha256.c @@ -0,0 +1 @@ +#include "../lib/sha256.c"

On Mon, Mar 03, 2014 at 12:19:25PM +0100, Heiko Schocher wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

based on patch from andreas@oetken.name:
http://patchwork.ozlabs.org/patch/294318/ commit message: I currently need support for rsa-sha256 signatures in u-boot and found out that the code for signatures is not very generic. Thus adding of different hash-algorithms for rsa-signatures is not easy to do without copy-pasting the rsa-code. I attached a patch for how I think it could be better and included support for rsa-sha256. This is a fast first shot.
aditionally work: - removed checkpatch warnings - removed compiler warnings - rebased against current head
Signed-off-by: Heiko Schocher hs@denx.de Cc: andreas@oetken.name Cc: Simon Glass sjg@chromium.org
--- changes for v2: - add comment from Simon Glass: - add commit message from original patch - remove unnecessary function declaration rsa_verify_256() - sandbox: add sha256 tests changes for v3: - add comment from Simon Glass: - remove "#if defined(CONFIG_FIT_SIGNATURE)" - remove "#if IMAGE_ENABLE_VERIFY" - left-align the comments in struct rsa_public_key - test without parameter, do sha1 and sha256 tests in one call --- common/image-sig.c | 38 +++++++++ doc/uImage.FIT/signature.txt | 14 +++- include/image.h | 21 +++++ include/rsa-checksum.h | 23 +++++ include/rsa.h | 14 ++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 98 ++++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 ++- lib/rsa/rsa-verify.c | 83 ++++++------------ .../{sign-configs.its => sign-configs-sha1.its} | 0 test/vboot/sign-configs-sha256.its | 45 ++++++++++ .../{sign-images.its => sign-images-sha1.its} | 0 test/vboot/sign-images-sha256.its | 42 ++++++++++ test/vboot/vboot_test.sh | 66 ++++++++------- 14 files changed, 363 insertions(+), 93 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c rename test/vboot/{sign-configs.its => sign-configs-sha1.its} (100%) create mode 100644 test/vboot/sign-configs-sha256.its rename test/vboot/{sign-images.its => sign-images-sha1.its} (100%) create mode 100644 test/vboot/sign-images-sha256.its
diff --git a/common/image-sig.c b/common/image-sig.c index 973b06d..8b6f49b 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -14,15 +14,53 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <image.h> #include <rsa.h> +#include <rsa-checksum.h>
#define IMAGE_MAX_HASHED_NODES 100
+#ifdef USE_HOSTCC +__attribute__((weak)) void *get_blob(void) +{ + return NULL; +} +#endif + +struct checksum_algo checksum_algos[] = { + { + "sha1", + SHA1_SUM_LEN, +#if IMAGE_ENABLE_SIGN + EVP_sha1, +#else + sha1_calculate, + padding_sha1_rsa2048, +#endif + }, + { + "sha256", + SHA256_SUM_LEN, +#if IMAGE_ENABLE_SIGN + EVP_sha256, +#else + sha256_calculate, + padding_sha256_rsa2048, +#endif + } +}; struct image_sig_algo image_sig_algos[] = { { "sha1,rsa2048", rsa_sign, rsa_add_verify_data, rsa_verify, + &checksum_algos[0], + }, + { + "sha256,rsa2048", + rsa_sign, + rsa_add_verify_data, + rsa_verify, + &checksum_algos[1], } };
diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index bc9f3fa..71f8b6c 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -346,7 +346,9 @@ Simple Verified Boot Test
Please see doc/uImage.FIT/verified-boot.txt for more information
+/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 Build keys +do sha1 test Build FIT with signed images Test Verified Boot Run: unsigned signatures:: OK Sign images @@ -355,10 +357,20 @@ Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images Test Verified Boot Run: signed config: OK +Test Verified Boot Run: signed config with bad hash: OK +do sha256 test +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 Verified Boot Run: signed config with bad hash: OK
Test passed
- Future Work ----------- - Roll-back protection using a TPM is done using the tpm command. This can diff --git a/include/image.h b/include/image.h index 52969aa..44b2b46 100644 --- a/include/image.h +++ b/include/image.h @@ -833,6 +833,7 @@ int calculate_hash(const void *data, int data_len, const char *algo, # ifdef USE_HOSTCC # define IMAGE_ENABLE_SIGN 1 # define IMAGE_ENABLE_VERIFY 0 +# include <openssl/evp.h> #else # define IMAGE_ENABLE_SIGN 0 # define IMAGE_ENABLE_VERIFY 1 @@ -872,6 +873,23 @@ struct image_region { int size; };
+#if IMAGE_ENABLE_VERIFY +# include <rsa-checksum.h> +#endif +struct checksum_algo { + const char *name; + const int checksum_len; +#if IMAGE_ENABLE_SIGN + const EVP_MD *(*calculate)(void); +#else +#if IMAGE_ENABLE_VERIFY + void (*calculate)(const struct image_region region[], + int region_count, uint8_t *checksum); + const uint8_t *rsa_padding; +#endif +#endif +}; + struct image_sig_algo { const char *name; /* Name of algorithm */
@@ -922,6 +940,9 @@ struct image_sig_algo { int (*verify)(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len); + + /* pointer to checksum algorithm */ + struct checksum_algo *checksum; };
/** diff --git a/include/rsa-checksum.h b/include/rsa-checksum.h new file mode 100644 index 0000000..850b253 --- /dev/null +++ b/include/rsa-checksum.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2013, Andreas Oetken. + * + * SPDX-License-Identifier: GPL-2.0+ +*/ + +#ifndef _RSA_CHECKSUM_H +#define _RSA_CHECKSUM_H + +#include <errno.h> +#include <image.h> +#include <sha1.h> +#include <sha256.h> + +extern const uint8_t padding_sha256_rsa2048[]; +extern const uint8_t padding_sha1_rsa2048[]; + +void sha256_calculate(const struct image_region region[], int region_count, + uint8_t *checksum); +void sha1_calculate(const struct image_region region[], int region_count, + uint8_t *checksum); + +#endif diff --git a/include/rsa.h b/include/rsa.h index add4c78..e9ae870 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -15,6 +15,20 @@ #include <errno.h> #include <image.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; /* len 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 */ +}; + #if IMAGE_ENABLE_SIGN /** * sign() - calculate and return signature for given input data diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile index 164ab39..a5a96cb6 100644 --- a/lib/rsa/Makefile +++ b/lib/rsa/Makefile @@ -7,4 +7,4 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o +obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c new file mode 100644 index 0000000..e520e1c --- /dev/null +++ b/lib/rsa/rsa-checksum.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013, Andreas Oetken. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <fdtdec.h> +#include <rsa.h> +#include <sha1.h> +#include <sha256.h> +#include <asm/byteorder.h> +#include <asm/errno.h> +#include <asm/unaligned.h> + +#define RSA2048_BYTES 256 + +/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */ + +const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_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, 0x00, 0x30, 0x31, 0x30, +0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, +0x00, 0x04, 0x20 +}; + +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 +}; + +void sha1_calculate(const struct image_region region[], int region_count, + uint8_t *checksum) +{ + sha1_context ctx; + uint32_t i; + i = 0; + + sha1_starts(&ctx); + for (i = 0; i < region_count; i++) + sha1_update(&ctx, region[i].data, region[i].size); + sha1_finish(&ctx, checksum); +} + +void sha256_calculate(const struct image_region region[], int region_count, + uint8_t *checksum) +{ + sha256_context ctx; + uint32_t i; + i = 0; + + sha256_starts(&ctx); + for (i = 0; i < region_count; i++) + sha256_update(&ctx, region[i].data, region[i].size); + sha256_finish(&ctx, checksum); +} diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 549130e..0fe6e9f 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -159,8 +159,9 @@ static void rsa_remove(void) EVP_cleanup(); }
-static int rsa_sign_with_key(RSA *rsa, const struct image_region region[], - int region_count, uint8_t **sigp, uint *sig_size) +static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo, + const struct image_region region[], int region_count, + uint8_t **sigp, uint *sig_size) { EVP_PKEY *key; EVP_MD_CTX *context; @@ -192,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, const struct image_region region[], goto err_create; } EVP_MD_CTX_init(context); - if (!EVP_SignInit(context, EVP_sha1())) { + if (!EVP_SignInit(context, checksum_algo->calculate())) { ret = rsa_err("Signer setup failed"); goto err_sign; } @@ -242,7 +243,8 @@ int rsa_sign(struct image_sign_info *info, 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); + ret = rsa_sign_with_key(rsa, info->algo->checksum, region, + region_count, sigp, sig_len); if (ret) goto err_sign;
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 02cc4e3..b3573a8 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -8,23 +8,11 @@ #include <fdtdec.h> #include <rsa.h> #include <sha1.h> +#include <sha256.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) @@ -36,39 +24,6 @@ struct rsa_public_key { /* 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 * @@ -209,13 +164,14 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) }
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 uint32_t sig_len, const uint8_t *hash, + struct checksum_algo *algo) { const uint8_t *padding; int pad_len; int ret;
- if (!key || !sig || !hash) + if (!key || !sig || !hash || !algo) return -EIO;
if (sig_len != (key->len * sizeof(uint32_t))) { @@ -223,6 +179,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig, return -EINVAL; }
+ debug("Checksum algorithm: %s", algo->name); + /* Sanity check for stack size */ if (sig_len > RSA_MAX_SIG_BITS / 8) { debug("Signature length %u exceeds maximum %d\n", sig_len, @@ -238,9 +196,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig, if (ret) return ret;
- /* Determine padding to use depending on the signature type. */ - padding = padding_sha1_rsa2048; - pad_len = RSA2048_BYTES - SHA1_SUM_LEN; + padding = algo->rsa_padding; + pad_len = RSA2048_BYTES - algo->checksum_len;
/* Check pkcs1.5 padding bytes. */ if (memcmp(buf, padding, pad_len)) { @@ -309,7 +266,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info, }
debug("key length %d\n", key.len); - ret = rsa_verify_key(&key, sig, sig_len, hash); + ret = rsa_verify_key(&key, sig, sig_len, hash, info->algo->checksum); if (ret) { printf("%s: RSA failed to verify: %d\n", __func__, ret); return ret; @@ -323,12 +280,22 @@ int rsa_verify(struct image_sign_info *info, uint8_t *sig, uint sig_len) { const void *blob = info->fdt_blob; - uint8_t hash[SHA1_SUM_LEN]; + /* Reserve memory for maximum checksum-length */ + uint8_t hash[RSA2048_BYTES]; int ndepth, noffset; int sig_node, node; char name[100]; - sha1_context ctx; - int ret, i; + int ret; + + /* + * Verify that the checksum-length does not exceed the + * rsa-signature-length + */ + if (info->algo->checksum->checksum_len > RSA2048_BYTES) { + debug("%s: invlaid checksum-algorithm %s for RSA2048\n", + __func__, info->algo->checksum->name); + return -EINVAL; + }
sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); if (sig_node < 0) { @@ -336,10 +303,8 @@ int rsa_verify(struct image_sign_info *info, 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); + /* Calculate checksum with checksum-algorithm */ + info->algo->checksum->calculate(region, region_count, hash);
/* See if we must use a particular key */ if (info->required_keynode != -1) { diff --git a/test/vboot/sign-configs.its b/test/vboot/sign-configs-sha1.its similarity index 100% rename from test/vboot/sign-configs.its rename to test/vboot/sign-configs-sha1.its diff --git a/test/vboot/sign-configs-sha256.its b/test/vboot/sign-configs-sha256.its new file mode 100644 index 0000000..1b3432e --- /dev/null +++ b/test/vboot/sign-configs-sha256.its @@ -0,0 +1,45 @@ +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + data = /incbin/("test-kernel.bin"); + type = "kernel_noload"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x4>; + entry = <0x8>; + kernel-version = <1>; + hash@1 { + algo = "sha256"; + }; + }; + fdt@1 { + description = "snow"; + data = /incbin/("sandbox-kernel.dtb"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + fdt-version = <1>; + hash@1 { + algo = "sha256"; + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + signature@1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + sign-images = "fdt", "kernel"; + }; + }; + }; +}; diff --git a/test/vboot/sign-images.its b/test/vboot/sign-images-sha1.its similarity index 100% rename from test/vboot/sign-images.its rename to test/vboot/sign-images-sha1.its diff --git a/test/vboot/sign-images-sha256.its b/test/vboot/sign-images-sha256.its new file mode 100644 index 0000000..e6aa9fc --- /dev/null +++ b/test/vboot/sign-images-sha256.its @@ -0,0 +1,42 @@ +/dts-v1/; + +/ { + description = "Chrome OS kernel image with one or more FDT blobs"; + #address-cells = <1>; + + images { + kernel@1 { + data = /incbin/("test-kernel.bin"); + type = "kernel_noload"; + arch = "sandbox"; + os = "linux"; + compression = "none"; + load = <0x4>; + entry = <0x8>; + kernel-version = <1>; + signature@1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + }; + }; + fdt@1 { + description = "snow"; + data = /incbin/("sandbox-kernel.dtb"); + type = "flat_dt"; + arch = "sandbox"; + compression = "none"; + fdt-version = <1>; + signature@1 { + algo = "sha256,rsa2048"; + key-name-hint = "dev"; + }; + }; + }; + configurations { + default = "conf@1"; + conf@1 { + kernel = "kernel@1"; + fdt = "fdt@1"; + }; + }; +}; diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh index bb2c605..3e2856e 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -61,47 +61,57 @@ openssl req -batch -new -x509 -key ${keys}/dev.key -out ${keys}/dev.crt
pushd ${dir} >/dev/null
-# Compile 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 +function do_test { + echo do $sha test + # Compile our device tree files for kernel and U-Boot + 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 + # 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} + # Build the FIT, but don't sign anything yet + echo Build FIT with signed images + ${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
-run_uboot "unsigned signatures:" "dev-" + 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} + # 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+" + 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 + # 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} + echo Build FIT with signed configuration + ${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp}
-run_uboot "unsigned config" "sha1+ OK" + run_uboot "unsigned config" $sha"+ 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} + # 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+" + run_uboot "signed config" "dev+"
-# Increment the first byte of the signature, which should cause failure -sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value) -newbyte=$(printf %x $((0x${sig:0:2} + 1))) -sig="${newbyte} ${sig:2}" -fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig} + # Increment the first byte of the signature, which should cause failure + sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value) + newbyte=$(printf %x $((0x${sig:0:2} + 1))) + sig="${newbyte} ${sig:2}" + fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
-run_uboot "signed config with bad hash" "Bad Data Hash" + run_uboot "signed config with bad hash" "Bad Data Hash" +} + +sha=sha1 +do_test +sha=sha256 +do_test
popd >/dev/null

Hi Heiko,
On 3 March 2014 04:19, Heiko Schocher hs@denx.de wrote:
based on patch from andreas@oetken.name:
http://patchwork.ozlabs.org/patch/294318/ commit message: I currently need support for rsa-sha256 signatures in u-boot and found out that the code for signatures is not very generic. Thus adding of different hash-algorithms for rsa-signatures is not easy to do without copy-pasting the rsa-code. I attached a patch for how I think it could be better and included support for rsa-sha256. This is a fast first shot.
aditionally work:
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocher hs@denx.de Cc: andreas@oetken.name Cc: Simon Glass sjg@chromium.org
This looks good to me. However, when running it I hit this crash?
O=b/sandbox test/vboot/vboot_test.sh Simple Verified Boot Test =========================
Please see doc/uImage.FIT/verified-boot.txt for more information
/home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 Build keys do sha1 test 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 check signed config on the host *** buffer overflow detected ***: /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign terminated ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f07c7ba9f47] /lib/x86_64-linux-gnu/libc.so.6(+0x109e40)[0x7f07c7ba8e40] /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign[0x40226f] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xed)[0x7f07c7ac076d] /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign[0x4023c5] ======= Memory map: ======== 00400000-0041a000 r-xp 00000000 fc:01 9840801 /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign 00619000-0061a000 r--p 00019000 fc:01 9840801 /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign 0061a000-0061b000 rw-p 0001a000 fc:01 9840801 /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign 0061b000-00711000 rw-p 00000000 00:00 0 00c24000-00c45000 rw-p 00000000 00:00 0 [heap] 7f07c746e000-7f07c7483000 r-xp 00000000 fc:01 2622892 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f07c7483000-7f07c7682000 ---p 00015000 fc:01 2622892 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f07c7682000-7f07c7683000 r--p 00014000 fc:01 2622892 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f07c7683000-7f07c7684000 rw-p 00015000 fc:01 2622892 /lib/x86_64-linux-gnu/libgcc_s.so.1 7f07c7684000-7f07c769a000 r-xp 00000000 fc:01 2622826 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 7f07c769a000-7f07c7899000 ---p 00016000 fc:01 2622826 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 7f07c7899000-7f07c789a000 r--p 00015000 fc:01 2622826 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 7f07c789a000-7f07c789b000 rw-p 00016000 fc:01 2622826 /lib/x86_64-linux-gnu/libz.so.1.2.3.4 7f07c789b000-7f07c789d000 r-xp 00000000 fc:01 2622044 /lib/x86_64-linux-gnu/libdl-2.15.so 7f07c789d000-7f07c7a9d000 ---p 00002000 fc:01 2622044 /lib/x86_64-linux-gnu/libdl-2.15.so 7f07c7a9d000-7f07c7a9e000 r--p 00002000 fc:01 2622044 /lib/x86_64-linux-gnu/libdl-2.15.so 7f07c7a9e000-7f07c7a9f000 rw-p 00003000 fc:01 2622044 /lib/x86_64-linux-gnu/libdl-2.15.so 7f07c7a9f000-7f07c7c54000 r-xp 00000000 fc:01 2622027 /lib/x86_64-linux-gnu/libc-2.15.so 7f07c7c54000-7f07c7e54000 ---p 001b5000 fc:01 2622027 /lib/x86_64-linux-gnu/libc-2.15.so 7f07c7e54000-7f07c7e58000 r--p 001b5000 fc:01 2622027 /lib/x86_64-linux-gnu/libc-2.15.so 7f07c7e58000-7f07c7e5a000 rw-p 001b9000 fc:01 2622027 /lib/x86_64-linux-gnu/libc-2.15.so 7f07c7e5a000-7f07c7e5f000 rw-p 00000000 00:00 0 7f07c7e5f000-7f07c8010000 r-xp 00000000 fc:01 2640614 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 7f07c8010000-7f07c8210000 ---p 001b1000 fc:01 2640614 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 7f07c8210000-7f07c822b000 r--p 001b1000 fc:01 2640614 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 7f07c822b000-7f07c8236000 rw-p 001cc000 fc:01 2640614 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0 7f07c8236000-7f07c823a000 rw-p 00000000 00:00 0 7f07c823a000-7f07c828e000 r-xp 00000000 fc:01 2640615 /lib/x86_64-linux-gnu/libssl.so.1.0.0 7f07c828e000-7f07c848e000 ---p 00054000 fc:01 2640615 /lib/x86_64-linux-gnu/libssl.so.1.0.0 7f07c848e000-7f07c8491000 r--p 00054000 fc:01 2640615 /lib/x86_64-linux-gnu/libssl.so.1.0.0 7f07c8491000-7f07c8497000 rw-p 00057000 fc:01 2640615 /lib/x86_64-linux-gnu/libssl.so.1.0.0 7f07c8497000-7f07c8498000 rw-p 00000000 00:00 0 7f07c8498000-7f07c84ba000 r-xp 00000000 fc:01 2622041 /lib/x86_64-linux-gnu/ld-2.15.so 7f07c869f000-7f07c86a3000 rw-p 00000000 00:00 0 7f07c86b7000-7f07c86ba000 rw-p 00000000 00:00 0 7f07c86ba000-7f07c86bb000 r--p 00022000 fc:01 2622041 /lib/x86_64-linux-gnu/ld-2.15.so 7f07c86bb000-7f07c86bd000 rw-p 00023000 fc:01 2622041 /lib/x86_64-linux-gnu/ld-2.15.so 7fff08a47000-7fff08a68000 rw-p 00000000 00:00 0 [stack] 7fff08ad7000-7fff08ad9000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] test/vboot/vboot_test.sh: line 65: 7597 Aborted (core dumped) ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb > ${tmp}
Verified boot key check on host failed, output follows:
Do you see this? Presumably not - I can dig a bit if you like?
Regards, Simon

Hello Simon,
Am 09.03.2014 06:33, schrieb Simon Glass:
Hi Heiko,
On 3 March 2014 04:19, Heiko Schocherhs@denx.de wrote:
based on patch from andreas@oetken.name:
http://patchwork.ozlabs.org/patch/294318/ commit message: I currently need support for rsa-sha256 signatures in u-boot and found out that the code for signatures is not very generic. Thus adding of different hash-algorithms for rsa-signatures is not easy to do without copy-pasting the rsa-code. I attached a patch for how I think it could be better and included support for rsa-sha256. This is a fast first shot.
aditionally work:
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocherhs@denx.de Cc: andreas@oetken.name Cc: Simon Glasssjg@chromium.org
This looks good to me. However, when running it I hit this crash?
O=b/sandbox test/vboot/vboot_test.sh Simple Verified Boot Test =========================
Please see doc/uImage.FIT/verified-boot.txt for more information
/home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 Build keys do sha1 test 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 check signed config on the host *** buffer overflow detected ***: /home/sjg/c/src/third_party/u-boot/files/b/sandbox/tools/fit_check_sign terminated ======= Backtrace: ========= /lib/x86_64-linux-gnu/libc.so.6(__fortify_fail+0x37)[0x7f07c7ba9f47] /lib/x86_64-linux-gnu/libc.so.6(+0x109e40)[0x7f07c7ba8e40]
[...]
[vsyscall] test/vboot/vboot_test.sh: line 65: 7597 Aborted (core dumped) ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb> ${tmp}
Verified boot key check on host failed, output follows:
Do you see this? Presumably not - I can dig a bit if you like?
No, I do not see this crash ... Hmm... you reply this error to the 4/8 patch of this series, but "fit_check_sign" is introduced in the 8/8 ... did you tried with all 8 patches applied?
Just tested with current head of U-Boot and I see no error:
commit 247161b8160fc699b0a517f081220bb50bc502a8 Merge: d57d60c 96ac18c Author: Tom Rini trini@ti.com Date: Fri Mar 7 20:54:22 2014 -0500
Merge branch 'master' of git://git.denx.de/u-boot-mpc85xx
$ O=sandbox ./test/vboot/vboot_test.sh Simple Verified Boot Test =========================
Please see doc/uImage.FIT/verified-boot.txt for more information
/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000 Build keys do sha1 test 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 check signed config on the host OK Test Verified Boot Run: signed config: OK Test Verified Boot Run: signed config with bad hash: OK do sha256 test 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 check signed config on the host OK Test Verified Boot Run: signed config: OK Test Verified Boot Run: signed config with bad hash: OK
Test passed pollux:u-boot hs [temp] $
Can you try with current head again?
bye, Heiko

On Mon, Mar 03, 2014 at 12:19:26PM +0100, Heiko Schocher wrote:
based on patch from andreas@oetken.name:
http://patchwork.ozlabs.org/patch/294318/ commit message: I currently need support for rsa-sha256 signatures in u-boot and found out that the code for signatures is not very generic. Thus adding of different hash-algorithms for rsa-signatures is not easy to do without copy-pasting the rsa-code. I attached a patch for how I think it could be better and included support for rsa-sha256. This is a fast first shot.
aditionally work:
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocher hs@denx.de Cc: andreas@oetken.name Cc: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

Add support for sha256,rsa4096 signatures in u-boot.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org Cc: andreas@oetken.name
--- changes for v2: - add comment from Simon Glass: - add a commit message changes for v3: add Acked-by from Simon Glass --- common/image-sig.c | 23 ++++++++++++++++++ include/image.h | 1 + include/rsa-checksum.h | 1 + include/rsa.h | 10 ++++++++ lib/rsa/rsa-checksum.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++-- lib/rsa/rsa-verify.c | 20 +++++----------- 6 files changed, 104 insertions(+), 16 deletions(-)
diff --git a/common/image-sig.c b/common/image-sig.c index 8b6f49b..763960a 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -29,6 +29,7 @@ struct checksum_algo checksum_algos[] = { { "sha1", SHA1_SUM_LEN, + RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha1, #else @@ -39,14 +40,28 @@ struct checksum_algo checksum_algos[] = { { "sha256", SHA256_SUM_LEN, + RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, #else sha256_calculate, padding_sha256_rsa2048, #endif + }, + { + "sha256", + SHA256_SUM_LEN, + RSA4096_BYTES, +#if IMAGE_ENABLE_SIGN + EVP_sha256, +#else + sha256_calculate, + padding_sha256_rsa4096, +#endif } + }; + struct image_sig_algo image_sig_algos[] = { { "sha1,rsa2048", @@ -61,7 +76,15 @@ struct image_sig_algo image_sig_algos[] = { rsa_add_verify_data, rsa_verify, &checksum_algos[1], + }, + { + "sha256,rsa4096", + rsa_sign, + rsa_add_verify_data, + rsa_verify, + &checksum_algos[2], } + };
struct image_sig_algo *image_get_sig_algo(const char *name) diff --git a/include/image.h b/include/image.h index 44b2b46..540afaa 100644 --- a/include/image.h +++ b/include/image.h @@ -879,6 +879,7 @@ struct image_region { struct checksum_algo { const char *name; const int checksum_len; + const int pad_len; #if IMAGE_ENABLE_SIGN const EVP_MD *(*calculate)(void); #else diff --git a/include/rsa-checksum.h b/include/rsa-checksum.h index 850b253..612db85 100644 --- a/include/rsa-checksum.h +++ b/include/rsa-checksum.h @@ -12,6 +12,7 @@ #include <sha1.h> #include <sha256.h>
+extern const uint8_t padding_sha256_rsa4096[]; extern const uint8_t padding_sha256_rsa2048[]; extern const uint8_t padding_sha1_rsa2048[];
diff --git a/include/rsa.h b/include/rsa.h index e9ae870..a5680ab 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -103,4 +103,14 @@ static inline int rsa_verify(struct image_sign_info *info, } #endif
+#define RSA2048_BYTES (2048 / 8) +#define RSA4096_BYTES (4096 / 8) + +/* This is the minimum/maximum key size we support, in bits */ +#define RSA_MIN_KEY_BITS 2048 +#define RSA_MAX_KEY_BITS 4096 + +/* This is the maximum signature length that we support, in bits */ +#define RSA_MAX_SIG_BITS 4096 + #endif diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c index e520e1c..a9d096d 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/rsa/rsa-checksum.c @@ -13,8 +13,6 @@ #include <asm/errno.h> #include <asm/unaligned.h>
-#define RSA2048_BYTES 256 - /* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_SUM_LEN] = { @@ -71,6 +69,69 @@ const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = { 0x05, 0x00, 0x04, 0x14 };
+const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_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, 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, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, + 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, + 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 +}; + void sha1_calculate(const struct image_region region[], int region_count, uint8_t *checksum) { diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index b3573a8..09268ca 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -15,15 +15,6 @@
#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 - /** * subtract_modulus() - subtract modulus from the given value * @@ -197,7 +188,7 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig, return ret;
padding = algo->rsa_padding; - pad_len = RSA2048_BYTES - algo->checksum_len; + pad_len = algo->pad_len - algo->checksum_len;
/* Check pkcs1.5 padding bytes. */ if (memcmp(buf, padding, pad_len)) { @@ -281,7 +272,7 @@ int rsa_verify(struct image_sign_info *info, { const void *blob = info->fdt_blob; /* Reserve memory for maximum checksum-length */ - uint8_t hash[RSA2048_BYTES]; + uint8_t hash[info->algo->checksum->pad_len]; int ndepth, noffset; int sig_node, node; char name[100]; @@ -291,9 +282,10 @@ int rsa_verify(struct image_sign_info *info, * Verify that the checksum-length does not exceed the * rsa-signature-length */ - if (info->algo->checksum->checksum_len > RSA2048_BYTES) { - debug("%s: invlaid checksum-algorithm %s for RSA2048\n", - __func__, info->algo->checksum->name); + if (info->algo->checksum->checksum_len > + info->algo->checksum->pad_len) { + debug("%s: invlaid checksum-algorithm %s for %s\n", + __func__, info->algo->checksum->name, info->algo->name); return -EINVAL; }

On Mon, Mar 03, 2014 at 12:19:27PM +0100, Heiko Schocher wrote:
Add support for sha256,rsa4096 signatures in u-boot.
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org Cc: andreas@oetken.name
Applied to u-boot/next, thanks!

From: Hung-ying Tyan tyanh@chromium.org
Add hash_init(), hash_update() and hash_finish() to the hash_algo struct. Add hash_lookup_algo() to look up the struct given an algorithm name.
Signed-off-by: Hung-ying Tyan tyanh@chromium.org Signed-off-by: Simon Glass sjg@chromium.org Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
--- changes for v2: - new in v2 changes for v3: add Acked-by from Simon Glass --- common/hash.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++------ include/hash.h | 48 ++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 11 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 872cd85..7627b84 100644 --- a/common/hash.c +++ b/common/hash.c @@ -12,6 +12,7 @@
#include <common.h> #include <command.h> +#include <malloc.h> #include <hw_sha.h> #include <hash.h> #include <sha1.h> @@ -19,6 +20,88 @@ #include <asm/io.h> #include <asm/errno.h>
+#ifdef CONFIG_CMD_SHA1SUM +static int hash_init_sha1(struct hash_algo *algo, void **ctxp) +{ + sha1_context *ctx = malloc(sizeof(sha1_context)); + sha1_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha1(struct hash_algo *algo, void *ctx, const void *buf, + unsigned int size, int is_last) +{ + sha1_update((sha1_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha1(struct hash_algo *algo, void *ctx, void *dest_buf, + int size) +{ + if (size < algo->digest_size) + return -1; + + sha1_finish((sha1_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + +#ifdef CONFIG_SHA256 +static int hash_init_sha256(struct hash_algo *algo, void **ctxp) +{ + sha256_context *ctx = malloc(sizeof(sha256_context)); + sha256_starts(ctx); + *ctxp = ctx; + return 0; +} + +static int hash_update_sha256(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + sha256_update((sha256_context *)ctx, buf, size); + return 0; +} + +static int hash_finish_sha256(struct hash_algo *algo, void *ctx, void + *dest_buf, int size) +{ + if (size < algo->digest_size) + return -1; + + sha256_finish((sha256_context *)ctx, dest_buf); + free(ctx); + return 0; +} +#endif + +static int hash_init_crc32(struct hash_algo *algo, void **ctxp) +{ + uint32_t *ctx = malloc(sizeof(uint32_t)); + *ctx = 0; + *ctxp = ctx; + return 0; +} + +static int hash_update_crc32(struct hash_algo *algo, void *ctx, + const void *buf, unsigned int size, int is_last) +{ + *((uint32_t *)ctx) = crc32(*((uint32_t *)ctx), buf, size); + return 0; +} + +static int hash_finish_crc32(struct hash_algo *algo, void *ctx, void *dest_buf, + int size) +{ + if (size < algo->digest_size) + return -1; + + *((uint32_t *)dest_buf) = *((uint32_t *)ctx); + free(ctx); + return 0; +} + /* * These are the hash algorithms we support. Chips which support accelerated * crypto could perhaps add named version of these algorithms here. Note that @@ -53,6 +136,9 @@ static struct hash_algo hash_algo[] = { SHA1_SUM_LEN, sha1_csum_wd, CHUNKSZ_SHA1, + hash_init_sha1, + hash_update_sha1, + hash_finish_sha1, }, #define MULTI_HASH #endif @@ -62,6 +148,9 @@ static struct hash_algo hash_algo[] = { SHA256_SUM_LEN, sha256_csum_wd, CHUNKSZ_SHA256, + hash_init_sha256, + hash_update_sha256, + hash_finish_sha256, }, #define MULTI_HASH #endif @@ -70,6 +159,9 @@ static struct hash_algo hash_algo[] = { 4, crc32_wd_buf, CHUNKSZ_CRC32, + hash_init_crc32, + hash_update_crc32, + hash_finish_crc32, }, };
@@ -204,16 +296,19 @@ static int parse_verify_sum(struct hash_algo *algo, char *verify_str, u8 *vsum, return 0; }
-static struct hash_algo *find_hash_algo(const char *name) +int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) { int i;
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { - if (!strcmp(name, hash_algo[i].name)) - return &hash_algo[i]; + if (!strcmp(algo_name, hash_algo[i].name)) { + *algop = &hash_algo[i]; + return 0; + } }
- return NULL; + debug("Unknown hash algorithm '%s'\n", algo_name); + return -EPROTONOSUPPORT; }
static void show_hash(struct hash_algo *algo, ulong addr, ulong len, @@ -230,12 +325,12 @@ int hash_block(const char *algo_name, const void *data, unsigned int len, uint8_t *output, int *output_size) { struct hash_algo *algo; + int ret; + + ret = hash_lookup_algo(algo_name, &algo); + if (ret) + return ret;
- 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); @@ -265,8 +360,7 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, u8 vsum[HASH_MAX_DIGEST_SIZE]; void *buf;
- algo = find_hash_algo(algo_name); - if (!algo) { + if (hash_lookup_algo(algo_name, &algo)) { printf("Unknown hash algorithm '%s'\n", algo_name); return CMD_RET_USAGE; } diff --git a/include/hash.h b/include/hash.h index e92d272..dc21678 100644 --- a/include/hash.h +++ b/include/hash.h @@ -27,6 +27,42 @@ struct hash_algo { void (*hash_func_ws)(const unsigned char *input, unsigned int ilen, unsigned char *output, unsigned int chunk_sz); int chunk_size; /* Watchdog chunk size */ + /* + * hash_init: Create the context for progressive hashing + * + * @algo: Pointer to the hash_algo struct + * @ctxp: Pointer to the pointer of the context for hashing + * @return 0 if ok, -1 on error + */ + int (*hash_init)(struct hash_algo *algo, void **ctxp); + /* + * hash_update: Perform hashing on the given buffer + * + * The context is freed by this function if an error occurs. + * + * @algo: Pointer to the hash_algo struct + * @ctx: Pointer to the context for hashing + * @buf: Pointer to the buffer being hashed + * @size: Size of the buffer being hashed + * @is_last: 1 if this is the last update; 0 otherwise + * @return 0 if ok, -1 on error + */ + int (*hash_update)(struct hash_algo *algo, void *ctx, const void *buf, + unsigned int size, int is_last); + /* + * hash_finish: Write the hash result to the given buffer + * + * The context is freed by this function. + * + * @algo: Pointer to the hash_algo struct + * @ctx: Pointer to the context for hashing + * @dest_buf: Pointer to the buffer for the result + * @size: Size of the buffer for the result + * @return 0 if ok, -ENOSPC if size of the result buffer is too small + * or -1 on other errors + */ + int (*hash_finish)(struct hash_algo *algo, void *ctx, void *dest_buf, + int size); };
/* @@ -77,4 +113,16 @@ int hash_command(const char *algo_name, int flags, cmd_tbl_t *cmdtp, int flag, int hash_block(const char *algo_name, const void *data, unsigned int len, uint8_t *output, int *output_size);
+/** + * hash_lookup_algo() - Look up the hash_algo struct for an algorithm + * + * The function returns the pointer to the struct or -EPROTONOSUPPORT if the + * algorithm is not available. + * + * @algo_name: Hash algorithm to look up + * @algop: Pointer to the hash_algo struct if found + * + * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm. + */ +int hash_lookup_algo(const char *algo_name, struct hash_algo **algop); #endif

On Mon, Mar 03, 2014 at 12:19:28PM +0100, Heiko Schocher wrote:
From: Hung-ying Tyan tyanh@chromium.org
Add hash_init(), hash_update() and hash_finish() to the hash_algo struct. Add hash_lookup_algo() to look up the struct given an algorithm name.
Signed-off-by: Hung-ying Tyan tyanh@chromium.org Signed-off-by: Simon Glass sjg@chromium.org Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties data with linux tools, for example "dd".
Signed-off-by: Heiko Schocher hs@denx.de
--- - no changes for v2 - changes for v3: - add comment from Marek Vasut: - do not call unlink() unconditionally - set errno = 0 and check errno after mmap() call - add comment from Simon Glass: - remove get_blob, as it is not needed - use getopt - rebased against current head eeb72e67619b98d2502fe634a3a5d9953de92ad0 -> Makefile adaptions necessary introduced from kbuild changes --- tools/.gitignore | 1 + tools/Makefile | 8 +++++ tools/fit_common.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ tools/fit_common.h | 22 +++++++++++++ tools/fit_image.c | 62 +++-------------------------------- tools/fit_info.c | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 217 insertions(+), 58 deletions(-) create mode 100644 tools/fit_common.c create mode 100644 tools/fit_common.h create mode 100644 tools/fit_info.c
diff --git a/tools/.gitignore b/tools/.gitignore index 2a90dfe..2f6ecc7 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,5 +1,6 @@ /bmp_logo /envcrc +/fit_info /gen_eth_addr /img2srec /kwboot diff --git a/tools/Makefile b/tools/Makefile index c5dbc31..c54d738 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -60,6 +60,9 @@ hostprogs-y += mkenvimage$(SFX) mkenvimage$(SFX)-objs := crc32.o mkenvimage.o os_support.o
hostprogs-y += dumpimage$(SFX) mkimage$(SFX) +ifdef CONFIG_FIT_SIGNATURE +hostprogs-y += fit_info$(SFX) +endif
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := image-sig.o # Flattened device tree objects @@ -71,6 +74,8 @@ dumpimage-mkimage-objs := aisimage.o \ $(FIT_SIG_OBJS-y) \ crc32.o \ default_image.o \ + fdtdec.o \ + fit_common.o \ fit_image.o \ image-fit.o \ image-host.o \ @@ -91,6 +96,7 @@ dumpimage-mkimage-objs := aisimage.o \
dumpimage$(SFX)-objs := $(dumpimage-mkimage-objs) dumpimage.o mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o +fit_info$(SFX)-objs := $(dumpimage-mkimage-objs) fit_info.o
# TODO(sjg@chromium.org): Is this correct on Mac OS?
@@ -98,6 +104,7 @@ mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o ifneq ($(CONFIG_MX23)$(CONFIG_MX28),) HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto +HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto # Add CONFIG_MXS into host CFLAGS, so we can check whether or not register # the mxsimage support within tools/mxsimage.c . HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS @@ -106,6 +113,7 @@ endif ifdef CONFIG_FIT_SIGNATURE HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto +HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto
# This affects include/image.h, but including the board config file # is tricky, so manually define this options here. diff --git a/tools/fit_common.c b/tools/fit_common.c new file mode 100644 index 0000000..ee1767b --- /dev/null +++ b/tools/fit_common.c @@ -0,0 +1,86 @@ +/* + * (C) Copyright 2014 + * DENX Software Engineering + * Heiko Schocher hs@denx.de + * + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar prafulla@marvell.com + * FIT image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "imagetool.h" +#include "mkimage.h" +#include "fit_common.h" +#include <image.h> +#include <u-boot/crc.h> + +int fit_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params) +{ + return fdt_check_header(ptr); +} + +int fit_check_image_types(uint8_t type) +{ + if (type == IH_TYPE_FLATDT) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +int mmap_fdt(char *cmdname, const char *fname, void **blobp, + struct stat *sbuf, int useunlink) +{ + 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", + cmdname, fname, strerror(errno)); + if (useunlink) + unlink(fname); + return -1; + } + + if (fstat(fd, sbuf) < 0) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + cmdname, fname, strerror(errno)); + if (useunlink) + unlink(fname); + return -1; + } + + errno = 0; + ptr = mmap(0, sbuf->st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if ((ptr == MAP_FAILED) || (errno != 0)) { + fprintf(stderr, "%s: Can't read %s: %s\n", + cmdname, fname, strerror(errno)); + if (useunlink) + unlink(fname); + return -1; + } + + /* check if ptr has a valid blob */ + if (fdt_check_header(ptr)) { + fprintf(stderr, "%s: Invalid FIT blob\n", cmdname); + if (useunlink) + unlink(fname); + return -1; + } + + *blobp = ptr; + return fd; +} diff --git a/tools/fit_common.h b/tools/fit_common.h new file mode 100644 index 0000000..adf4404 --- /dev/null +++ b/tools/fit_common.h @@ -0,0 +1,22 @@ +/* + * (C) Copyright 2014 + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _FIT_COMMON_H_ +#define _FIT_COMMON_H_ + +#include "imagetool.h" +#include "mkimage.h" +#include <image.h> + +int fit_verify_header(unsigned char *ptr, int image_size, + struct image_tool_params *params); + +int fit_check_image_types(uint8_t type); + +int mmap_fdt(char *cmdname, const char *fname, void **blobp, + struct stat *sbuf, int useunlink); + +#endif /* _FIT_COMMON_H_ */ diff --git a/tools/fit_image.c b/tools/fit_image.c index 1466164..eeee484 100644 --- a/tools/fit_image.c +++ b/tools/fit_image.c @@ -15,68 +15,13 @@ */
#include "imagetool.h" +#include "fit_common.h" #include "mkimage.h" #include <image.h> #include <u-boot/crc.h>
static image_header_t header;
-static int fit_verify_header (unsigned char *ptr, int image_size, - struct image_tool_params *params) -{ - return fdt_check_header(ptr); -} - -static int fit_check_image_types (uint8_t type) -{ - if (type == IH_TYPE_FLATDT) - return EXIT_SUCCESS; - else - return EXIT_FAILURE; -} - -int mmap_fdt(struct image_tool_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 * @@ -129,13 +74,14 @@ static int fit_handle_file(struct image_tool_params *params) }
if (params->keydest) { - destfd = mmap_fdt(params, params->keydest, &dest_blob, &sbuf); + destfd = mmap_fdt(params->cmdname, params->keydest, + &dest_blob, &sbuf, 1); if (destfd < 0) goto err_keydest; destfd_size = sbuf.st_size; }
- tfd = mmap_fdt(params, tmpfile, &ptr, &sbuf); + tfd = mmap_fdt(params->cmdname, tmpfile, &ptr, &sbuf, 1); if (tfd < 0) goto err_mmap;
diff --git a/tools/fit_info.c b/tools/fit_info.c new file mode 100644 index 0000000..50f3c8e --- /dev/null +++ b/tools/fit_info.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2014 + * DENX Software Engineering + * Heiko Schocher hs@denx.de + * + * fit_info: print the offset and the len of a property from + * node in a fit file. + * + * Based on: + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar prafulla@marvell.com + * FIT image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "mkimage.h" +#include "fit_common.h" +#include <image.h> +#include <u-boot/crc.h> + +void usage(char *cmdname) +{ + fprintf(stderr, "Usage: %s -f fit file -n node -p property\n" + " -f ==> set fit file which is used'\n" + " -n ==> set node name'\n" + " -p ==> set property name'\n", + cmdname); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + int ffd = -1; + struct stat fsbuf; + void *fit_blob; + int len; + int nodeoffset; /* node offset from libfdt */ + const void *nodep; /* property node pointer */ + char *fdtfile = NULL; + char *nodename = NULL; + char *propertyname = NULL; + char cmdname[50]; + int c; + + strcpy(cmdname, *argv); + while ((c = getopt(argc, argv, "f:n:p:")) != -1) + switch (c) { + case 'f': + fdtfile = optarg; + break; + case 'n': + nodename = optarg; + break; + case 'p': + propertyname = optarg; + break; + default: + usage(cmdname); + break; + } + + ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, 0); + + if (ffd < 0) { + printf("Could not open %s\n", fdtfile); + exit(EXIT_FAILURE); + } + + nodeoffset = fdt_path_offset(fit_blob, nodename); + if (nodeoffset < 0) { + printf("%s not found.", nodename); + exit(EXIT_FAILURE); + } + nodep = fdt_getprop(fit_blob, nodeoffset, propertyname, &len); + if (len == 0) { + printf("len == 0 %s\n", propertyname); + exit(EXIT_FAILURE); + } + + printf("NAME: %s\n", fit_get_name(fit_blob, nodeoffset, NULL)); + printf("LEN: %d\n", len); + printf("OFF: %d\n", (int)(nodep - fit_blob)); + (void) munmap((void *)fit_blob, fsbuf.st_size); + + close(ffd); + exit(EXIT_SUCCESS); +}

Hi Heiko,
On 3 March 2014 04:19, Heiko Schocher hs@denx.de wrote:
add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties
property's I think?
data with linux tools, for example "dd".
Signed-off-by: Heiko Schocher hs@denx.de
Acked-by: Simon Glass sjg@chromium.org
Seems OK to me. Note that there is an fdtget utility available which can sort-of do this - it is part of the dtc package. However I don't think it has an option to extract data in binary form (the -ts option may work but I'm not sure).
I don't understand the mmap() errno thing that Marek mentions, but it can do no harm.
Regards, Simon

On Mon, Mar 03, 2014 at 12:19:29PM +0100, Heiko Schocher wrote:
add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties data with linux tools, for example "dd".
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!

add host tool "fit_check_sign" which verifies, if a fit image is signed correct.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
--- - changes for v2: - fixed compile error for sandbox - add fit_check_sign test to test/vboot/vboot_test.sh
- changes for v3: - add comment from Marek Vasut: - do not use unlink - add comment from Simon Glass: - get_blob not weak, rename it to image_get_host_blob() - use getopt - as we not write the file, get rid of some unneccessary checks - move fdtdec_get_int() from lib/libfdt/fdt_wip.c to lib/fdtdec.c for HOSTCC compiles - rebased against current head eeb72e67619b98d2502fe634a3a5d9953de92ad0 -> Makefile adaptions necessary introduced from kbuild changes --- common/image-sig.c | 18 +++++----- doc/uImage.FIT/signature.txt | 6 ++++ include/fdt_support.h | 5 +++ include/image.h | 17 +++++---- lib/fdtdec.c | 20 +++++++++++ lib/rsa/rsa-checksum.c | 10 ++++-- lib/rsa/rsa-sign.c | 2 +- lib/rsa/rsa-verify.c | 18 +++++++--- test/vboot/vboot_test.sh | 20 +++++++++++ tools/.gitignore | 1 + tools/Makefile | 7 ++-- tools/fdt_host.h | 2 ++ tools/fdtdec.c | 1 + tools/fit_check_sign.c | 85 ++++++++++++++++++++++++++++++++++++++++++++ tools/image-host.c | 15 ++++++++ tools/rsa-checksum.c | 1 + tools/rsa-verify.c | 1 + 17 files changed, 204 insertions(+), 25 deletions(-) create mode 100644 tools/fdtdec.c create mode 100644 tools/fit_check_sign.c create mode 100644 tools/rsa-checksum.c create mode 100644 tools/rsa-verify.c
diff --git a/common/image-sig.c b/common/image-sig.c index 763960a..72284eb 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -19,9 +19,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMAGE_MAX_HASHED_NODES 100
#ifdef USE_HOSTCC -__attribute__((weak)) void *get_blob(void) +void *host_blob; +void image_set_host_blob(void *blob) { - return NULL; + host_blob = blob; +} +void *image_get_host_blob(void) +{ + return host_blob; } #endif
@@ -32,10 +37,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha1, -#else +#endif sha1_calculate, padding_sha1_rsa2048, -#endif }, { "sha256", @@ -43,10 +47,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa2048, -#endif }, { "sha256", @@ -54,10 +57,9 @@ struct checksum_algo checksum_algos[] = { RSA4096_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa4096, -#endif }
}; diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index 71f8b6c..9502037 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -357,6 +357,9 @@ Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images Test Verified Boot Run: signed config: OK +check signed config on the host +OK +Test Verified Boot Run: signed config: OK Test Verified Boot Run: signed config with bad hash: OK do sha256 test Build FIT with signed images @@ -367,6 +370,9 @@ Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images Test Verified Boot Run: signed config: OK +check signed config on the host +OK +Test Verified Boot Run: signed config: OK Test Verified Boot Run: signed config with bad hash: OK
Test passed diff --git a/include/fdt_support.h b/include/fdt_support.h index 9871e2f..76c9b2e 100644 --- a/include/fdt_support.h +++ b/include/fdt_support.h @@ -115,4 +115,9 @@ static inline int fdt_status_disabled_by_alias(void *fdt, const char* alias) }
#endif /* ifdef CONFIG_OF_LIBFDT */ + +#ifdef USE_HOSTCC +int fdtdec_get_int(const void *blob, int node, const char *prop_name, + int default_val); +#endif #endif /* ifndef __FDT_SUPPORT_H */ diff --git a/include/image.h b/include/image.h index 540afaa..2508d7d 100644 --- a/include/image.h +++ b/include/image.h @@ -832,7 +832,7 @@ int calculate_hash(const void *data, int data_len, const char *algo, #if defined(CONFIG_FIT_SIGNATURE) # ifdef USE_HOSTCC # define IMAGE_ENABLE_SIGN 1 -# define IMAGE_ENABLE_VERIFY 0 +# define IMAGE_ENABLE_VERIFY 1 # include <openssl/evp.h> #else # define IMAGE_ENABLE_SIGN 0 @@ -844,7 +844,9 @@ int calculate_hash(const void *data, int data_len, const char *algo, #endif
#ifdef USE_HOSTCC -# define gd_fdt_blob() NULL +void *image_get_host_blob(void); +void image_set_host_blob(void *host_blob); +# define gd_fdt_blob() image_get_host_blob() #else # define gd_fdt_blob() (gd->fdt_blob) #endif @@ -881,14 +883,11 @@ struct checksum_algo { const int checksum_len; const int pad_len; #if IMAGE_ENABLE_SIGN - const EVP_MD *(*calculate)(void); -#else -#if IMAGE_ENABLE_VERIFY + const EVP_MD *(*calculate_sign)(void); +#endif void (*calculate)(const struct image_region region[], int region_count, uint8_t *checksum); const uint8_t *rsa_padding; -#endif -#endif };
struct image_sig_algo { @@ -1009,7 +1008,11 @@ struct image_region *fit_region_make_list(const void *fit,
static inline int fit_image_check_target_arch(const void *fdt, int node) { +#ifndef USE_HOSTCC return fit_image_check_arch(fdt, node, IH_ARCH_DEFAULT); +#else + return 0; +#endif }
#ifdef CONFIG_FIT_VERBOSE diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 1fecab3..42b74bc 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -3,6 +3,7 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#ifndef USE_HOSTCC #include <common.h> #include <serial.h> #include <libfdt.h> @@ -617,3 +618,22 @@ int fdtdec_decode_region(const void *blob, int node, debug("%s: size=%zx\n", __func__, *size); return 0; } +#else +#include "libfdt.h" +#include "fdt_support.h" + +int fdtdec_get_int(const void *blob, int node, const char *prop_name, + int default_val) +{ + const int *cell; + int len; + + cell = fdt_getprop_w((void *)blob, node, prop_name, &len); + if (cell && len >= sizeof(int)) { + int val = fdt32_to_cpu(cell[0]); + + return val; + } + return default_val; +} +#endif diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c index a9d096d..32d6602 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/rsa/rsa-checksum.c @@ -4,14 +4,18 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> -#include <rsa.h> -#include <sha1.h> -#include <sha256.h> #include <asm/byteorder.h> #include <asm/errno.h> #include <asm/unaligned.h> +#else +#include "fdt_host.h" +#endif +#include <rsa.h> +#include <sha1.h> +#include <sha256.h>
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 0fe6e9f..ca8c120 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -193,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo, goto err_create; } EVP_MD_CTX_init(context); - if (!EVP_SignInit(context, checksum_algo->calculate())) { + if (!EVP_SignInit(context, checksum_algo->calculate_sign())) { ret = rsa_err("Signer setup failed"); goto err_sign; } diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 09268ca..587da5b 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -4,17 +4,28 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> -#include <rsa.h> -#include <sha1.h> -#include <sha256.h> +#include <asm/types.h> #include <asm/byteorder.h> #include <asm/errno.h> +#include <asm/types.h> #include <asm/unaligned.h> +#else +#include "fdt_host.h" +#include "mkimage.h" +#include <fdt_support.h> +#endif +#include <rsa.h> +#include <sha1.h> +#include <sha256.h>
#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby)))
+#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a) +#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a)) + /** * subtract_modulus() - subtract modulus from the given value * @@ -150,7 +161,6 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) /* 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; }
diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh index 3e2856e..3c6efa7 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -47,6 +47,7 @@ O=$(readlink -f ${O}) dtc="-I dts -O dtb -p 2000" uboot="${O}/u-boot" mkimage="${O}/tools/mkimage" +fit_check_sign="${O}/tools/fit_check_sign" keys="${dir}/dev-keys" echo ${mkimage} -D "${dtc}"
@@ -99,6 +100,25 @@ function do_test {
run_uboot "signed config" "dev+"
+ echo check signed config on the host + if ! ${fit_check_sign} -f test.fit -k sandbox-u-boot.dtb >${tmp}; then + echo + echo "Verified boot key check on host failed, output follows:" + cat ${tmp} + false + else + if ! grep -q "dev+" ${tmp}; then + echo + echo "Verified boot key check failed, output follows:" + cat ${tmp} + false + else + echo "OK" + fi + fi + + run_uboot "signed config" "dev+" + # Increment the first byte of the signature, which should cause failure sig=$(fdtget -t bx test.fit /configurations/conf@1/signature@1 value) newbyte=$(printf %x $((0x${sig:0:2} + 1))) diff --git a/tools/.gitignore b/tools/.gitignore index 2f6ecc7..b1e997f 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -1,5 +1,6 @@ /bmp_logo /envcrc +/fit_check_sign /fit_info /gen_eth_addr /img2srec diff --git a/tools/Makefile b/tools/Makefile index c54d738..8d25ecc 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -61,13 +61,13 @@ mkenvimage$(SFX)-objs := crc32.o mkenvimage.o os_support.o
hostprogs-y += dumpimage$(SFX) mkimage$(SFX) ifdef CONFIG_FIT_SIGNATURE -hostprogs-y += fit_info$(SFX) +hostprogs-y += fit_info$(SFX) fit_check_sign$(SFX) endif
FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := image-sig.o # Flattened device tree objects LIBFDT_OBJS := fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o -RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o +RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := rsa-sign.o rsa-verify.o rsa-checksum.o
# common objs for dumpimage and mkimage dumpimage-mkimage-objs := aisimage.o \ @@ -97,6 +97,7 @@ dumpimage-mkimage-objs := aisimage.o \ dumpimage$(SFX)-objs := $(dumpimage-mkimage-objs) dumpimage.o mkimage$(SFX)-objs := $(dumpimage-mkimage-objs) mkimage.o fit_info$(SFX)-objs := $(dumpimage-mkimage-objs) fit_info.o +fit_check_sign$(SFX)-objs := $(dumpimage-mkimage-objs) fit_check_sign.o
# TODO(sjg@chromium.org): Is this correct on Mac OS?
@@ -105,6 +106,7 @@ ifneq ($(CONFIG_MX23)$(CONFIG_MX28),) HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto +HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto # Add CONFIG_MXS into host CFLAGS, so we can check whether or not register # the mxsimage support within tools/mxsimage.c . HOSTCFLAGS_mxsimage.o += -DCONFIG_MXS @@ -114,6 +116,7 @@ ifdef CONFIG_FIT_SIGNATURE HOSTLOADLIBES_dumpimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_mkimage$(SFX) := -lssl -lcrypto HOSTLOADLIBES_fit_info$(SFX) := -lssl -lcrypto +HOSTLOADLIBES_fit_check_sign$(SFX) := -lssl -lcrypto
# This affects include/image.h, but including the board config file # is tricky, so manually define this options here. diff --git a/tools/fdt_host.h b/tools/fdt_host.h index c2b23c6..134d965 100644 --- a/tools/fdt_host.h +++ b/tools/fdt_host.h @@ -11,4 +11,6 @@ #include "../include/libfdt.h" #include "../include/fdt_support.h"
+int fit_check_sign(const void *working_fdt, const void *key); + #endif /* __FDT_HOST_H__ */ diff --git a/tools/fdtdec.c b/tools/fdtdec.c new file mode 100644 index 0000000..f1c2256 --- /dev/null +++ b/tools/fdtdec.c @@ -0,0 +1 @@ +#include "../lib/fdtdec.c" diff --git a/tools/fit_check_sign.c b/tools/fit_check_sign.c new file mode 100644 index 0000000..d6d9340 --- /dev/null +++ b/tools/fit_check_sign.c @@ -0,0 +1,85 @@ +/* + * (C) Copyright 2014 + * DENX Software Engineering + * Heiko Schocher hs@denx.de + * + * Based on: + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar prafulla@marvell.com + * FIT image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include "mkimage.h" +#include "fit_common.h" +#include <image.h> +#include <u-boot/crc.h> + +void usage(char *cmdname) +{ + fprintf(stderr, "Usage: %s -f fit file -k key file\n" + " -f ==> set fit file which should be checked'\n" + " -k ==> set key file which contains the key'\n", + cmdname); + exit(EXIT_FAILURE); +} + +int main(int argc, char **argv) +{ + int ffd = -1; + int kfd = -1; + struct stat fsbuf; + struct stat ksbuf; + void *fit_blob; + char *fdtfile = NULL; + char *keyfile = NULL; + char cmdname[50]; + int ret; + void *key_blob; + int c; + + strcpy(cmdname, *argv); + while ((c = getopt(argc, argv, "f:k:")) != -1) + switch (c) { + case 'f': + fdtfile = optarg; + break; + case 'k': + keyfile = optarg; + break; + default: + usage(cmdname); + break; + } + + ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf, 0); + if (ffd < 0) + return EXIT_FAILURE; + kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf, 0); + if (ffd < 0) + return EXIT_FAILURE; + + image_set_host_blob(key_blob); + ret = fit_check_sign(fit_blob, key_blob); + + if (ret) + ret = EXIT_SUCCESS; + else + ret = EXIT_FAILURE; + + (void) munmap((void *)fit_blob, fsbuf.st_size); + (void) munmap((void *)key_blob, ksbuf.st_size); + + close(ffd); + close(kfd); + exit(ret); +} diff --git a/tools/image-host.c b/tools/image-host.c index 8e185ec..651f1c2 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -695,3 +695,18 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
return 0; } + +#ifdef CONFIG_FIT_SIGNATURE +int fit_check_sign(const void *working_fdt, const void *key) +{ + int cfg_noffset; + int ret; + + cfg_noffset = fit_conf_get_node(working_fdt, NULL); + if (!cfg_noffset) + return -1; + + ret = fit_config_verify(working_fdt, cfg_noffset); + return ret; +} +#endif diff --git a/tools/rsa-checksum.c b/tools/rsa-checksum.c new file mode 100644 index 0000000..09033e6 --- /dev/null +++ b/tools/rsa-checksum.c @@ -0,0 +1 @@ +#include "../lib/rsa/rsa-checksum.c" diff --git a/tools/rsa-verify.c b/tools/rsa-verify.c new file mode 100644 index 0000000..bb662a1 --- /dev/null +++ b/tools/rsa-verify.c @@ -0,0 +1 @@ +#include "../lib/rsa/rsa-verify.c"

+Charles for HOSTCC comments
Hi Heiko,
On 3 March 2014 04:19, Heiko Schocher hs@denx.de wrote:
add host tool "fit_check_sign" which verifies, if a fit image is signed correct.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
Looks good - a few nits and the crash I mentioned.
It's interesting that the host and target environments are so different - much of it is unavoidable but your patch is a good example of what is needed when we 'bridge the gap.
Regards, Simon

On Mon, Mar 03, 2014 at 12:19:30PM +0100, Heiko Schocher wrote:
add host tool "fit_check_sign" which verifies, if a fit image is signed correct.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
Applied to u-boot/next, thanks!
participants (3)
-
Heiko Schocher
-
Simon Glass
-
Tom Rini