[U-Boot] [PATCH 1/4] [RFC] rsa: Split the rsa-verify

Simon Glass sjg at chromium.org
Wed Dec 17 22:46:45 CET 2014


Hi Ruchika,

On 17 December 2014 at 03:05, Ruchika Gupta <ruchika.gupta at freescale.com> wrote:
> Public exponentiation which is required in rsa verify
> functionality is currently tightly integrated with
> verification code in rsa_verify.c. Currently this
> implementation is software based. Some platforms
> having support of the exponentiation in hardware.
> To enable the rsa verify functionality to use the
> Modular exponentiation if present in hardware, the
> patch-set splits the file into two files:
>
> 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 formal (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 exponentiation
> from rsa-verify.c to this file. The file is compiled if
> "CONFIG_RSA_MOD_EXP_SW" is defined. In general if both
> CONFIG_FIT_SIGNATURE and CONFIG_RSA are defined,
> CONFIG_RSA_MOD_EXP_SW gets automatically defined.
>
> Platforms having hardware implementation for rsa_mod_exp can
> add a define "CONFIG_RSA_MOD_EXP_HW" to their config files.
> Adding this defined, undefs the CONFIG_RSA_MOD_EXP_SW and
> hardware implementation of mod_exp gets compiled.
>
> Signed-off-by: Ruchika Gupta <ruchika.gupta at freescale.com>
> CC: Simon Glass <sjg at chromium.org>

I'm going to mostly limit my comments to high level things for this
RFC. It's a good idea.

Can you add a patch to move existing RSA CONFIGs to Kconfig, and then
use Kconfig for your new options. Then I think your ...EXP_HW and
...EXP_SW become an choice:

1. Software RSA
2. Freescale xxx chip hardware RSA
3. Some other RSA implementation

With my driver model hat on, there really should be a uclass for an
exponentiation implementation and an interface that these drivers
implement. Since you already have an interface, that should be easy.

I'm not sure about the structures you mention above, but potentially
you can have a the driver-specific structure and a uclass structure.
The device tree would parse to the latter perhaps.

> ---
>  include/config_fallbacks.h   |   5 +
>  include/u-boot/rsa-mod-exp.h |  25 ++++
>  lib/rsa/Makefile             |   1 +
>  lib/rsa/rsa-mod-exp.c        | 308 +++++++++++++++++++++++++++++++++++++++++++
>  lib/rsa/rsa-verify.c         | 307 +++++-------------------------------------
>  tools/Makefile               |   2 +-
>  6 files changed, 370 insertions(+), 278 deletions(-)
>  create mode 100644 include/u-boot/rsa-mod-exp.h
>  create mode 100644 lib/rsa/rsa-mod-exp.c
>
> diff --git a/include/config_fallbacks.h b/include/config_fallbacks.h
> index ddfe045..d4676b4 100644
> --- a/include/config_fallbacks.h
> +++ b/include/config_fallbacks.h
> @@ -83,6 +83,11 @@
>  #define CONFIG_SYS_PBSIZE      (CONFIG_SYS_CBSIZE + 128)
>  #endif
>
> +#if defined(CONFIG_FIT_SIGNATURE) && defined(CONFIG_RSA) && \
> +               !defined(CONFIG_RSA_MOD_EXP_HW)
> +#define CONFIG_RSA_MOD_EXP_SW
> +#endif

As above you shouldn't need this

> +
>  #ifndef CONFIG_FIT_SIGNATURE
>  #define CONFIG_IMAGE_FORMAT_LEGACY
>  #endif
> diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h
> new file mode 100644
> index 0000000..577f673
> --- /dev/null
> +++ b/include/u-boot/rsa-mod-exp.h
> @@ -0,0 +1,25 @@
> +/*
> + * 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>

Comments here

> +
> +struct key_prop {
> +       const void *rr;
> +       const void *modulus;
> +       const void *public_exponent;
> +       uint32_t n0inv;
> +       int num_bits;
> +       uint32_t exp_len;
> +};
> +
> +int rsa_mod_exp(const uint8_t *sig, uint32_t sig_len,
> +               struct key_prop *node, uint8_t *out);
> +
> +#endif
> diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
> index a5a96cb6..ccc6060 100644
> --- a/lib/rsa/Makefile
> +++ b/lib/rsa/Makefile
> @@ -8,3 +8,4 @@
>  #
>
>  obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
> +obj-$(CONFIG_RSA_MOD_EXP_SW) += 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..f69ae1b
> --- /dev/null
> +++ b/lib/rsa/rsa-mod-exp.c
> @@ -0,0 +1,308 @@
> +/*
> + * 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 <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;
> +       }
> +}

I'm not quite sure what is happening here, but can you please first
move the code and then in a separate patch, change it. Maybe I am
missing something here, sorry if so.

> +
> +/**
> + * 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(const uint8_t *sig, uint32_t sig_len,
> +               struct key_prop *prop, uint8_t *out)
> +{
> +       struct rsa_public_key key;
> +       int ret;
> +
> +       if (!prop) {
> +               debug("%s: Skipping invalid prop", __func__);
> +               return -EBADF;
> +       }
> +       if (!prop->n0inv) {
> +               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[sig_len / sizeof(uint32_t)];
> +
> +       memcpy(buf, sig, sig_len);
> +
> +       ret = pow_mod(&key, buf);
> +       if (ret)
> +               return ret;
> +
> +       memcpy(out, buf, sig_len);
> +
> +       return 0;
> +}
> diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
> index 4ef19b6..583400f 100644
> --- a/lib/rsa/rsa-verify.c
> +++ b/lib/rsa/rsa-verify.c
> @@ -17,230 +17,13 @@
>  #include "mkimage.h"
>  #include <fdt_support.h>
>  #endif
> +#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
> - *
> - * @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 int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
> +static int rsa_verify_key(struct key_prop *node, const uint8_t *sig,
>                           const uint32_t sig_len, const uint8_t *hash,
>                           struct checksum_algo *algo)
>  {
> @@ -248,10 +31,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 (!node || !sig || !hash || !algo)
>                 return -EIO;
>
> -       if (sig_len != (key->len * sizeof(uint32_t))) {
> +       if (sig_len != (node->num_bits / 8)) {
>                 debug("Signature is of incorrect length %d\n", sig_len);
>                 return -EINVAL;
>         }
> @@ -265,13 +48,13 @@ 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)];
> -
> -       memcpy(buf, sig, sig_len);
> +       uint8_t buf[sig_len];
>
> -       ret = pow_mod(key, buf);
> -       if (ret)
> +       ret = rsa_mod_exp(sig, sig_len, node, buf);
> +       if (ret) {
> +               debug("Error in Modular exponentation\n");
>                 return ret;
> +       }
>
>         padding = algo->rsa_padding;
>         pad_len = algo->pad_len - algo->checksum_len;
> @@ -291,72 +74,42 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
>         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]);
> -}
> -
>  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;
>
>         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;
> -       }
> +       rsa_verify_key(&prop, sig, sig_len, hash, info->algo->checksum);
>
>         return 0;
> +
>  }
>
>  int rsa_verify(struct image_sign_info *info,
> diff --git a/tools/Makefile b/tools/Makefile
> index a4216a1..f67cd15 100644
> --- a/tools/Makefile
> +++ b/tools/Makefile
> @@ -60,7 +60,7 @@ 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


More information about the U-Boot mailing list