Hi Ruchika, On 30 December 2014 at 02:30, Ruchika Gupta <ruchika.gu...@freescale.com> wrote: > Public exponentiation which is required in rsa verify functionality is > tightly integrated with verification code in rsa_verify.c. The patch > splits the file into twp separating the modular exponentiation. > > 1. rsa-verify.c > - The file parses device tree keys node to fill a keyprop structure. > The keyprop structure can then be converted to implementation specific > format. > (struct rsa_pub_key for sw implementation) > - The parsed device tree node is then passed to a generic rsa_mod_exp > function. > > 2. rsa-mod-exp.c > Move the software specific functions related to modular exponentiation > from rsa-verify.c to this file. > > Signed-off-by: Ruchika Gupta <ruchika.gu...@freescale.com> > CC: Simon Glass <s...@chromium.org> > --- > Changes in v4: > Modified rsa_mod_exp_sw function to add pointer to output length > > Changes in v3: > Kconfig moved to separate patch. This patch just splits the file now > > Changes in v2: > Addressed few of Simon Glass's comments: > - Kconfig option added for RSA > - Comments added for new keyprop struct > > include/u-boot/rsa-mod-exp.h | 49 +++++++ > lib/rsa/Makefile | 2 +- > lib/rsa/rsa-mod-exp.c | 309 ++++++++++++++++++++++++++++++++++++++ > lib/rsa/rsa-verify.c | 343 > +++++++++---------------------------------- > tools/Makefile | 3 +- > 5 files changed, 429 insertions(+), 277 deletions(-) > create mode 100644 include/u-boot/rsa-mod-exp.h > create mode 100644 lib/rsa/rsa-mod-exp.c > > diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h > new file mode 100644 > index 0000000..7b74f3c > --- /dev/null > +++ b/include/u-boot/rsa-mod-exp.h > @@ -0,0 +1,49 @@ > +/* > + * Copyright (c) 2014, Ruchika Gupta. > + * > + * SPDX-License-Identifier: GPL-2.0+ > +*/ > + > +#ifndef _RSA_MOD_EXP_H > +#define _RSA_MOD_EXP_H > + > +#include <errno.h> > +#include <image.h> > + > +/** > + * struct key_prop - holder for a public key properties > + * > + * The struct has pointers to modulus (Typically called N), > + * The inverse, R^2, exponent. These can be typecasted and > + * used as byte arrays or converted to the required format > + * as per requirement of RSA implementation. > + */ > +struct key_prop { > + const void *rr; /* R^2 can be treated as byte array */ > + const void *modulus; /* modulus as byte array */ > + const void *public_exponent; /* public exponent as byte array */ > + uint32_t n0inv; /* -1 / modulus[0] mod 2^32 */ > + int num_bits; /* Key length in bits */ > + uint32_t exp_len; /* Exponent length in number of uint8_t */ > +}; > + > +/** > + * rsa_mod_exp_sw() - Perform RSA Modular Exponentiation in sw > + * > + * Operation: result[] = sig ^ exponent % modulus > + * > + * @sig: RSA PKCS1.5 signature > + * @sig_len: Length of signature in number of bytes > + * @node: Node with RSA key elements like modulus, exponent, R^2, n0inv > + * @outp: Set to an allocated buffer holding the output hash > + * @out_len: Set to length of hash(outp) calculated after exponentiation > + * > + * This computes exponentiation over the signature. Resulting hash value is > + * placed in an allocated buffer, the pointer is returned as *outp. The > + * length of calulated hash is returned via the out_len pointer argument. The > + * caller should free *outp > + */ > +int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, > + struct key_prop *node, uint8_t **outp, uint32_t *out_len); > + > +#endif > diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile > index a5a96cb6..cc25b3c 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 rsa-checksum.o > +obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o rsa-mod-exp.o > diff --git a/lib/rsa/rsa-mod-exp.c b/lib/rsa/rsa-mod-exp.c > new file mode 100644 > index 0000000..af01b74 > --- /dev/null > +++ b/lib/rsa/rsa-mod-exp.c > @@ -0,0 +1,309 @@ > +/* > + * Copyright (c) 2013, Google Inc. > + * > + * SPDX-License-Identifier: GPL-2.0+ > + */ > + > +#ifndef USE_HOSTCC > +#include <common.h> > +#include <fdtdec.h> > +#include <asm/types.h> > +#include <asm/byteorder.h> > +#include <asm/errno.h> > +#include <asm/types.h> > +#include <asm/unaligned.h> > +#else > +#include "fdt_host.h" > +#include "mkimage.h" > +#include <fdt_support.h> > +#endif > +#include <malloc.h> > +#include <u-boot/rsa.h> > +#include <u-boot/rsa-mod-exp.h> > + > +#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby))) > + > +#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a) > +#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a)) > + > +/* Default public exponent for backward compatibility */ > +#define RSA_DEFAULT_PUBEXP 65537 > + > +/** > + * subtract_modulus() - subtract modulus from the given value > + * > + * @key: Key containing modulus to subtract > + * @num: Number to subtract modulus from, as little endian word array > + */ > +static void subtract_modulus(const struct rsa_public_key *key, uint32_t > num[]) > +{ > + int64_t acc = 0; > + uint i; > + > + for (i = 0; i < key->len; i++) { > + acc += (uint64_t)num[i] - key->modulus[i]; > + num[i] = (uint32_t)acc; > + acc >>= 32; > + } > +} > + > +/** > + * greater_equal_modulus() - check if a value is >= modulus > + * > + * @key: Key containing modulus to check > + * @num: Number to check against modulus, as little endian word array > + * @return 0 if num < modulus, 1 if num >= modulus > + */ > +static int greater_equal_modulus(const struct rsa_public_key *key, > + uint32_t num[]) > +{ > + int i; > + > + for (i = (int)key->len - 1; i >= 0; i--) { > + if (num[i] < key->modulus[i]) > + return 0; > + if (num[i] > key->modulus[i]) > + return 1; > + } > + > + return 1; /* equal */ > +} > + > +/** > + * montgomery_mul_add_step() - Perform montgomery multiply-add step > + * > + * Operation: montgomery result[] += a * b[] / n0inv % modulus > + * > + * @key: RSA key > + * @result: Place to put result, as little endian word array > + * @a: Multiplier > + * @b: Multiplicand, as little endian word array > + */ > +static void montgomery_mul_add_step(const struct rsa_public_key *key, > + uint32_t result[], const uint32_t a, const uint32_t b[]) > +{ > + uint64_t acc_a, acc_b; > + uint32_t d0; > + uint i; > + > + acc_a = (uint64_t)a * b[0] + result[0]; > + d0 = (uint32_t)acc_a * key->n0inv; > + acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a; > + for (i = 1; i < key->len; i++) { > + acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i]; > + acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] + > + (uint32_t)acc_a; > + result[i - 1] = (uint32_t)acc_b; > + } > + > + acc_a = (acc_a >> 32) + (acc_b >> 32); > + > + result[i - 1] = (uint32_t)acc_a; > + > + if (acc_a >> 32) > + subtract_modulus(key, result); > +} > + > +/** > + * montgomery_mul() - Perform montgomery mutitply > + * > + * Operation: montgomery result[] = a[] * b[] / n0inv % modulus > + * > + * @key: RSA key > + * @result: Place to put result, as little endian word array > + * @a: Multiplier, as little endian word array > + * @b: Multiplicand, as little endian word array > + */ > +static void montgomery_mul(const struct rsa_public_key *key, > + uint32_t result[], uint32_t a[], const uint32_t b[]) > +{ > + uint i; > + > + for (i = 0; i < key->len; ++i) > + result[i] = 0; > + for (i = 0; i < key->len; ++i) > + montgomery_mul_add_step(key, result, a[i], b); > +} > + > +/** > + * num_pub_exponent_bits() - Number of bits in the public exponent > + * > + * @key: RSA key > + * @num_bits: Storage for the number of public exponent bits > + */ > +static int num_public_exponent_bits(const struct rsa_public_key *key, > + int *num_bits) > +{ > + uint64_t exponent; > + int exponent_bits; > + const uint max_bits = (sizeof(exponent) * 8); > + > + exponent = key->exponent; > + exponent_bits = 0; > + > + if (!exponent) { > + *num_bits = exponent_bits; > + return 0; > + } > + > + for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits) > + if (!(exponent >>= 1)) { > + *num_bits = exponent_bits; > + return 0; > + } > + > + return -EINVAL; > +} > + > +/** > + * is_public_exponent_bit_set() - Check if a bit in the public exponent is > set > + * > + * @key: RSA key > + * @pos: The bit position to check > + */ > +static int is_public_exponent_bit_set(const struct rsa_public_key *key, > + int pos) > +{ > + return key->exponent & (1ULL << pos); > +} > + > +/** > + * pow_mod() - in-place public exponentiation > + * > + * @key: RSA key > + * @inout: Big-endian word array containing value and result > + */ > +static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) > +{ > + uint32_t *result, *ptr; > + uint i; > + int j, k; > + > + /* Sanity check for stack size - key->len is in 32-bit words */ > + if (key->len > RSA_MAX_KEY_BITS / 32) { > + debug("RSA key words %u exceeds maximum %d\n", key->len, > + RSA_MAX_KEY_BITS / 32); > + return -EINVAL; > + } > + > + uint32_t val[key->len], acc[key->len], tmp[key->len]; > + uint32_t a_scaled[key->len]; > + result = tmp; /* Re-use location. */ > + > + /* Convert from big endian byte array to little endian word array. */ > + for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--) > + val[i] = get_unaligned_be32(ptr); > + > + if (0 != num_public_exponent_bits(key, &k)) > + return -EINVAL; > + > + if (k < 2) { > + debug("Public exponent is too short (%d bits, minimum 2)\n", > + k); > + return -EINVAL; > + } > + > + if (!is_public_exponent_bit_set(key, 0)) { > + debug("LSB of RSA public exponent must be set.\n"); > + return -EINVAL; > + } > + > + /* the bit at e[k-1] is 1 by definition, so start with: C := M */ > + montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */ > + /* retain scaled version for intermediate use */ > + memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0])); > + > + for (j = k - 2; j > 0; --j) { > + montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n > */ > + > + if (is_public_exponent_bit_set(key, j)) { > + /* acc = tmp * val / R mod n */ > + montgomery_mul(key, acc, tmp, a_scaled); > + } else { > + /* e[j] == 0, copy tmp back to acc for next operation > */ > + memcpy(acc, tmp, key->len * sizeof(acc[0])); > + } > + } > + > + /* the bit at e[0] is always 1 */ > + montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ > + montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */ > + memcpy(result, acc, key->len * sizeof(result[0])); > + > + /* Make sure result < mod; result is at most 1x mod too large. */ > + if (greater_equal_modulus(key, result)) > + subtract_modulus(key, result); > + > + /* 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; > +} > + > +static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int > len) > +{ > + int i; > + > + for (i = 0; i < len; i++) > + dst[i] = fdt32_to_cpu(src[len - 1 - i]); > +} > + > +int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, > + struct key_prop *prop, uint8_t **out, uint32_t *len) > +{ > + struct rsa_public_key key; > + int ret; > + > + if (!prop) { > + debug("%s: Skipping invalid prop", __func__); > + return -EBADF; > + } > + if (!prop->n0inv) {
Sorry I did not notice this in v3, but you should remove this check. This is a value, not a pointer. > + debug("%s: Missing rsa,n0-inverse", __func__); > + return -EFAULT; > + } > + key.n0inv = prop->n0inv; > + key.len = prop->num_bits; > + > + if (!prop->public_exponent) > + key.exponent = RSA_DEFAULT_PUBEXP; > + else > + key.exponent = > + fdt64_to_cpu(*((uint64_t *)(prop->public_exponent))); > + > + if (!key.len || !prop->modulus || !prop->rr) { > + debug("%s: Missing RSA key info", __func__); > + return -EFAULT; > + } > + > + /* Sanity check for stack size */ > + if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) { > + debug("RSA key bits %u outside allowed range %d..%d\n", > + key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS); > + return -EFAULT; > + } > + key.len /= sizeof(uint32_t) * 8; > + uint32_t key1[key.len], key2[key.len]; > + > + key.modulus = key1; > + key.rr = key2; > + rsa_convert_big_endian(key.modulus, (uint32_t *)prop->modulus, > key.len); > + rsa_convert_big_endian(key.rr, (uint32_t *)prop->rr, key.len); > + if (!key.modulus || !key.rr) { > + debug("%s: Out of memory", __func__); > + return -ENOMEM; > + } > + > + uint32_t *buf = malloc(sig_len); Can you declare buf at the top of the function? Also you need if (!buf) return -ENOMEM; > + > + memcpy(buf, sig, sig_len); > + > + ret = pow_mod(&key, buf); > + if (ret) > + return ret; > + > + *out = (uint8_t *)buf; > + *len = sig_len; If len is the same as sig_len, why do you need this extra parameter? I wonder if I put you wrong somewhere? If sig_len is passed in, there is no need for rsa_mod_exp_sw() to malloc() space - the caller may as well just supply the buffer as now. > + > + return 0; > +} > diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c > index 4ef19b6..1d2e707 100644 > --- a/lib/rsa/rsa-verify.c > +++ b/lib/rsa/rsa-verify.c > @@ -17,230 +17,27 @@ > #include "mkimage.h" > #include <fdt_support.h> > #endif > +#include <malloc.h> > +#include <u-boot/rsa-mod-exp.h> > #include <u-boot/rsa.h> > -#include <u-boot/sha1.h> > -#include <u-boot/sha256.h> > - > -#define UINT64_MULT32(v, multby) (((uint64_t)(v)) * ((uint32_t)(multby))) > - > -#define get_unaligned_be32(a) fdt32_to_cpu(*(uint32_t *)a) > -#define put_unaligned_be32(a, b) (*(uint32_t *)(b) = cpu_to_fdt32(a)) > > /* Default public exponent for backward compatibility */ > #define RSA_DEFAULT_PUBEXP 65537 > > /** > - * subtract_modulus() - subtract modulus from the given value > + * rsa_verify_key() - Verify a signature against some data using RSA Key > * > - * @key: Key containing modulus to subtract > - * @num: Number to subtract modulus from, as little endian word array > - */ > -static void subtract_modulus(const struct rsa_public_key *key, uint32_t > num[]) > -{ > - int64_t acc = 0; > - uint i; > - > - for (i = 0; i < key->len; i++) { > - acc += (uint64_t)num[i] - key->modulus[i]; > - num[i] = (uint32_t)acc; > - acc >>= 32; > - } > -} > - > -/** > - * greater_equal_modulus() - check if a value is >= modulus > + * Verify a RSA PKCS1.5 signature against an expected hash using > + * the RSA Key properties in prop structure. > * > - * @key: Key containing modulus to check > - * @num: Number to check against modulus, as little endian word array > - * @return 0 if num < modulus, 1 if num >= modulus > + * @prop: Specifies key > + * @sig: Signature > + * @sig_len: Number of bytes in signature > + * @hash: Pointer to the expected hash > + * @algo: Checksum algo structure having information on RSA padding etc. > + * @return 0 if verified, -ve on error > */ > -static int greater_equal_modulus(const struct rsa_public_key *key, > - uint32_t num[]) > -{ > - int i; > - > - for (i = (int)key->len - 1; i >= 0; i--) { > - if (num[i] < key->modulus[i]) > - return 0; > - if (num[i] > key->modulus[i]) > - return 1; > - } > - > - return 1; /* equal */ > -} > - > -/** > - * montgomery_mul_add_step() - Perform montgomery multiply-add step > - * > - * Operation: montgomery result[] += a * b[] / n0inv % modulus > - * > - * @key: RSA key > - * @result: Place to put result, as little endian word array > - * @a: Multiplier > - * @b: Multiplicand, as little endian word array > - */ > -static void montgomery_mul_add_step(const struct rsa_public_key *key, > - uint32_t result[], const uint32_t a, const uint32_t b[]) > -{ > - uint64_t acc_a, acc_b; > - uint32_t d0; > - uint i; > - > - acc_a = (uint64_t)a * b[0] + result[0]; > - d0 = (uint32_t)acc_a * key->n0inv; > - acc_b = (uint64_t)d0 * key->modulus[0] + (uint32_t)acc_a; > - for (i = 1; i < key->len; i++) { > - acc_a = (acc_a >> 32) + (uint64_t)a * b[i] + result[i]; > - acc_b = (acc_b >> 32) + (uint64_t)d0 * key->modulus[i] + > - (uint32_t)acc_a; > - result[i - 1] = (uint32_t)acc_b; > - } > - > - acc_a = (acc_a >> 32) + (acc_b >> 32); > - > - result[i - 1] = (uint32_t)acc_a; > - > - if (acc_a >> 32) > - subtract_modulus(key, result); > -} > - > -/** > - * montgomery_mul() - Perform montgomery mutitply > - * > - * Operation: montgomery result[] = a[] * b[] / n0inv % modulus > - * > - * @key: RSA key > - * @result: Place to put result, as little endian word array > - * @a: Multiplier, as little endian word array > - * @b: Multiplicand, as little endian word array > - */ > -static void montgomery_mul(const struct rsa_public_key *key, > - uint32_t result[], uint32_t a[], const uint32_t b[]) > -{ > - uint i; > - > - for (i = 0; i < key->len; ++i) > - result[i] = 0; > - for (i = 0; i < key->len; ++i) > - montgomery_mul_add_step(key, result, a[i], b); > -} > - > -/** > - * num_pub_exponent_bits() - Number of bits in the public exponent > - * > - * @key: RSA key > - * @num_bits: Storage for the number of public exponent bits > - */ > -static int num_public_exponent_bits(const struct rsa_public_key *key, > - int *num_bits) > -{ > - uint64_t exponent; > - int exponent_bits; > - const uint max_bits = (sizeof(exponent) * 8); > - > - exponent = key->exponent; > - exponent_bits = 0; > - > - if (!exponent) { > - *num_bits = exponent_bits; > - return 0; > - } > - > - for (exponent_bits = 1; exponent_bits < max_bits + 1; ++exponent_bits) > - if (!(exponent >>= 1)) { > - *num_bits = exponent_bits; > - return 0; > - } > - > - return -EINVAL; > -} > - > -/** > - * is_public_exponent_bit_set() - Check if a bit in the public exponent is > set > - * > - * @key: RSA key > - * @pos: The bit position to check > - */ > -static int is_public_exponent_bit_set(const struct rsa_public_key *key, > - int pos) > -{ > - return key->exponent & (1ULL << pos); > -} > - > -/** > - * pow_mod() - in-place public exponentiation > - * > - * @key: RSA key > - * @inout: Big-endian word array containing value and result > - */ > -static int pow_mod(const struct rsa_public_key *key, uint32_t *inout) > -{ > - uint32_t *result, *ptr; > - uint i; > - int j, k; > - > - /* Sanity check for stack size - key->len is in 32-bit words */ > - if (key->len > RSA_MAX_KEY_BITS / 32) { > - debug("RSA key words %u exceeds maximum %d\n", key->len, > - RSA_MAX_KEY_BITS / 32); > - return -EINVAL; > - } > - > - uint32_t val[key->len], acc[key->len], tmp[key->len]; > - uint32_t a_scaled[key->len]; > - result = tmp; /* Re-use location. */ > - > - /* Convert from big endian byte array to little endian word array. */ > - for (i = 0, ptr = inout + key->len - 1; i < key->len; i++, ptr--) > - val[i] = get_unaligned_be32(ptr); > - > - if (0 != num_public_exponent_bits(key, &k)) > - return -EINVAL; > - > - if (k < 2) { > - debug("Public exponent is too short (%d bits, minimum 2)\n", > - k); > - return -EINVAL; > - } > - > - if (!is_public_exponent_bit_set(key, 0)) { > - debug("LSB of RSA public exponent must be set.\n"); > - return -EINVAL; > - } > - > - /* the bit at e[k-1] is 1 by definition, so start with: C := M */ > - montgomery_mul(key, acc, val, key->rr); /* acc = a * RR / R mod n */ > - /* retain scaled version for intermediate use */ > - memcpy(a_scaled, acc, key->len * sizeof(a_scaled[0])); > - > - for (j = k - 2; j > 0; --j) { > - montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n > */ > - > - if (is_public_exponent_bit_set(key, j)) { > - /* acc = tmp * val / R mod n */ > - montgomery_mul(key, acc, tmp, a_scaled); > - } else { > - /* e[j] == 0, copy tmp back to acc for next operation > */ > - memcpy(acc, tmp, key->len * sizeof(acc[0])); > - } > - } > - > - /* the bit at e[0] is always 1 */ > - montgomery_mul(key, tmp, acc, acc); /* tmp = acc^2 / R mod n */ > - montgomery_mul(key, acc, tmp, val); /* acc = tmp * a / R mod M */ > - memcpy(result, acc, key->len * sizeof(result[0])); > - > - /* Make sure result < mod; result is at most 1x mod too large. */ > - if (greater_equal_modulus(key, result)) > - subtract_modulus(key, result); > - > - /* 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; > -} > - > -static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t > *sig, > +static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig, > const uint32_t sig_len, const uint8_t *hash, > struct checksum_algo *algo) > { > @@ -248,10 +45,10 @@ static int rsa_verify_key(const struct rsa_public_key > *key, const uint8_t *sig, > int pad_len; > int ret; > > - if (!key || !sig || !hash || !algo) > + if (!prop || !sig || !hash || !algo) > return -EIO; > > - if (sig_len != (key->len * sizeof(uint32_t))) { > + if (sig_len != (prop->num_bits / 8)) { > debug("Signature is of incorrect length %d\n", sig_len); > return -EINVAL; > } > @@ -265,13 +62,20 @@ static int rsa_verify_key(const struct rsa_public_key > *key, const uint8_t *sig, > return -EINVAL; > } > > - uint32_t buf[sig_len / sizeof(uint32_t)]; > + uint8_t *buf; > + uint32_t buf_len; Again please put declarations at the top. As per above comment perhaps you can revert this chunk anyway. (and the next two) > > - memcpy(buf, sig, sig_len); > - > - ret = pow_mod(key, buf); > - if (ret) > + ret = rsa_mod_exp_sw(sig, sig_len, prop, &buf, &buf_len); > + if (ret) { > + debug("Error in Modular exponentation\n"); > return ret; > + } > + > + if (buf_len != sig_len) { > + debug("In RSAVerify(): hash length not same as sig len\n"); > + free(buf); > + return -EINVAL; > + } This check doesn't achieve anything really. If ret == 0, then buf_len == sig_len. > > padding = algo->rsa_padding; > pad_len = algo->pad_len - algo->checksum_len; > @@ -279,84 +83,73 @@ static int rsa_verify_key(const struct rsa_public_key > *key, const uint8_t *sig, > /* Check pkcs1.5 padding bytes. */ > if (memcmp(buf, padding, pad_len)) { > debug("In RSAVerify(): Padding check failed!\n"); > + free(buf); > return -EINVAL; > } > > /* Check hash. */ > - if (memcmp((uint8_t *)buf + pad_len, hash, sig_len - pad_len)) { > + if (memcmp(buf + pad_len, hash, sig_len - pad_len)) { > debug("In RSAVerify(): Hash check failed!\n"); > + free(buf); > return -EACCES; > } > > - return 0; > -} > - > -static void rsa_convert_big_endian(uint32_t *dst, const uint32_t *src, int > len) > -{ > - int i; > + free(buf); > > - for (i = 0; i < len; i++) > - dst[i] = fdt32_to_cpu(src[len - 1 - i]); > + return 0; > } > > +/** > + * rsa_verify_with_keynode() - Verify a signature against some data using > + * information in node with prperties of RSA Key like modulus, exponent etc. > + * > + * Parse sign-node and fill a key_prop structure with properties of the > + * key. Verify a RSA PKCS1.5 signature against an expected hash using > + * the properties parsed > + * > + * @info: Specifies key and FIT information > + * @hash: Pointer to the expected hash > + * @sig: Signature > + * @sig_len: Number of bytes in signature > + * @node: Node having the RSA Key properties > + * @return 0 if verified, -ve on error > + */ > static int rsa_verify_with_keynode(struct image_sign_info *info, > - const void *hash, uint8_t *sig, uint sig_len, int node) > + const void *hash, uint8_t *sig, > + uint sig_len, int node) > { > const void *blob = info->fdt_blob; > - struct rsa_public_key key; > - const void *modulus, *rr; > - const uint64_t *public_exponent; > + struct key_prop prop; > int length; > - int ret; > + int ret = 0; > > if (node < 0) { > debug("%s: Skipping invalid node", __func__); > return -EBADF; > } > - if (!fdt_getprop(blob, node, "rsa,n0-inverse", NULL)) { > - debug("%s: Missing rsa,n0-inverse", __func__); > - return -EFAULT; > - } > - key.len = fdtdec_get_int(blob, node, "rsa,num-bits", 0); > - key.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0); > - public_exponent = fdt_getprop(blob, node, "rsa,exponent", &length); > - if (!public_exponent || length < sizeof(*public_exponent)) > - key.exponent = RSA_DEFAULT_PUBEXP; > - else > - key.exponent = fdt64_to_cpu(*public_exponent); > - modulus = fdt_getprop(blob, node, "rsa,modulus", NULL); > - rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); > - if (!key.len || !modulus || !rr) { > - debug("%s: Missing RSA key info", __func__); > - return -EFAULT; > - } > > - /* Sanity check for stack size */ > - if (key.len > RSA_MAX_KEY_BITS || key.len < RSA_MIN_KEY_BITS) { > - debug("RSA key bits %u outside allowed range %d..%d\n", > - key.len, RSA_MIN_KEY_BITS, RSA_MAX_KEY_BITS); > + prop.num_bits = fdtdec_get_int(blob, node, "rsa,num-bits", 0); > + > + prop.n0inv = fdtdec_get_int(blob, node, "rsa,n0-inverse", 0); > + > + prop.public_exponent = fdt_getprop(blob, node, "rsa,exponent", > &length); > + if (!prop.public_exponent || length < sizeof(uint64_t)) > + prop.public_exponent = NULL; > + > + prop.exp_len = sizeof(uint64_t); > + > + prop.modulus = fdt_getprop(blob, node, "rsa,modulus", NULL); > + > + prop.rr = fdt_getprop(blob, node, "rsa,r-squared", NULL); > + > + if (!prop.num_bits || !prop.modulus) { > + debug("%s: Missing RSA key info", __func__); > return -EFAULT; > } > - key.len /= sizeof(uint32_t) * 8; > - uint32_t key1[key.len], key2[key.len]; > - > - key.modulus = key1; > - key.rr = key2; > - rsa_convert_big_endian(key.modulus, modulus, key.len); > - rsa_convert_big_endian(key.rr, rr, key.len); > - if (!key.modulus || !key.rr) { > - debug("%s: Out of memory", __func__); > - return -ENOMEM; > - } > > - debug("key length %d\n", key.len); > - 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; > - } > + ret = rsa_verify_key(&prop, sig, sig_len, hash, info->algo->checksum); > > - return 0; > + return ret; > } > > int rsa_verify(struct image_sign_info *info, > diff --git a/tools/Makefile b/tools/Makefile > index a4216a1..0b981da 100644 > --- a/tools/Makefile > +++ b/tools/Makefile > @@ -60,7 +60,8 @@ FIT_SIG_OBJS-$(CONFIG_FIT_SIGNATURE) := common/image-sig.o > LIBFDT_OBJS := $(addprefix lib/libfdt/, \ > fdt.o fdt_ro.o fdt_rw.o fdt_strerror.o fdt_wip.o) > RSA_OBJS-$(CONFIG_FIT_SIGNATURE) := $(addprefix lib/rsa/, \ > - rsa-sign.o rsa-verify.o > rsa-checksum.o) > + rsa-sign.o rsa-verify.o > rsa-checksum.o \ > + rsa-mod-exp.o) > > # common objs for dumpimage and mkimage > dumpimage-mkimage-objs := aisimage.o \ > -- > 1.8.1.4 > Regards, Simon _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot