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

- add sha256,rsa2048 and sha256,rsa4098 support to u-boot. - add "fdt sign" 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@chromium.org as Simon Glass mentioned
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
Makefile | 2 + common/cmd_fdt.c | 42 +++++- common/hash.c | 116 +++++++++++++-- common/image-fit.c | 5 + common/image-sig.c | 66 +++++++++ doc/uImage.FIT/signature.txt | 33 ++++- include/fdt_support.h | 5 + include/hash.h | 48 ++++++ include/image.h | 37 ++++- include/rsa-checksum.h | 26 ++++ include/rsa.h | 24 +++ lib/libfdt/fdt_wip.c | 17 +++ 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 | 2 +- .../{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 | 54 ++++++- tools/Makefile | 42 +++++- tools/fdt_host.h | 2 + tools/fit_check_sign.c | 119 +++++++++++++++ tools/fit_common.c | 81 ++++++++++ tools/fit_common.h | 22 +++ tools/fit_image.c | 62 +------- tools/fit_info.c | 116 +++++++++++++++ tools/image-host.c | 15 +- 30 files changed, 1148 insertions(+), 157 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/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
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;

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 Cc: 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
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 8 February 2014 22:34, Heiko Schocher hs@denx.de 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 Cc: Simon Glass sjg@chromium.org
Acked-by: Simon Glass sjg@chromium.org

Hi Heiko,
On 8 February 2014 22:34, Heiko Schocher hs@denx.de 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 Cc: 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
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) {
Sorry, I missed this earlier - I think this should be "che" if the command is checksig.
Regards, Simon

Hi Heiko,
On 15 February 2014 16:00, Simon Glass sjg@chromium.org wrote:
Hi Heiko,
On 8 February 2014 22:34, Heiko Schocher hs@denx.de 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 Cc: 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
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) {
Sorry, I missed this earlier - I think this should be "che" if the command is checksig.
Hmm, ignore this, I was looking in the wrong place.
Regards, Simon

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
common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 2 +- tools/Makefile | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/common/image-fit.c b/common/image-fit.c index cf4b67e..f32feb6 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 7de2bb2..f001a5f 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..5766de2 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -258,7 +258,7 @@ 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, *curr; int chunk; #endif
diff --git a/tools/Makefile b/tools/Makefile index 328cea3..5e36e5e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -71,6 +71,7 @@ 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 +EXT_OBJ_FILES-y += lib/sha256.o
# Source files located in the tools directory NOPED_OBJ_FILES-y += aisimage.o @@ -223,6 +224,7 @@ $(obj)dumpimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \ + $(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS) @@ -252,6 +254,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \ + $(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS)

Hi Heiko,
On 8 February 2014 22:34, Heiko Schocher hs@denx.de wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocher hs@denx.de Acked-by: Simon Glass sjg@chromium.org
Sorry I spotted a few things since.
changes for v2:
- add Acked-by from Simon Glass
common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 2 +- tools/Makefile | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-)
diff --git a/common/image-fit.c b/common/image-fit.c index cf4b67e..f32feb6 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 7de2bb2..f001a5f 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 */
Thinking about this again, I wonder if we want to force SHA256 to be enabled when FIT is used? Should we just hold the existing CONFIG_SHA256 setting in the board file and change:
# define IMAGE_ENABLE_CRC32 1 # define IMAGE_ENABLE_MD5 1 # define IMAGE_ENABLE_SHA1 1 +# define IMAGE_ENABLE_SHA256 1
this to:
#ifdef CONFIG_SHA256 +# define IMAGE_ENABLE_SHA256 0 #endif
?
# 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..5766de2 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -258,7 +258,7 @@ 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, *curr;
Why remove the const here?
int chunk;
#endif
diff --git a/tools/Makefile b/tools/Makefile index 328cea3..5e36e5e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -71,6 +71,7 @@ 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 +EXT_OBJ_FILES-y += lib/sha256.o
# Source files located in the tools directory NOPED_OBJ_FILES-y += aisimage.o @@ -223,6 +224,7 @@ $(obj)dumpimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \
$(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS)
@@ -252,6 +254,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \
$(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS)
-- 1.8.3.1
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Regards, Simon

