Hi Heiko, On 24 January 2014 23:44, Heiko Schocher <h...@denx.de> wrote: > based on patch from andr...@oetken.name: > > http://patchwork.ozlabs.org/patch/294318/
Should probably add the full commit message in here. > > - removed checkpatch warnings > - removed compiler warnings > - rebased against current head > > Signed-off-by: Heiko Schocher <h...@denx.de> > Cc: Simon Glass <s...@chromium.org> > Cc: andr...@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 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot