[U-Boot] [PATCH 0/7] 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
Heiko Schocher (7): tools/image-host: fix sign-images bug fdt: add "fdt sign" command fit: add sha256 support rsa: add sha256-rsa2048 algorithm rsa: add sha256,rsa4096 algorithm tools, fit: add fit_info host command tools, fit_check_sign: verify a signed fit image
Makefile | 2 + common/cmd_fdt.c | 38 +++++++++++- common/image-fit.c | 5 ++ common/image-sig.c | 66 ++++++++++++++++++++ include/fdt_support.h | 5 ++ include/image.h | 37 ++++++++++- include/rsa-checksum.h | 26 ++++++++ include/rsa.h | 35 +++++++++++ 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 | 101 ++++++++++-------------------- lib/sha256.c | 2 +- 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 ++++- 22 files changed, 831 insertions(+), 137 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c create mode 100644 tools/fit_check_sign.c create mode 100644 tools/fit_common.c create mode 100644 tools/fit_common.h create mode 100644 tools/fit_info.c
Cc: Simon Glass sjg@chromium.org Cc: andreas@oetken.name

property "sign-images" is never found, fix this.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org --- 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;

Hi Heiko,
On 24 January 2014 23:44, Heiko Schocher hs@denx.de wrote:
property "sign-images" is never found, fix this.
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
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);
Acked-by: Simon Glass sjg@chromium.org
Unfortunately I did not add a test for this.
if (!prop) return 0;
-- 1.8.3.1
Regards, Simon

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 --- common/cmd_fdt.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 3a9edd6..b8468ea 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -243,7 +243,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* * Set the value of a property in the working_fdt. */ - } else if (argv[1][0] == 's') { + } else if (strncmp(argv[1], "se", 2) == 0) { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */ @@ -283,6 +283,37 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; }
+#if defined(CONFIG_FIT_SIGNATURE) + } else if (strncmp(argv[1], "si", 2) == 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) + 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 + /******************************************************************** * Get the value of a property in the working_fdt. ********************************************************************/ @@ -992,6 +1023,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 sign [<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

Hi Heiko,
On 24 January 2014 23:44, 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
common/cmd_fdt.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 3a9edd6..b8468ea 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -243,7 +243,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* * Set the value of a property in the working_fdt. */
} else if (argv[1][0] == 's') {
} else if (strncmp(argv[1], "se", 2) == 0) { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */
@@ -283,6 +283,37 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; }
+#if defined(CONFIG_FIT_SIGNATURE)
} else if (strncmp(argv[1], "si", 2) == 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)
return CMD_RET_FAILURE;
May need to print an error here, since otherwise it won't be clear what went wrong.
ret = fit_config_verify(working_fdt, cfg_noffset);
if (ret == 1)
return CMD_RET_SUCCESS;
else
return CMD_RET_FAILURE;
+#endif
/******************************************************************** * Get the value of a property in the working_fdt. ********************************************************************/
@@ -992,6 +1023,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 sign [<addr>] - check FIT signature\n"
How about checksig instead of sign? 'sign' sounds like you are going to sign it.
" <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
1.8.3.1
Regards, Simon

Hello Simon,
Am 26.01.2014 22:04, schrieb Simon Glass:
Hi Heiko,
On 24 January 2014 23:44, Heiko Schocherhs@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 Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
common/cmd_fdt.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/common/cmd_fdt.c b/common/cmd_fdt.c index 3a9edd6..b8468ea 100644 --- a/common/cmd_fdt.c +++ b/common/cmd_fdt.c @@ -243,7 +243,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) /* * Set the value of a property in the working_fdt. */
} else if (argv[1][0] == 's') {
} else if (strncmp(argv[1], "se", 2) == 0) { char *pathp; /* path */ char *prop; /* property */ int nodeoffset; /* node offset from libfdt */
@@ -283,6 +283,37 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; }
+#if defined(CONFIG_FIT_SIGNATURE)
} else if (strncmp(argv[1], "si", 2) == 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)
return CMD_RET_FAILURE;
May need to print an error here, since otherwise it won't be clear what went wrong.
Hmm... fit_conf_get_node() prints a dedicated error message if debug is activated... I thought this is enough ... ?
ret = fit_config_verify(working_fdt, cfg_noffset);
if (ret == 1)
return CMD_RET_SUCCESS;
else
return CMD_RET_FAILURE;
+#endif
/******************************************************************** * Get the value of a property in the working_fdt. ********************************************************************/
@@ -992,6 +1023,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 sign [<addr>] - check FIT signature\n"
How about checksig instead of sign? 'sign' sounds like you are going to sign it.
Of course, that sounds better! Change this for v2, thanks!
"<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
1.8.3.1
Regards, Simon
Thanks for the review.
bye, Heiko