Hello Simon,
Am 15.02.2014 23:47, schrieb Simon Glass:
Hi Heiko,
On 8 February 2014 22:34, Heiko Schocherhs@denx.de wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocherhs@denx.de Acked-by: Simon Glasssjg@chromium.org
Sorry I spotted a few things since.
No problem! Thanks for your review.
changes for v2:
add Acked-by from Simon Glass
common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 2 +- tools/Makefile | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-)
[...]
diff --git a/include/image.h b/include/image.h index 7de2bb2..f001a5f 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 */
Thinking about this again, I wonder if we want to force SHA256 to be enabled when FIT is used? Should we just hold the existing CONFIG_SHA256 setting in the board file and change:
I can do this, but why are the others fix?
# define IMAGE_ENABLE_CRC32 1 # define IMAGE_ENABLE_MD5 1 # define IMAGE_ENABLE_SHA1 1 +# define IMAGE_ENABLE_SHA256 1
this to:
#ifdef CONFIG_SHA256 +# define IMAGE_ENABLE_SHA256 0 #endif
?
Ok, changed, into:
#ifdef CONFIG_SHA256 # define IMAGE_ENABLE_SHA256 1 #endif
# 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..5766de2 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -258,7 +258,7 @@ 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, *curr;
Why remove the const here?
I add const here ... I remve the "const" for the "curr" pointer.
int chunk;
#endif
diff --git a/tools/Makefile b/tools/Makefile index 328cea3..5e36e5e 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -71,6 +71,7 @@ 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 +EXT_OBJ_FILES-y += lib/sha256.o
# Source files located in the tools directory NOPED_OBJ_FILES-y += aisimage.o @@ -223,6 +224,7 @@ $(obj)dumpimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \
$(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS)
@@ -252,6 +254,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(obj)os_support.o \ $(obj)pblimage.o \ $(obj)sha1.o \
$(obj)sha256.o \ $(obj)ublimage.o \ $(LIBFDT_OBJS) \ $(RSA_OBJS)
-- 1.8.3.1
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Regards, Simon
bye, Heiko

Hello Simon,
I was a little to fast with my answer ...
Am 17.02.2014 07:33, schrieb Heiko Schocher:
Hello Simon,
Am 15.02.2014 23:47, schrieb Simon Glass:
Hi Heiko,
On 8 February 2014 22:34, Heiko Schocherhs@denx.de wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocherhs@denx.de Acked-by: Simon Glasssjg@chromium.org
Sorry I spotted a few things since.
No problem! Thanks for your review.
changes for v2:
- add Acked-by from Simon Glass
common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 2 +- tools/Makefile | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-)
[...]
diff --git a/include/image.h b/include/image.h index 7de2bb2..f001a5f 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 */
Thinking about this again, I wonder if we want to force SHA256 to be enabled when FIT is used? Should we just hold the existing CONFIG_SHA256 setting in the board file and change:
I can do this, but why are the others fix?
Hmm.. if I do this, mkimage does not work, as missing this "IMAGE_ENABLE_SHA256" define ... I get the following error message:
"Unsupported hash algorithm (sha256) for 'hash@1' hash node in 'U-BOOT@1' image node tools/mkimage Can't add hashes to FIT blob"
I think, when compiling mkimage for the host, we have no board config header availiable, as mkimage is not compiled (and not intent to be) board specific ...
Seems that this is the reason, why the other algorithms are also always enabled ...
bye, Heiko

