rsa: Split the rsa-verify to separate the modular exponentiation
authorRuchika Gupta <ruchika.gupta@freescale.com>
Fri, 23 Jan 2015 10:31:50 +0000 (16:01 +0530)
committerSimon Glass <sjg@chromium.org>
Fri, 30 Jan 2015 00:09:58 +0000 (17:09 -0700)
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.gupta@freescale.com>
CC: Simon Glass <sjg@chromium.org>
Acked-by: Simon Glass <sjg@chromium.org>
include/u-boot/rsa-mod-exp.h [new file with mode: 0644]
lib/rsa/Makefile
lib/rsa/rsa-mod-exp.c [new file with mode: 0644]
lib/rsa/rsa-verify.c
tools/Makefile

diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h
new file mode 100644 (file)
index 0000000..59cd9ea
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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: out[] = 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
+ * @out:       Result in form of byte array
+ */
+int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len,
+               struct key_prop *node, uint8_t *out);
+
+#endif
index a5a96cb680d16d1cea1f88375f2ca1ec7bfc1776..cc25b3ce6d9232c60ff0b848632265b8a2788626 100644 (file)
@@ -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 (file)
index 0000000..4a6de2b
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ * 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;
+       }
+}
+
+/**
+ * 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)
+{
+       struct rsa_public_key key;
+       int ret;
+
+       if (!prop) {
+               debug("%s: Skipping invalid prop", __func__);
+               return -EBADF;
+       }
+       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;
+}
index 4ef19b66f4b12588f2bbe0a978500a0718177336..f8bc086fd77c0a7049795f864be82b6bcf95b53d 100644 (file)
 #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
+ * rsa_verify_key() - Verify a signature against some data using RSA Key
  *
- * @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
+ * Verify a RSA PKCS1.5 signature against an expected hash using
+ * the RSA Key properties in prop structure.
  *
- * @key:       RSA key
- * @inout:     Big-endian word array containing value and result
+ * @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 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 +44,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 +61,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_sw(sig, sig_len, prop, 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 +87,57 @@ 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]);
-}
-
+/**
+ * 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,
index e549f8e63c9cbe0b1066a659efb16bd641601601..46b90b2861d46fe4e5db4cd6f31e0a550c798448 100644 (file)
@@ -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 \