
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