Hi Heiko,
On 16 February 2014 23:49, Heiko Schocher hs@denx.de wrote:
Hello Simon,
I was a little to fast with my answer ...
Am 17.02.2014 07:33, schrieb Heiko Schocher:
Hello Simon,
Am 15.02.2014 23:47, schrieb Simon Glass:
Hi Heiko,
On 8 February 2014 22:34, Heiko Schocherhs@denx.de wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocherhs@denx.de Acked-by: Simon Glasssjg@chromium.org
Sorry I spotted a few things since.
No problem! Thanks for your review.
changes for v2:
- add Acked-by from Simon Glass
common/image-fit.c | 5 +++++ include/image.h | 9 +++++++++ lib/sha256.c | 2 +- tools/Makefile | 3 +++ 4 files changed, 18 insertions(+), 1 deletion(-)
[...]
diff --git a/include/image.h b/include/image.h index 7de2bb2..f001a5f 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 */
Thinking about this again, I wonder if we want to force SHA256 to be enabled when FIT is used? Should we just hold the existing CONFIG_SHA256 setting in the board file and change:
I can do this, but why are the others fix?
Hmm.. if I do this, mkimage does not work, as missing this "IMAGE_ENABLE_SHA256" define ... I get the following error message:
"Unsupported hash algorithm (sha256) for 'hash@1' hash node in 'U-BOOT@1' image node tools/mkimage Can't add hashes to FIT blob"
I think, when compiling mkimage for the host, we have no board config header availiable, as mkimage is not compiled (and not intent to be) board specific ...
Seems that this is the reason, why the other algorithms are also always enabled ...
Ah yes, I remember this problem - I wanted mkimage to support everything rather than be dependent on what particular board you build with. In the end I dropped the signing part from this idea.
So yes your code is correct and I'm sorry for the trouble.
Regards, Simon

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
common/image-sig.c | 33 ++++++++ doc/uImage.FIT/signature.txt | 25 +++++- include/image.h | 21 +++++ include/rsa-checksum.h | 25 ++++++ 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 | 18 ++-- 14 files changed, 346 insertions(+), 70 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..8b212a7 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -14,15 +14,47 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <image.h> #include <rsa.h> +#include <rsa-checksum.h>
#define IMAGE_MAX_HASHED_NODES 100
+#if defined(CONFIG_FIT_SIGNATURE) +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], } };
@@ -407,3 +439,4 @@ int fit_config_verify(const void *fit, int conf_noffset) return !fit_config_verify_required_sigs(fit, conf_noffset, gd_fdt_blob()); } +#endif diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index bc9f3fa..5bd229f 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -346,6 +346,7 @@ 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 Build FIT with signed images Test Verified Boot Run: unsigned signatures:: OK @@ -355,9 +356,31 @@ 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 +Test sha1 passed
+Or for testing sha256: + +$ O=sandbox ./test/vboot/vboot_test.sh sha256 +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 +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 sha256 passed
Future Work ----------- diff --git a/include/image.h b/include/image.h index f001a5f..eb3429f 100644 --- a/include/image.h +++ b/include/image.h @@ -832,6 +832,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 @@ -871,6 +872,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 */
@@ -921,6 +939,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..12494a6 --- /dev/null +++ b/include/rsa-checksum.h @@ -0,0 +1,25 @@ +/* + * 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> + +#if IMAGE_ENABLE_VERIFY +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 + +#endif diff --git a/include/rsa.h b/include/rsa.h index add4c78..0367671 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; /* 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 */ +}; + #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..27b221a 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -6,6 +6,14 @@ # # SPDX-License-Identifier: GPL-2.0+
+# Args: +# $1: sha256 or sha1 (default) +if [ -z "$1" ]; then + sha=sha1 +else + sha=$1 +fi + set -e
# Run U-Boot and report the result @@ -70,7 +78,7 @@ 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} +${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
run_uboot "unsigned signatures:" "dev-"
@@ -85,9 +93,9 @@ run_uboot "signed images" "dev+" 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} +${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 @@ -107,7 +115,7 @@ popd >/dev/null
echo if ${ok}; then - echo "Test passed" + echo "Test $sha passed" else - echo "Test failed" + echo "Test $sha failed" fi

Hi Heiko,
On 8 February 2014 22:34, 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
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
common/image-sig.c | 33 ++++++++ doc/uImage.FIT/signature.txt | 25 +++++- include/image.h | 21 +++++ include/rsa-checksum.h | 25 ++++++ 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 | 18 ++-- 14 files changed, 346 insertions(+), 70 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..8b212a7 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -14,15 +14,47 @@ DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/ #include <image.h> #include <rsa.h> +#include <rsa-checksum.h>
#define IMAGE_MAX_HASHED_NODES 100
+#if defined(CONFIG_FIT_SIGNATURE)
This is already in the Makefile for image-sig.c
+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], }
};
@@ -407,3 +439,4 @@ int fit_config_verify(const void *fit, int conf_noffset) return !fit_config_verify_required_sigs(fit, conf_noffset, gd_fdt_blob()); } +#endif diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index bc9f3fa..5bd229f 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -346,6 +346,7 @@ 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 Build FIT with signed images Test Verified Boot Run: unsigned signatures:: OK @@ -355,9 +356,31 @@ 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 +Test sha1 passed
+Or for testing sha256:
+$ O=sandbox ./test/vboot/vboot_test.sh sha256 +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 +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 sha256 passed
Future Work
diff --git a/include/image.h b/include/image.h index f001a5f..eb3429f 100644 --- a/include/image.h +++ b/include/image.h @@ -832,6 +832,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 @@ -871,6 +872,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 */
@@ -921,6 +939,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..12494a6 --- /dev/null +++ b/include/rsa-checksum.h @@ -0,0 +1,25 @@ +/*
- 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>
+#if IMAGE_ENABLE_VERIFY
I don't think we need this in a header file.
+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
+#endif diff --git a/include/rsa.h b/include/rsa.h index add4c78..0367671 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; /* 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 */
Nice to left-align the comments?
+};
#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..27b221a 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -6,6 +6,14 @@ # # SPDX-License-Identifier: GPL-2.0+
+# Args: +# $1: sha256 or sha1 (default) +if [ -z "$1" ]; then
sha=sha1
+else
sha=$1
+fi
The test looks good, but can we please do both sha1 and sha256? It is supposed to be an automated test so running it twice or with arguments is not very friendly.
set -e
# Run U-Boot and report the result @@ -70,7 +78,7 @@ 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} +${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
run_uboot "unsigned signatures:" "dev-"
@@ -85,9 +93,9 @@ run_uboot "signed images" "dev+" 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} +${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 @@ -107,7 +115,7 @@ popd >/dev/null
echo if ${ok}; then
echo "Test passed"
echo "Test $sha passed"
else
echo "Test failed"
echo "Test $sha failed"
fi
1.8.3.1
Regards, Simon

Add support for sha256,rsa4096 signatures in u-boot.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org Cc: andreas@oetken.name
--- changes for v2: - add comment from Simon Glass: - add a commit message
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 8b212a7..199e634 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -23,6 +23,7 @@ struct checksum_algo checksum_algos[] = { { "sha1", SHA1_SUM_LEN, + RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha1, #else @@ -33,14 +34,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", @@ -55,7 +70,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 eb3429f..6e4745a 100644 --- a/include/image.h +++ b/include/image.h @@ -878,6 +878,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 12494a6..a7b553c 100644 --- a/include/rsa-checksum.h +++ b/include/rsa-checksum.h @@ -13,6 +13,7 @@ #include <sha256.h>
#if IMAGE_ENABLE_VERIFY +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 0367671..a388233 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 8 February 2014 22:34, Heiko Schocher hs@denx.de wrote:
Add support for sha256,rsa4096 signatures in u-boot.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org Cc: andreas@oetken.name
Acked-by: Simon Glass sjg@chromium.org

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
--- changes for v2: - new in v2
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

Hi Heiko,
On 8 February 2014 22:34, Heiko Schocher hs@denx.de 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
I think this is crying out for another patch - an integration to get rid of lib/rsa/rsa-checksum.c. You should be able to look up the hash algorithm name using the hash.h file and get the pad length, etc. from that. Then you can call this progressive hashing API instead of adding new code in lib/rsa/rsa-checksum.c.
There may be a catch, but I can't see one at present.
Regards, Simon

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
Makefile | 1 + tools/Makefile | 20 +++++++++ tools/fit_common.c | 81 +++++++++++++++++++++++++++++++++++++ tools/fit_common.h | 22 ++++++++++ tools/fit_image.c | 62 ++-------------------------- tools/fit_info.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 244 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/Makefile b/Makefile index 47a03e3..a2e424d 100644 --- a/Makefile +++ b/Makefile @@ -794,6 +794,7 @@ clean: @rm -f $(obj)tools/bmp_logo $(obj)tools/easylogo/easylogo \ $(obj)tools/env/fw_printenv \ $(obj)tools/envcrc \ + $(obj)tools/fit_info \ $(obj)tools/gdb/{gdbcont,gdbsend} \ $(obj)tools/gen_eth_addr $(obj)tools/img2srec \ $(obj)tools/dump{env,}image \ diff --git a/tools/Makefile b/tools/Makefile index 5e36e5e..d079bc9 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -53,6 +53,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += dumpimage$(SFX) BIN_FILES-y += mkenvimage$(SFX) BIN_FILES-y += mkimage$(SFX) +BIN_FILES-y += fit_info$(SFX) BIN_FILES-$(CONFIG_EXYNOS5250) += mk$(BOARD)spl$(SFX) BIN_FILES-$(CONFIG_EXYNOS5420) += mk$(BOARD)spl$(SFX) BIN_FILES-$(CONFIG_MX23) += mxsboot$(SFX) @@ -77,6 +78,7 @@ EXT_OBJ_FILES-y += lib/sha256.o NOPED_OBJ_FILES-y += aisimage.o NOPED_OBJ_FILES-y += default_image.o NOPED_OBJ_FILES-y += dumpimage.o +NOPED_OBJ_FILES-y += fit_common.o NOPED_OBJ_FILES-y += fit_image.o NOPED_OBJ_FILES-y += image-host.o NOPED_OBJ_FILES-y += imximage.o @@ -84,6 +86,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += imagetool.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o +NOPED_OBJ_FILES-y += fit_info.o NOPED_OBJ_FILES-y += mxsimage.o NOPED_OBJ_FILES-y += omapimage.o NOPED_OBJ_FILES-y += os_support.o @@ -210,6 +213,7 @@ $(obj)dumpimage$(SFX): $(obj)aisimage.o \ $(FIT_SIG_OBJS) \ $(obj)crc32.o \ $(obj)default_image.o \ + $(obj)fit_common.o \ $(obj)fit_image.o \ $(obj)image-fit.o \ $(obj)image.o \ @@ -240,6 +244,7 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(FIT_SIG_OBJS) \ $(obj)crc32.o \ $(obj)default_image.o \ + $(obj)fit_common.o \ $(obj)fit_image.o \ $(obj)image-fit.o \ $(obj)image-host.o \ @@ -261,6 +266,21 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) $(HOSTSTRIP) $@
+$(obj)fit_info$(SFX): $(obj)fit_info.o \ + $(FIT_SIG_OBJS) \ + $(obj)crc32.o \ + $(obj)fit_common.o \ + $(obj)image-fit.o \ + $(obj)image-host.o \ + $(obj)image.o \ + $(obj)md5.o \ + $(obj)sha1.o \ + $(obj)sha256.o \ + $(LIBFDT_OBJS) \ + $(RSA_OBJS) + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) + $(HOSTSTRIP) $@ + $(obj)mk$(BOARD)spl$(SFX): $(obj)mkexynosspl.o $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ diff --git a/tools/fit_common.c b/tools/fit_common.c new file mode 100644 index 0000000..26b6c8d --- /dev/null +++ b/tools/fit_common.c @@ -0,0 +1,81 @@ +/* + * (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) +{ + 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)); + unlink(fname); + return -1; + } + + if (fstat(fd, sbuf) < 0) { + fprintf(stderr, "%s: Can't stat %s: %s\n", + 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", + 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", cmdname); + 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..e745f10 --- /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); + +#endif /* _FIT_COMMON_H_ */ diff --git a/tools/fit_image.c b/tools/fit_image.c index 1466164..d4430bc 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); 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); if (tfd < 0) goto err_mmap;
diff --git a/tools/fit_info.c b/tools/fit_info.c new file mode 100644 index 0000000..4c5a1a1 --- /dev/null +++ b/tools/fit_info.c @@ -0,0 +1,116 @@ +/* + * (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 [<node> <property>]\n" + " -f ==> set fit file which is used'\n", + cmdname); + exit(EXIT_FAILURE); +} + +void *key_blob; + +void *get_blob(void) +{ + return key_blob; +} + +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 cmdname[50]; + + strcpy(cmdname, *argv); + + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'f': + if (--argc <= 0) + usage(cmdname); + fdtfile = *++argv; + goto NXTARG; + + default: + usage(cmdname); + } + } +NXTARG:; + } + + if (argc != 2) + usage(cmdname); + + ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf); + + if (ffd < 0) { + printf("Could not open %s\n", fdtfile); + exit(EXIT_FAILURE); + } + + nodeoffset = fdt_path_offset(fit_blob, argv[0]); + if (nodeoffset < 0) { + printf("%s not found.", argv[0]); + exit(EXIT_FAILURE); + } + nodep = fdt_getprop(fit_blob, nodeoffset, argv[1], &len); + if (len == 0) { + printf("len == 0 %s\n", argv[1]); + 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); + + /* We're a bit of paranoid */ +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) + (void) fdatasync(ffd); +#else + (void) fsync(ffd); +#endif + + if (close(ffd)) { + fprintf(stderr, "%s: Write error on %s: %s\n", + cmdname, fdtfile, strerror(errno)); + exit(EXIT_FAILURE); + } + exit(EXIT_SUCCESS); +}

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
Makefile | 1 + common/image-sig.c | 22 +++++--- doc/uImage.FIT/signature.txt | 8 +++ include/fdt_support.h | 5 ++ include/image.h | 16 +++--- lib/libfdt/fdt_wip.c | 17 +++++++ lib/rsa/rsa-checksum.c | 10 ++-- lib/rsa/rsa-sign.c | 2 +- lib/rsa/rsa-verify.c | 18 +++++-- test/vboot/vboot_test.sh | 36 ++++++++++++- tools/Makefile | 19 ++++++- tools/fdt_host.h | 2 + tools/fit_check_sign.c | 119 +++++++++++++++++++++++++++++++++++++++++++ tools/image-host.c | 13 +++++ 14 files changed, 265 insertions(+), 23 deletions(-) create mode 100644 tools/fit_check_sign.c
diff --git a/Makefile b/Makefile index a2e424d..900d8f7 100644 --- a/Makefile +++ b/Makefile @@ -794,6 +794,7 @@ clean: @rm -f $(obj)tools/bmp_logo $(obj)tools/easylogo/easylogo \ $(obj)tools/env/fw_printenv \ $(obj)tools/envcrc \ + $(obj)tools/fit_check_sign \ $(obj)tools/fit_info \ $(obj)tools/gdb/{gdbcont,gdbsend} \ $(obj)tools/gen_eth_addr $(obj)tools/img2srec \ diff --git a/common/image-sig.c b/common/image-sig.c index 199e634..5b19ea8 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -19,6 +19,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMAGE_MAX_HASHED_NODES 100
#if defined(CONFIG_FIT_SIGNATURE) + +#ifdef USE_HOSTCC +__attribute__((weak)) void *get_blob(void) +{ + return NULL; +} +#endif + struct checksum_algo checksum_algos[] = { { "sha1", @@ -26,10 +34,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha1, -#else +#endif sha1_calculate, padding_sha1_rsa2048, -#endif }, { "sha256", @@ -37,10 +44,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa2048, -#endif }, { "sha256", @@ -48,10 +54,9 @@ struct checksum_algo checksum_algos[] = { RSA4096_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa4096, -#endif }
}; @@ -462,4 +467,9 @@ int fit_config_verify(const void *fit, int conf_noffset) return !fit_config_verify_required_sigs(fit, conf_noffset, gd_fdt_blob()); } +#else +int fit_config_verify(const void *fit, int conf_noffset) +{ + return 0; +} #endif diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index 5bd229f..171af2a 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -355,7 +355,11 @@ Test Verified Boot Run: signed images: OK Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images +check signed config on the host +OK Test Verified Boot Run: signed config: OK +check bad signed config on the host +OK Test Verified Boot Run: signed config with bad hash: OK
Test sha1 passed @@ -377,7 +381,11 @@ Test Verified Boot Run: signed images: OK Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images +check signed config on the host +OK Test Verified Boot Run: signed config: OK +check bad signed config on the host +OK Test Verified Boot Run: signed config with bad hash: OK
Test sha256 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 6e4745a..260a396 100644 --- a/include/image.h +++ b/include/image.h @@ -831,7 +831,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 @@ -843,7 +843,8 @@ int calculate_hash(const void *data, int data_len, const char *algo, #endif
#ifdef USE_HOSTCC -# define gd_fdt_blob() NULL +void *get_blob(void); +# define gd_fdt_blob() get_blob() #else # define gd_fdt_blob() (gd->fdt_blob) #endif @@ -880,14 +881,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 { @@ -1008,7 +1006,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/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c index 3f2dfa5..4babdbc 100644 --- a/lib/libfdt/fdt_wip.c +++ b/lib/libfdt/fdt_wip.c @@ -31,6 +31,23 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, return 0; }
+#ifdef USE_HOSTCC +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 + static void _fdt_nop_region(void *start, int len) { fdt32_t *p; 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 27b221a..fc33f2d 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -55,6 +55,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}"
@@ -88,7 +89,6 @@ ${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
@@ -101,6 +101,23 @@ run_uboot "unsigned config" $sha"+ OK" echo Sign images ${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+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 @@ -109,6 +126,23 @@ newbyte=$(printf %x $((0x${sig:0:2} + 1))) sig="${newbyte} ${sig:2}" fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
+echo check bad 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 "failed" ${tmp}; then + echo + echo "Verified boot key check failed, output follows:" + cat ${tmp} + false + else + echo "OK" + fi +fi + run_uboot "signed config with bad hash" "Bad Data Hash"
popd >/dev/null diff --git a/tools/Makefile b/tools/Makefile index d079bc9..874705a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -53,6 +53,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += dumpimage$(SFX) BIN_FILES-y += mkenvimage$(SFX) BIN_FILES-y += mkimage$(SFX) +BIN_FILES-y += fit_check_sign$(SFX) BIN_FILES-y += fit_info$(SFX) BIN_FILES-$(CONFIG_EXYNOS5250) += mk$(BOARD)spl$(SFX) BIN_FILES-$(CONFIG_EXYNOS5420) += mk$(BOARD)spl$(SFX) @@ -86,6 +87,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += imagetool.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o +NOPED_OBJ_FILES-y += fit_check_sign.o NOPED_OBJ_FILES-y += fit_info.o NOPED_OBJ_FILES-y += mxsimage.o NOPED_OBJ_FILES-y += omapimage.o @@ -122,7 +124,7 @@ LIBFDT_OBJ_FILES-y += fdt_strerror.o LIBFDT_OBJ_FILES-y += fdt_wip.o
# RSA objects -RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o +RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o rsa-verify.o rsa-checksum.o
# Generated LCD/video logo LOGO_H = $(OBJTREE)/include/bmp_logo.h @@ -266,6 +268,21 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) $(HOSTSTRIP) $@
+$(obj)fit_check_sign$(SFX): $(obj)fit_check_sign.o \ + $(FIT_SIG_OBJS) \ + $(obj)crc32.o \ + $(obj)fit_common.o \ + $(obj)image-fit.o \ + $(obj)image-host.o \ + $(obj)image.o \ + $(obj)md5.o \ + $(obj)sha1.o \ + $(obj)sha256.o \ + $(LIBFDT_OBJS) \ + $(RSA_OBJS) + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) + $(HOSTSTRIP) $@ + $(obj)fit_info$(SFX): $(obj)fit_info.o \ $(FIT_SIG_OBJS) \ $(obj)crc32.o \ 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/fit_check_sign.c b/tools/fit_check_sign.c new file mode 100644 index 0000000..63c7295 --- /dev/null +++ b/tools/fit_check_sign.c @@ -0,0 +1,119 @@ +/* + * (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 *key_blob; + +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); +} + +void *get_blob(void) +{ + return key_blob; +} + +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; + + strcpy(cmdname, *argv); + + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'f': + if (--argc <= 0) + usage(cmdname); + fdtfile = *++argv; + goto NXTARG; + + case 'k': + if (--argc <= 0) + usage(cmdname); + keyfile = *++argv; + goto NXTARG; + + default: + usage(cmdname); + } + } +NXTARG:; + } + + if (argc != 0) + usage(cmdname); + + ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf); + kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf); + + 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); + + /* We're a bit of paranoid */ +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) + (void) fdatasync(ffd); + (void) fdatasync(kfd); +#else + (void) fsync(ffd); + (void) fsync(kfd); +#endif + + if (close(ffd)) { + fprintf(stderr, "%s: Write error on %s: %s\n", + cmdname, fdtfile, strerror(errno)); + exit(EXIT_FAILURE); + } + if (close(kfd)) { + fprintf(stderr, "%s: Write error on %s: %s\n", + cmdname, keyfile, strerror(errno)); + exit(EXIT_FAILURE); + } + + exit(ret); +} diff --git a/tools/image-host.c b/tools/image-host.c index 8e185ec..65e3932 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -695,3 +695,16 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
return 0; } + +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; +}