Dear Heiko,
In message 52E5FE93.2030306@denx.de you wrote:
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
if (!cfg_noffset)
return CMD_RET_FAILURE;
May need to print an error here, since otherwise it won't be clear what went wrong.
Hmm... fit_conf_get_node() prints a dedicated error message if debug is
^^^^^^^^^^^
activated... I thought this is enough ... ?
^^^^^^^^^
But in production versions (with debug NOT enabled) the user would never know what went wrong?
Best regards,
Wolfgang Denk

Hello Wolfgang,
Am 27.01.2014 07:50, schrieb Wolfgang Denk:
Dear Heiko,
In message52E5FE93.2030306@denx.de you wrote:
cfg_noffset = fit_conf_get_node(working_fdt, NULL);
if (!cfg_noffset)
return CMD_RET_FAILURE;
May need to print an error here, since otherwise it won't be clear what went wrong.
Hmm... fit_conf_get_node() prints a dedicated error message if debug is
^^^^^^^^^^^
activated... I thought this is enough ... ?
^^^^^^^^^
But in production versions (with debug NOT enabled) the user would never know what went wrong?
Good argument, so, add an error message in next patch version.
bye, Heiko

On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Best regards, Marek Vasut

Hello Marek,
Am 08.02.2014 15:09, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Why not? I use this "fdt check" command for example in a script, for checking if the FIT image is correct signed, and if so, update with the binaries in it some UBI Volumes (not only kernel, dt and/or rootfs) ... but if this is not accepted, I can look into the bootm command if I can use it ... but I do not want boot the FIT image ...
bye, Heiko

On Monday, February 10, 2014 at 07:15:09 AM, Heiko Schocher wrote:
Hello Marek,
Am 08.02.2014 15:09, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Why not? I use this "fdt check" command for example in a script, for checking if the FIT image is correct signed, and if so, update with the binaries in it some UBI Volumes (not only kernel, dt and/or rootfs) ... but if this is not accepted, I can look into the bootm command if I can use it ... but I do not want boot the FIT image ...
But doesn't 'bootm prep' (aka. prepare the image for booting, but do not actually boot) do the same thing ? It does verify the image etc., right ?
Best regards, Marek Vasut

Hello Marek,
Am 12.02.2014 11:46, schrieb Marek Vasut:
On Monday, February 10, 2014 at 07:15:09 AM, Heiko Schocher wrote:
Hello Marek,
Am 08.02.2014 15:09, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Why not? I use this "fdt check" command for example in a script, for checking if the FIT image is correct signed, and if so, update with the binaries in it some UBI Volumes (not only kernel, dt and/or rootfs) ... but if this is not accepted, I can look into the bootm command if I can use it ... but I do not want boot the FIT image ...
But doesn't 'bootm prep' (aka. prepare the image for booting, but do not actually boot) do the same thing ? It does verify the image etc., right ?
Yes, but maybe do "etc" things I do not need?
From the "bootm prep" help text: "prep - OS specific prep before relocation or go"
"OS specific prep or go" ... Hmm...
- The "fdt checksign" command (as I renamed it in v2) does no "OS specific" things, only check the signature of the FIT image. There is no OS dependency ... With "bootm prep" there are maybe done OS specific things with the FIT Image ... maybe in my case it would work, but is this true for all boards?
- "or go" ... I definitely do not want to boot the FIT Image!
bye, Heiko

On Wednesday, February 12, 2014 at 04:31:50 PM, Heiko Schocher wrote:
Hello Marek,
Am 12.02.2014 11:46, schrieb Marek Vasut:
On Monday, February 10, 2014 at 07:15:09 AM, Heiko Schocher wrote:
Hello Marek,
Am 08.02.2014 15:09, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Why not? I use this "fdt check" command for example in a script, for checking if the FIT image is correct signed, and if so, update with the binaries in it some UBI Volumes (not only kernel, dt and/or rootfs) ... but if this is not accepted, I can look into the bootm command if I can use it ... but I do not want boot the FIT image ...
But doesn't 'bootm prep' (aka. prepare the image for booting, but do not actually boot) do the same thing ? It does verify the image etc., right ?
Yes, but maybe do "etc" things I do not need?
From the "bootm prep" help text: "prep - OS specific prep before relocation or go"
"OS specific prep or go" ... Hmm...
The "fdt checksign" command (as I renamed it in v2) does no "OS specific" things, only check the signature of the FIT image. There is no OS dependency ... With "bootm prep" there are maybe done OS specific things with the FIT Image ... maybe in my case it would work, but is this true for all boards?
"or go" ... I definitely do not want to boot the FIT Image!
CC Simon, he might clear this up. I'm sick (flu?) and I don't want to leave this thread hanging , sorry.
Best regards, Marek Vasut

Hello Marek,
Am 13.02.2014 21:26, schrieb Marek Vasut:
On Wednesday, February 12, 2014 at 04:31:50 PM, Heiko Schocher wrote:
Hello Marek,
Am 12.02.2014 11:46, schrieb Marek Vasut:
On Monday, February 10, 2014 at 07:15:09 AM, Heiko Schocher wrote:
Hello Marek,
Am 08.02.2014 15:09, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:24 AM, Heiko Schocher wrote:
check if a fdt is correct signed pass an optional addr value. Contains the addr of the key blob
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Should the FIT signature checking really be part of the 'fdt' command ? Shouldn't 'bootm' check the signature (well, 'bootm prep' or such does) or somesuch command ?
Why not? I use this "fdt check" command for example in a script, for checking if the FIT image is correct signed, and if so, update with the binaries in it some UBI Volumes (not only kernel, dt and/or rootfs) ... but if this is not accepted, I can look into the bootm command if I can use it ... but I do not want boot the FIT image ...
But doesn't 'bootm prep' (aka. prepare the image for booting, but do not actually boot) do the same thing ? It does verify the image etc., right ?
Yes, but maybe do "etc" things I do not need?
From the "bootm prep" help text: "prep - OS specific prep before relocation or go"
"OS specific prep or go" ... Hmm...
The "fdt checksign" command (as I renamed it in v2) does no "OS specific" things, only check the signature of the FIT image. There is no OS dependency ... With "bootm prep" there are maybe done OS specific things with the FIT Image ... maybe in my case it would work, but is this true for all boards?
"or go" ... I definitely do not want to boot the FIT Image!
CC Simon, he might clear this up. I'm sick (flu?) and I don't want to leave this
Simon is on Cc, and he remarked to rename this "fdt sign" into "fdt checksign", I did in the "v2" of this patch ...
thread hanging , sorry.
Bad news. I hope you get well soon!
bye, Heiko

add sha256 support to fit images
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org --- 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)

On 24 January 2014 23:44, Heiko Schocher hs@denx.de wrote:
add sha256 support to fit images
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
Acked-by: Simon Glass sjg@chromium.org
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)
-- 1.8.3.1

based on patch from andreas@oetken.name:
http://patchwork.ozlabs.org/patch/294318/
- removed checkpatch warnings - removed compiler warnings - rebased against current head
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org Cc: andreas@oetken.name --- common/image-sig.c | 33 +++++++++++++++++ include/image.h | 21 +++++++++++ include/rsa-checksum.h | 25 +++++++++++++ include/rsa.h | 25 +++++++++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 +++--- lib/rsa/rsa-verify.c | 83 +++++++++++++----------------------------- 8 files changed, 233 insertions(+), 64 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c
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/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..adf809b 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 @@ -80,6 +94,10 @@ static inline int rsa_add_verify_data(struct image_sign_info *info, int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len); + +int rsa_verify_256(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len); #else static inline int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, @@ -87,6 +105,13 @@ static inline int rsa_verify(struct image_sign_info *info, { return -ENXIO; } + +static inline int rsa_verify_256(struct image_sign_info *info, + const struct image_region region[], int region_count, + uint8_t *sig, uint sig_len) +{ + return -ENXIO; +} #endif
#endif diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile 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) {

Hi Heiko,
On 24 January 2014 23:44, Heiko Schocher hs@denx.de wrote:
based on patch from andreas@oetken.name:
Should probably add the full commit message in here.
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org Cc: andreas@oetken.name
common/image-sig.c | 33 +++++++++++++++++ include/image.h | 21 +++++++++++ include/rsa-checksum.h | 25 +++++++++++++ include/rsa.h | 25 +++++++++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 +++--- lib/rsa/rsa-verify.c | 83 +++++++++++++----------------------------- 8 files changed, 233 insertions(+), 64 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c
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/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..adf809b 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
@@ -80,6 +94,10 @@ static inline int rsa_add_verify_data(struct image_sign_info *info, int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len);
+int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
Do we need to create this as a separate function? It seems a bit icky. Can rsa_verify() not handle both?
#else static inline int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, @@ -87,6 +105,13 @@ static inline int rsa_verify(struct image_sign_info *info, { return -ENXIO; }
+static inline int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len)
+{
return -ENXIO;
+} #endif
#endif diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile 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) {
-- 1.8.3.1
Also can you please update the tests to include a sha256 test?
Regards, Simon

Hello Simon,
Am 26.01.2014 22:10, schrieb Simon Glass:
Hi Heiko,
On 24 January 2014 23:44, Heiko Schocherhs@denx.de wrote:
based on patch from andreas@oetken.name:
Should probably add the full commit message in here.
Ok, do this in v2.
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org Cc: andreas@oetken.name
common/image-sig.c | 33 +++++++++++++++++ include/image.h | 21 +++++++++++ include/rsa-checksum.h | 25 +++++++++++++ include/rsa.h | 25 +++++++++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 +++--- lib/rsa/rsa-verify.c | 83 +++++++++++++----------------------------- 8 files changed, 233 insertions(+), 64 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c
[...]
diff --git a/include/rsa.h b/include/rsa.h index add4c78..adf809b 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
@@ -80,6 +94,10 @@ static inline int rsa_add_verify_data(struct image_sign_info *info, int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len);
+int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
Do we need to create this as a separate function? It seems a bit icky. Can rsa_verify() not handle both?
Good catch! I never defined rsa_verify_256(), remove this in v2.
#else static inline int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, @@ -87,6 +105,13 @@ static inline int rsa_verify(struct image_sign_info *info, { return -ENXIO; }
+static inline int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len)
+{
return -ENXIO;
+} #endif
#endif
[...]
Also can you please update the tests to include a sha256 test?
You mean the "test/vboot/vboot_test.sh" ?
bye, Heiko

Hi Heiko,
On 26 January 2014 22:45, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 26.01.2014 22:10, schrieb Simon Glass:
Hi Heiko,
On 24 January 2014 23:44, Heiko Schocherhs@denx.de wrote:
based on patch from andreas@oetken.name:
Should probably add the full commit message in here.
Ok, do this in v2.
- removed checkpatch warnings
- removed compiler warnings
- rebased against current head
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org Cc: andreas@oetken.name
common/image-sig.c | 33 +++++++++++++++++ include/image.h | 21 +++++++++++ include/rsa-checksum.h | 25 +++++++++++++ include/rsa.h | 25 +++++++++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-checksum.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-sign.c | 10 +++--- lib/rsa/rsa-verify.c | 83 +++++++++++++----------------------------- 8 files changed, 233 insertions(+), 64 deletions(-) create mode 100644 include/rsa-checksum.h create mode 100644 lib/rsa/rsa-checksum.c
[...]
diff --git a/include/rsa.h b/include/rsa.h index add4c78..adf809b 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
@@ -80,6 +94,10 @@ static inline int rsa_add_verify_data(struct image_sign_info *info, int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len);
+int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
Do we need to create this as a separate function? It seems a bit icky. Can rsa_verify() not handle both?
Good catch! I never defined rsa_verify_256(), remove this in v2.
#else static inline int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, @@ -87,6 +105,13 @@ static inline int rsa_verify(struct image_sign_info *info, { return -ENXIO; }
+static inline int rsa_verify_256(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len)
+{
return -ENXIO;
+} #endif
#endif
[...]
Also can you please update the tests to include a sha256 test?
You mean the "test/vboot/vboot_test.sh" ?
Yes, you could expand this, or convert to Python if you prefer.
Regards, Simon

Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org --- 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 adf809b..20e842e 100644 --- a/include/rsa.h +++ b/include/rsa.h @@ -114,4 +114,14 @@ static inline int rsa_verify_256(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; }

Hi Heiko,
On 24 January 2014 23:44, Heiko Schocher hs@denx.de wrote:
Signed-off-by: Heiko Schocher hs@denx.de Cc: Simon Glass sjg@chromium.org
Missing commit message. Is there no way to integrate this with common/hash.c? Perhaps the start/finish part of the hashing algorithm should be added to hash.h struct hash_algo?
I have a patch from Hung-ying Tyan that mostly does this. It won't apply directly, but here it is below in case it helps...
Regards, Simon
From: Hung-ying Tyan tyanh@chromium.org Date: Tue, 21 May 2013 18:24:37 +0800 Subject: [PATCH] gen: Add progressive hash API
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.
Got properly encoded result. See https://gerrit-int.chromium.org/#/c/38781 for the hashp command. Used "mm" command to iteratively write and "md" command to dump standard string (mentioned below) to memory location 0x40008000.
String: "20656854 63697571 7262206b 206e776f 20786f66 706d756a 766f2073 74207265 6c206568 20797a61 00676f64 00000000"
("The quick brown fox jumps over the lazy dog")
Encoded String: "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
Signed-off-by: Hung-ying Tyan tyanh@chromium.org Signed-off-by: Simon Glass sjg@chromium.org --- common/hash.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++------ include/hash.h | 49 ++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 11 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 10e887f..5d4fc4e 100644 --- a/common/hash.c +++ b/common/hash.c @@ -26,11 +26,94 @@ #include <common.h> #include <command.h> #include <hash.h> +#include <malloc.h> #include <sha1.h> #include <sha256.h> #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 @@ -65,6 +148,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 @@ -74,6 +160,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 @@ -82,6 +171,9 @@ static struct hash_algo hash_algo[] = { 4, crc32_wd_buf, CHUNKSZ_CRC32, + hash_init_crc32, + hash_update_crc32, + hash_finish_crc32, }, };
@@ -216,16 +308,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, @@ -242,12 +337,11 @@ int hash_block(const char *algo_name, const void *data, int len, uint8_t *output, int *output_size) { struct hash_algo *algo; + int ret;
- algo = find_hash_algo(algo_name); - if (!algo) { - debug("Unknown hash algorithm '%s'\n", algo_name); - return -EPROTONOSUPPORT; - } + ret = hash_lookup_algo(algo_name, &algo); + if (ret) + return ret; if (output_size && *output_size < algo->digest_size) { debug("Output buffer size %d too small (need %d bytes)", *output_size, algo->digest_size); @@ -276,8 +370,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 a837551..0c54e88 100644 --- a/include/hash.h +++ b/include/hash.h @@ -43,6 +43,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); };
/* @@ -86,4 +122,17 @@ 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, 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

Hello Simon,
Am 26.01.2014 22:19, schrieb Simon Glass:
Hi Heiko,
On 24 January 2014 23:44, Heiko Schocherhs@denx.de wrote:
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Missing commit message. Is there no way to integrate this with common/hash.c? Perhaps the start/finish part of the hashing algorithm should be added to hash.h struct hash_algo?
I have a patch from Hung-ying Tyan that mostly does this. It won't apply directly, but here it is below in case it helps...
I tried this patch, and it works fine. I prefer to add this patch to my patchserie, so this change is cleanly seperated. Is this ok?
bye, Heiko

Hi Heiko,
On 26 January 2014 23:36, Heiko Schocher hs@denx.de wrote:
Hello Simon,
Am 26.01.2014 22:19, schrieb Simon Glass:
Hi Heiko,
On 24 January 2014 23:44, Heiko Schocherhs@denx.de wrote:
Signed-off-by: Heiko Schocherhs@denx.de Cc: Simon Glasssjg@chromium.org
Missing commit message. Is there no way to integrate this with common/hash.c? Perhaps the start/finish part of the hashing algorithm should be added to hash.h struct hash_algo?
I have a patch from Hung-ying Tyan that mostly does this. It won't apply directly, but here it is below in case it helps...
I tried this patch, and it works fine. I prefer to add this patch to my patchserie, so this change is cleanly seperated. Is this ok?
Yes of course, thanks.
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 --- 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); +}

On Saturday, January 25, 2014 at 07:44:28 AM, Heiko Schocher wrote:
add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties data with linux tools, for example "dd".
Signed-off-by: Heiko Schocher hs@denx.de
[...]
+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);
Are you sure about this unlink() call here ? The unlink() might delete the file, dunno if that was intended ;-)
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);
Here this might be a problem ;-)
Also, make sure to set errno = 0 before mmap() and check the errno afterwards here too. [...] Best regards, Marek Vasut

Hello Marek,
Am 08.02.2014 15:16, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:28 AM, Heiko Schocher wrote:
add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties data with linux tools, for example "dd".
Signed-off-by: Heiko Schocherhs@denx.de
[...]
+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);
Are you sure about this unlink() call here ? The unlink() might delete the file, dunno if that was intended ;-)
Heh.. good catch! I only moved this function from tools/fit_image.c to a common place, so other function can use it too ... but I just noticed, I do not really need this ...
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);
Here this might be a problem ;-)
Also, make sure to set errno = 0 before mmap() and check the errno afterwards here too. [...]
Seems this function needs a rework! I drop this from my patch, as I do not need it.
bye, Heiko

On Monday, February 10, 2014 at 07:28:51 AM, Heiko Schocher wrote:
Hello Marek,
Am 08.02.2014 15:16, schrieb Marek Vasut:
On Saturday, January 25, 2014 at 07:44:28 AM, Heiko Schocher wrote:
add fit_info command to the host tools. This command prints the name, offset and the len from a property from a node in a fit file. This info can be used to extract a properties data with linux tools, for example "dd".
Signed-off-by: Heiko Schocherhs@denx.de
[...]
+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);
Are you sure about this unlink() call here ? The unlink() might delete the file, dunno if that was intended ;-)
Heh.. good catch! I only moved this function from tools/fit_image.c to a common place, so other function can use it too ... but I just noticed, I do not really need this ...
[...]
Seems this function needs a rework! I drop this from my patch, as I do not need it.
Thanks!
Best regards, Marek Vasut

add host tool "fit_check_sign" which verifies, if a fit image is signed correct.
Signed-off-by: Heiko Schocher hs@denx.de --- Makefile | 1 + common/image-sig.c | 22 ++++++--- include/fdt_support.h | 5 +++ include/image.h | 16 ++++--- lib/libfdt/fdt_wip.c | 17 +++++++ lib/rsa/rsa-checksum.c | 4 ++ lib/rsa/rsa-sign.c | 2 +- lib/rsa/rsa-verify.c | 10 ++++- tools/Makefile | 19 +++++++- tools/fdt_host.h | 2 + tools/fit_check_sign.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ tools/image-host.c | 13 ++++++ 12 files changed, 214 insertions(+), 16 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/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..b12b35e 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/rsa/rsa-checksum.c @@ -4,8 +4,12 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> +#else +#include "fdt_host.h" +#endif #include <rsa.h> #include <sha1.h> #include <sha256.h> 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..48be99d 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -4,8 +4,14 @@ * SPDX-License-Identifier: GPL-2.0+ */
+#ifndef USE_HOSTCC #include <common.h> #include <fdtdec.h> +#else +#include "fdt_host.h" +#include "mkimage.h" +#include <fdt_support.h> +#endif #include <rsa.h> #include <sha1.h> #include <sha256.h> @@ -15,6 +21,9 @@
#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 +159,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/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; +}
participants (4)
-
Heiko Schocher
-
Marek Vasut
-
Simon Glass
-
Wolfgang Denk