Hi Heiko,
On 8 February 2014 22:34, 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
Overall this seems reasonable, and very useful. I'm just a little nervous about some of the work-arounds to make the code run on the host. So a few minor comments.
- changes for v2:
- fixed compile error for sandbox
- add fit_check_sign test to test/vboot/vboot_test.sh
Makefile | 1 + common/image-sig.c | 22 +++++--- doc/uImage.FIT/signature.txt | 8 +++ include/fdt_support.h | 5 ++ include/image.h | 16 +++--- lib/libfdt/fdt_wip.c | 17 +++++++ lib/rsa/rsa-checksum.c | 10 ++-- lib/rsa/rsa-sign.c | 2 +- lib/rsa/rsa-verify.c | 18 +++++-- test/vboot/vboot_test.sh | 36 ++++++++++++- tools/Makefile | 19 ++++++- tools/fdt_host.h | 2 + tools/fit_check_sign.c | 119 +++++++++++++++++++++++++++++++++++++++++++ tools/image-host.c | 13 +++++ 14 files changed, 265 insertions(+), 23 deletions(-) create mode 100644 tools/fit_check_sign.c
diff --git a/Makefile b/Makefile index a2e424d..900d8f7 100644 --- a/Makefile +++ b/Makefile @@ -794,6 +794,7 @@ clean: @rm -f $(obj)tools/bmp_logo $(obj)tools/easylogo/easylogo \ $(obj)tools/env/fw_printenv \ $(obj)tools/envcrc \
$(obj)tools/fit_check_sign \ $(obj)tools/fit_info \ $(obj)tools/gdb/{gdbcont,gdbsend} \ $(obj)tools/gen_eth_addr $(obj)tools/img2srec \
diff --git a/common/image-sig.c b/common/image-sig.c index 199e634..5b19ea8 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -19,6 +19,14 @@ DECLARE_GLOBAL_DATA_PTR; #define IMAGE_MAX_HASHED_NODES 100
#if defined(CONFIG_FIT_SIGNATURE)
+#ifdef USE_HOSTCC +__attribute__((weak)) void *get_blob(void) +{
return NULL;
+} +#endif
Why make this weak? A better name would be something like image_get_host_blob(). I think we should get a compile error if it is not defined.
struct checksum_algo checksum_algos[] = { { "sha1", @@ -26,10 +34,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha1, -#else +#endif sha1_calculate, padding_sha1_rsa2048, -#endif }, { "sha256", @@ -37,10 +44,9 @@ struct checksum_algo checksum_algos[] = { RSA2048_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa2048, -#endif }, { "sha256", @@ -48,10 +54,9 @@ struct checksum_algo checksum_algos[] = { RSA4096_BYTES, #if IMAGE_ENABLE_SIGN EVP_sha256, -#else +#endif sha256_calculate, padding_sha256_rsa4096, -#endif }
}; @@ -462,4 +467,9 @@ int fit_config_verify(const void *fit, int conf_noffset) return !fit_config_verify_required_sigs(fit, conf_noffset, gd_fdt_blob()); } +#else +int fit_config_verify(const void *fit, int conf_noffset) +{
return 0;
+} #endif diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt index 5bd229f..171af2a 100644 --- a/doc/uImage.FIT/signature.txt +++ b/doc/uImage.FIT/signature.txt @@ -355,7 +355,11 @@ Test Verified Boot Run: signed images: OK Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images +check signed config on the host +OK Test Verified Boot Run: signed config: OK +check bad signed config on the host +OK Test Verified Boot Run: signed config with bad hash: OK
Test sha1 passed @@ -377,7 +381,11 @@ Test Verified Boot Run: signed images: OK Build FIT with signed configuration Test Verified Boot Run: unsigned config: OK Sign images +check signed config on the host +OK Test Verified Boot Run: signed config: OK +check bad signed config on the host +OK Test Verified Boot Run: signed config with bad hash: OK
Test sha256 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 6e4745a..260a396 100644 --- a/include/image.h +++ b/include/image.h @@ -831,7 +831,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 @@ -843,7 +843,8 @@ int calculate_hash(const void *data, int data_len, const char *algo, #endif
#ifdef USE_HOSTCC -# define gd_fdt_blob() NULL +void *get_blob(void); +# define gd_fdt_blob() get_blob()
image_get_host_blob()
#else # define gd_fdt_blob() (gd->fdt_blob) #endif @@ -880,14 +881,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 { @@ -1008,7 +1006,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/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c index 3f2dfa5..4babdbc 100644 --- a/lib/libfdt/fdt_wip.c +++ b/lib/libfdt/fdt_wip.c @@ -31,6 +31,23 @@ int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, return 0; }
+#ifdef USE_HOSTCC +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
I don't think you can put this function here - it is an upstream library. If you don't want to include fdtdec.c into the hostcc compilation, then perhaps add this function into a host file somewhere, with a comment as to why it is here.
static void _fdt_nop_region(void *start, int len) { fdt32_t *p; 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 27b221a..fc33f2d 100755 --- a/test/vboot/vboot_test.sh +++ b/test/vboot/vboot_test.sh @@ -55,6 +55,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}"
@@ -88,7 +89,6 @@ ${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
@@ -101,6 +101,23 @@ run_uboot "unsigned config" $sha"+ OK" echo Sign images ${mkimage} -D "${dtc}" -F -k dev-keys -K sandbox-u-boot.dtb -r test.fit >${tmp}
+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 @@ -109,6 +126,23 @@ newbyte=$(printf %x $((0x${sig:0:2} + 1))) sig="${newbyte} ${sig:2}" fdtput -t bx test.fit /configurations/conf@1/signature@1 value ${sig}
+echo check bad 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 "failed" ${tmp}; then
echo
echo "Verified boot key check failed, output follows:"
cat ${tmp}
false
else
echo "OK"
fi
+fi
run_uboot "signed config with bad hash" "Bad Data Hash"
popd >/dev/null diff --git a/tools/Makefile b/tools/Makefile index d079bc9..874705a 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -53,6 +53,7 @@ BIN_FILES-$(CONFIG_XWAY_SWAP_BYTES) += xway-swap-bytes$(SFX) BIN_FILES-y += dumpimage$(SFX) BIN_FILES-y += mkenvimage$(SFX) BIN_FILES-y += mkimage$(SFX) +BIN_FILES-y += fit_check_sign$(SFX) BIN_FILES-y += fit_info$(SFX) BIN_FILES-$(CONFIG_EXYNOS5250) += mk$(BOARD)spl$(SFX) BIN_FILES-$(CONFIG_EXYNOS5420) += mk$(BOARD)spl$(SFX) @@ -86,6 +87,7 @@ NOPED_OBJ_FILES-y += kwbimage.o NOPED_OBJ_FILES-y += imagetool.o NOPED_OBJ_FILES-y += mkenvimage.o NOPED_OBJ_FILES-y += mkimage.o +NOPED_OBJ_FILES-y += fit_check_sign.o NOPED_OBJ_FILES-y += fit_info.o NOPED_OBJ_FILES-y += mxsimage.o NOPED_OBJ_FILES-y += omapimage.o @@ -122,7 +124,7 @@ LIBFDT_OBJ_FILES-y += fdt_strerror.o LIBFDT_OBJ_FILES-y += fdt_wip.o
# RSA objects -RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o +RSA_OBJ_FILES-$(CONFIG_FIT_SIGNATURE) += rsa-sign.o rsa-verify.o rsa-checksum.o
# Generated LCD/video logo LOGO_H = $(OBJTREE)/include/bmp_logo.h @@ -266,6 +268,21 @@ $(obj)mkimage$(SFX): $(obj)aisimage.o \ $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS) $(HOSTSTRIP) $@
+$(obj)fit_check_sign$(SFX): $(obj)fit_check_sign.o \
$(FIT_SIG_OBJS) \
$(obj)crc32.o \
$(obj)fit_common.o \
$(obj)image-fit.o \
$(obj)image-host.o \
$(obj)image.o \
$(obj)md5.o \
$(obj)sha1.o \
$(obj)sha256.o \
$(LIBFDT_OBJS) \
$(RSA_OBJS)
$(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTLIBS)
$(HOSTSTRIP) $@
$(obj)fit_info$(SFX): $(obj)fit_info.o \ $(FIT_SIG_OBJS) \ $(obj)crc32.o \ 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/fit_check_sign.c b/tools/fit_check_sign.c new file mode 100644 index 0000000..63c7295 --- /dev/null +++ b/tools/fit_check_sign.c @@ -0,0 +1,119 @@ +/*
- (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 *key_blob;
+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);
+}
+void *get_blob(void) +{
return key_blob;
+}
+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;
strcpy(cmdname, *argv);
while (--argc > 0 && **++argv == '-') {
while (*++*argv) {
If this is a new tool, shouldn't we use getopt()?
switch (**argv) {
case 'f':
if (--argc <= 0)
usage(cmdname);
fdtfile = *++argv;
goto NXTARG;
case 'k':
if (--argc <= 0)
usage(cmdname);
keyfile = *++argv;
goto NXTARG;
default:
usage(cmdname);
}
}
+NXTARG:;
}
if (argc != 0)
usage(cmdname);
ffd = mmap_fdt(cmdname, fdtfile, &fit_blob, &fsbuf);
kfd = mmap_fdt(cmdname, keyfile, &key_blob, &ksbuf);
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);
from here:
/* We're a bit of paranoid */
+#if defined(_POSIX_SYNCHRONIZED_IO) && \
!defined(__sun__) && \
!defined(__FreeBSD__) && \
!defined(__APPLE__)
(void) fdatasync(ffd);
(void) fdatasync(kfd);
+#else
(void) fsync(ffd);
(void) fsync(kfd);
+#endif
I don't think we need this since we are not changing the file.
if (close(ffd)) {
fprintf(stderr, "%s: Write error on %s: %s\n",
cmdname, fdtfile, strerror(errno));
exit(EXIT_FAILURE);
}
if (close(kfd)) {
fprintf(stderr, "%s: Write error on %s: %s\n",
cmdname, keyfile, strerror(errno));
exit(EXIT_FAILURE);
}
We are not writing, I think we can ignore errors on close().
exit(ret);
+} diff --git a/tools/image-host.c b/tools/image-host.c index 8e185ec..65e3932 100644 --- a/tools/image-host.c +++ b/tools/image-host.c @@ -695,3 +695,16 @@ int fit_add_verification_data(const char *keydir, void *keydest, void *fit,
return 0;
}
+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;
+}
1.8.3.1
Regards, Simon
participants (2)
-
Heiko Schocher
-
Simon Glass