[U-Boot] [PATCH 0/9] [v3] rsa: Modify rsa lib to use hw acceleration

The rsa-verify functionality is a two step operation involving: 1. Checksum (hash) Calculation over image regions 2. Public Key Modular exponentiation over signature to generate hash
The following patch set modifies the rsa library to use hw acceleration if available in platform.
The first two patches in the series, split the rsa-verify lib into two files: 1. rsa-verify.c Does Verification
2. rsa-mod-exp.c Does Modular Exponentiation
Driver Model is added for RSA Modular Exponentiation.
The patch set also has patches are related with hash lib support in RSA.
For hash, the infrastructure already exists in common/hash.c. rsa_checksum is modified to use the API's registered with the hash_algo structure. Once HW accelerated support for progressive hash is available, RSA library can easily pick it up.
Ruchika Gupta (9): rsa: Split the rsa-verify to separate the modular exponentiation FIT: Modify option FIT_SIGNATURE in Kconfig DM: crypto/rsa: Add rsa Modular Exponentiation DM driver configs: Move CONFIG_FIT_SIGNATURE to defconfig lib/rsa: Modify rsa to use DM driver if available DM: crypto/fsl - Add Freescale rsa DM driver lib/rsa: Add Kconfig option for HW accelerated RSA hash: Add function to find hash_algo struct with progressive hash rsa: Use checksum algorithms from struct hash_algo
Changes in v3: Simon's comments incoprorated. - Driver Model added for RSA Modular Exponentiation - Other cosmetic changes like multiline comments etc incoporated - CONFIG_FIT_SIGNATURE moved to defconfig file for the boards using it
I have tested it's compilation on sandbox platform. However, I don't have the sandbox board available with me to test it. The patches have been tested on freescale platform LS1020 with all the configs and tests available in test/vboot. The tests have been done with both RSA_HW as well as RSA_SW driver.
Changes in v2: Kconfig option introduced
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Kconfig | 3 +- common/hash.c | 33 +++- common/image-sig.c | 6 +- configs/ids8313_defconfig | 2 + configs/sandbox_defconfig | 3 + configs/zynq_microzed_defconfig | 3 + configs/zynq_zc70x_defconfig | 3 + configs/zynq_zc770_xm010_defconfig | 3 + configs/zynq_zc770_xm012_defconfig | 3 + configs/zynq_zc770_xm013_defconfig | 3 + configs/zynq_zed_defconfig | 3 + configs/zynq_zybo_defconfig | 3 + drivers/crypto/Kconfig | 3 + drivers/crypto/Makefile | 1 + drivers/crypto/fsl/Kconfig | 6 + drivers/crypto/fsl/Makefile | 1 + drivers/crypto/fsl/fsl_rsa.c | 62 +++++++ drivers/crypto/fsl/jobdesc.c | 28 +++ drivers/crypto/fsl/jobdesc.h | 5 + drivers/crypto/fsl/rsa_caam.h | 27 +++ drivers/crypto/rsa/Kconfig | 5 + drivers/crypto/rsa/Makefile | 8 + drivers/crypto/rsa/rsa_sw.c | 39 ++++ drivers/crypto/rsa/rsa_uclass.c | 32 ++++ include/configs/am335x_evm.h | 5 +- include/configs/ids8313.h | 3 - include/configs/sandbox.h | 3 - include/configs/zynq-common.h | 6 - include/dm/uclass-id.h | 1 + include/hash.h | 15 ++ include/image.h | 5 +- include/u-boot/rsa-checksum.h | 7 +- include/u-boot/rsa-mod-exp.h | 83 +++++++++ lib/Kconfig | 2 + lib/rsa/Kconfig | 52 ++++++ lib/rsa/Makefile | 1 + lib/rsa/rsa-checksum.c | 53 +++++- lib/rsa/rsa-mod-exp.c | 307 ++++++++++++++++++++++++++++++++ lib/rsa/rsa-verify.c | 354 +++++++++---------------------------- tools/Makefile | 3 +- 40 files changed, 872 insertions(+), 313 deletions(-) create mode 100644 drivers/crypto/fsl/Kconfig create mode 100644 drivers/crypto/fsl/fsl_rsa.c create mode 100644 drivers/crypto/fsl/rsa_caam.h create mode 100644 drivers/crypto/rsa/Kconfig create mode 100644 drivers/crypto/rsa/Makefile create mode 100644 drivers/crypto/rsa/rsa_sw.c create mode 100644 drivers/crypto/rsa/rsa_uclass.c create mode 100644 include/u-boot/rsa-mod-exp.h create mode 100644 lib/rsa/Kconfig create mode 100644 lib/rsa/rsa-mod-exp.c

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 --- 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 | 43 ++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-mod-exp.c | 307 ++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-verify.c | 329 ++++++++----------------------------------- tools/Makefile | 3 +- 5 files changed, 408 insertions(+), 276 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..59cd9ea --- /dev/null +++ b/include/u-boot/rsa-mod-exp.h @@ -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 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..7a9b222 --- /dev/null +++ b/lib/rsa/rsa-mod-exp.c @@ -0,0 +1,307 @@ +/* + * 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; + } + 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..f8bc086 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -17,230 +17,26 @@ #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, 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 \

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@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.
- 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.
- 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
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 | 43 ++++++ lib/rsa/Makefile | 2 +- lib/rsa/rsa-mod-exp.c | 307 ++++++++++++++++++++++++++++++++++++++++ lib/rsa/rsa-verify.c | 329 ++++++++----------------------------------- tools/Makefile | 3 +- 5 files changed, 408 insertions(+), 276 deletions(-) create mode 100644 include/u-boot/rsa-mod-exp.h create mode 100644 lib/rsa/rsa-mod-exp.c
Acked-by: Simon Glass sjg@chromium.org

For FIT signature based approach to work, RSA library needs to be selected. The FIT_SIGNATURE option in Kconfig is modified to automatically select RSA. Selecting RSA compiles the RSA library required for image verification.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: New patch created for adding Kconfig option for FIT signature
Kconfig | 3 ++- lib/Kconfig | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Kconfig b/Kconfig index 153ee2b..c2d7cb9 100644 --- a/Kconfig +++ b/Kconfig @@ -116,8 +116,9 @@ config FIT_VERBOSE depends on FIT
config FIT_SIGNATURE - bool "Enabel signature verification of FIT uImages" + bool "Enable signature verification of FIT uImages" depends on FIT + select RSA help This option enables signature verification of FIT uImages, using a hash signed and verified using RSA. diff --git a/lib/Kconfig b/lib/Kconfig index 8460439..602dd37 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -27,4 +27,10 @@ config SYS_HZ get_timer() must operate in milliseconds and this option must be set to 1000.
+config RSA + bool "Use RSA Library" + help + RSA support.This enables the RSA algorithm used for FIT image + verification in U-Boot. + endmenu

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
For FIT signature based approach to work, RSA library needs to be selected. The FIT_SIGNATURE option in Kconfig is modified to automatically select RSA. Selecting RSA compiles the RSA library required for image verification.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Reviewed-by: Simon Glass sjg@chromium.org
One nit below.
Changes in v3: New patch created for adding Kconfig option for FIT signature
Kconfig | 3 ++- lib/Kconfig | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/Kconfig b/Kconfig index 153ee2b..c2d7cb9 100644 --- a/Kconfig +++ b/Kconfig @@ -116,8 +116,9 @@ config FIT_VERBOSE depends on FIT
config FIT_SIGNATURE
bool "Enabel signature verification of FIT uImages"
bool "Enable signature verification of FIT uImages" depends on FIT
select RSA help This option enables signature verification of FIT uImages, using a hash signed and verified using RSA.
diff --git a/lib/Kconfig b/lib/Kconfig index 8460439..602dd37 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -27,4 +27,10 @@ config SYS_HZ get_timer() must operate in milliseconds and this option must be set to 1000.
+config RSA
bool "Use RSA Library"
help
RSA support.This enables the RSA algorithm used for FIT image
verification in U-Boot.
Please expand this a bit - you can point to the documentation for example.
Regards, Simon

Add a new rsa uclass for performing modular exponentiation and implement the software driver basing on this uclass.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: New patch with driver model for RSA UCLASS
drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + drivers/crypto/rsa/Kconfig | 5 +++++ drivers/crypto/rsa/Makefile | 8 ++++++++ drivers/crypto/rsa/rsa_sw.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/crypto/rsa/rsa_uclass.c | 31 +++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/u-boot/rsa-mod-exp.h | 40 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 126 insertions(+) create mode 100644 drivers/crypto/rsa/Kconfig create mode 100644 drivers/crypto/rsa/Makefile create mode 100644 drivers/crypto/rsa/rsa_sw.c create mode 100644 drivers/crypto/rsa/rsa_uclass.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index e69de29..75f3479 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -0,0 +1 @@ +source drivers/crypto/rsa/Kconfig diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 7b79237..a2f30fc 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -6,4 +6,5 @@ #
obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o +obj-y += rsa/ obj-y += fsl/ diff --git a/drivers/crypto/rsa/Kconfig b/drivers/crypto/rsa/Kconfig new file mode 100644 index 0000000..7eb90a1 --- /dev/null +++ b/drivers/crypto/rsa/Kconfig @@ -0,0 +1,5 @@ +config DM_RSA + bool "Enable Driver Model for RSA " + depends on DM + help + If you want to use driver model for RSA Modular Exponentiation, say Y. diff --git a/drivers/crypto/rsa/Makefile b/drivers/crypto/rsa/Makefile new file mode 100644 index 0000000..fae4f8c --- /dev/null +++ b/drivers/crypto/rsa/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-$(CONFIG_DM_RSA) += rsa_uclass.o +obj-$(CONFIG_RSA_SW) += rsa_sw.o diff --git a/drivers/crypto/rsa/rsa_sw.c b/drivers/crypto/rsa/rsa_sw.c new file mode 100644 index 0000000..5d94754 --- /dev/null +++ b/drivers/crypto/rsa/rsa_sw.c @@ -0,0 +1,39 @@ +/* + * (C) Copyright 2014 Freescale Semiconductor, Inc. + * Author: Ruchika Gupta ruchika.gupta@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <dm.h> +#include <u-boot/rsa-mod-exp.h> + +int mod_exp_sw(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, + struct key_prop *prop, uint8_t *out) +{ + int ret = 0; + + ret = rsa_mod_exp_sw(sig, sig_len, prop, out); + + if (ret) { + debug("%s: RSA failed to verify: %d\n", __func__, ret); + return ret; + } + return 0; +} + +static const struct rsa_ops rsa_ops_sw = { + .get_mod_exp = mod_exp_sw, +}; + +U_BOOT_DRIVER(fsl_rsa) = { + .name = "rsa_sw", + .id = UCLASS_RSA, + .ops = &rsa_ops_sw, +}; + +U_BOOT_DEVICE(rsa_sw) = { + .name = "rsa_sw", +}; diff --git a/drivers/crypto/rsa/rsa_uclass.c b/drivers/crypto/rsa/rsa_uclass.c new file mode 100644 index 0000000..f4f4f39 --- /dev/null +++ b/drivers/crypto/rsa/rsa_uclass.c @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2014 Freescale Semiconductor, Inc + * Author: Ruchika Gupta ruchika.gupta@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <dm.h> +#include <u-boot/rsa-mod-exp.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/io.h> +#include <linux/list.h> + +int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, + struct key_prop *node, uint8_t *out) +{ + const struct rsa_ops *ops = device_get_ops(dev); + + if (!ops->get_mod_exp) + return -ENOSYS; + + return ops->get_mod_exp(dev, sig, sig_len, node, out); +} + +UCLASS_DRIVER(rsa) = { + .id = UCLASS_RSA, + .name = "rsa", +}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index f17c3c2..659369e 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -33,6 +33,7 @@ enum uclass_id { UCLASS_I2C, /* I2C bus */ UCLASS_I2C_GENERIC, /* Generic I2C device */ UCLASS_I2C_EEPROM, /* I2C EEPROM device */ + UCLASS_RSA , /* RSA Mod Exp device */
UCLASS_COUNT, UCLASS_INVALID = -1, diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h index 59cd9ea..7f7e196 100644 --- a/include/u-boot/rsa-mod-exp.h +++ b/include/u-boot/rsa-mod-exp.h @@ -40,4 +40,44 @@ struct key_prop { int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, struct key_prop *node, uint8_t *out);
+/** + * rsa_mod_exp - Perform RSA Modular Exponentiation + * + * Operation: out[] = sig ^ exponent % modulus + * + * @udev: RSA Device + * @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(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, + struct key_prop *node, uint8_t *out); + +/** + * struct struct rsa_ops - Driver model for RSA operations + * + * The uclass interface is implemented by all crypto devices which use + * driver model. + */ +struct rsa_ops { + /** + * Perform Modular Exponentiation + * + * Operation: out[] = sig ^ exponent % modulus + * + * @dev: RSA Device + * @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 + * Returns: 0 if exponentiation is succesful, or a negative value + * if it wasn't. + */ + int (*get_mod_exp)(struct udevice *dev, const uint8_t *sig, + uint32_t sig_len, struct key_prop *node, + uint8_t *out); +}; + #endif

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Add a new rsa uclass for performing modular exponentiation and implement the software driver basing on this uclass.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: New patch with driver model for RSA UCLASS
drivers/crypto/Kconfig | 1 + drivers/crypto/Makefile | 1 + drivers/crypto/rsa/Kconfig | 5 +++++ drivers/crypto/rsa/Makefile | 8 ++++++++ drivers/crypto/rsa/rsa_sw.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/crypto/rsa/rsa_uclass.c | 31 +++++++++++++++++++++++++++++++ include/dm/uclass-id.h | 1 + include/u-boot/rsa-mod-exp.h | 40 ++++++++++++++++++++++++++++++++++++++++ 8 files changed, 126 insertions(+) create mode 100644 drivers/crypto/rsa/Kconfig create mode 100644 drivers/crypto/rsa/Makefile create mode 100644 drivers/crypto/rsa/rsa_sw.c create mode 100644 drivers/crypto/rsa/rsa_uclass.c
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index e69de29..75f3479 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -0,0 +1 @@ +source drivers/crypto/rsa/Kconfig diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 7b79237..a2f30fc 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -6,4 +6,5 @@ #
obj-$(CONFIG_EXYNOS_ACE_SHA) += ace_sha.o +obj-y += rsa/ obj-y += fsl/ diff --git a/drivers/crypto/rsa/Kconfig b/drivers/crypto/rsa/Kconfig new file mode 100644 index 0000000..7eb90a1 --- /dev/null +++ b/drivers/crypto/rsa/Kconfig @@ -0,0 +1,5 @@ +config DM_RSA
bool "Enable Driver Model for RSA "
depends on DM
help
If you want to use driver model for RSA Modular Exponentiation, say Y.
Can you send a new patch (later if you prefer) which removes this option altogether? It should be the default. In other words, RSA should always use driver model.
diff --git a/drivers/crypto/rsa/Makefile b/drivers/crypto/rsa/Makefile new file mode 100644 index 0000000..fae4f8c --- /dev/null +++ b/drivers/crypto/rsa/Makefile @@ -0,0 +1,8 @@ +# +# (C) Copyright 2014 Freescale Semiconductor, Inc. +# +# SPDX-License-Identifier: GPL-2.0+ +#
+obj-$(CONFIG_DM_RSA) += rsa_uclass.o +obj-$(CONFIG_RSA_SW) += rsa_sw.o diff --git a/drivers/crypto/rsa/rsa_sw.c b/drivers/crypto/rsa/rsa_sw.c new file mode 100644 index 0000000..5d94754 --- /dev/null +++ b/drivers/crypto/rsa/rsa_sw.c @@ -0,0 +1,39 @@ +/*
- (C) Copyright 2014 Freescale Semiconductor, Inc.
- Author: Ruchika Gupta ruchika.gupta@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <config.h> +#include <common.h> +#include <dm.h> +#include <u-boot/rsa-mod-exp.h>
+int mod_exp_sw(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
struct key_prop *prop, uint8_t *out)
+{
int ret = 0;
ret = rsa_mod_exp_sw(sig, sig_len, prop, out);
if (ret) {
debug("%s: RSA failed to verify: %d\n", __func__, ret);
return ret;
}
return 0;
+}
+static const struct rsa_ops rsa_ops_sw = {
.get_mod_exp = mod_exp_sw,
+};
+U_BOOT_DRIVER(fsl_rsa) = {
.name = "rsa_sw",
.id = UCLASS_RSA,
.ops = &rsa_ops_sw,
+};
+U_BOOT_DEVICE(rsa_sw) = {
.name = "rsa_sw",
+}; diff --git a/drivers/crypto/rsa/rsa_uclass.c b/drivers/crypto/rsa/rsa_uclass.c new file mode 100644 index 0000000..f4f4f39 --- /dev/null +++ b/drivers/crypto/rsa/rsa_uclass.c @@ -0,0 +1,31 @@ +/*
- (C) Copyright 2014 Freescale Semiconductor, Inc
- Author: Ruchika Gupta ruchika.gupta@freescale.com
- SPDX-License-Identifier: GPL-2.0+
- */
+#include <common.h> +#include <dm.h> +#include <u-boot/rsa-mod-exp.h> +#include <errno.h> +#include <fdtdec.h> +#include <malloc.h> +#include <asm/io.h> +#include <linux/list.h>
+int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
struct key_prop *node, uint8_t *out)
+{
const struct rsa_ops *ops = device_get_ops(dev);
if (!ops->get_mod_exp)
return -ENOSYS;
return ops->get_mod_exp(dev, sig, sig_len, node, out);
+}
+UCLASS_DRIVER(rsa) = {
.id = UCLASS_RSA,
.name = "rsa",
+}; diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index f17c3c2..659369e 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -33,6 +33,7 @@ enum uclass_id { UCLASS_I2C, /* I2C bus */ UCLASS_I2C_GENERIC, /* Generic I2C device */ UCLASS_I2C_EEPROM, /* I2C EEPROM device */
UCLASS_RSA , /* RSA Mod Exp device */
Funny spacing here.
UCLASS_COUNT, UCLASS_INVALID = -1,
diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h index 59cd9ea..7f7e196 100644 --- a/include/u-boot/rsa-mod-exp.h +++ b/include/u-boot/rsa-mod-exp.h @@ -40,4 +40,44 @@ struct key_prop { int rsa_mod_exp_sw(const uint8_t *sig, uint32_t sig_len, struct key_prop *node, uint8_t *out);
+/**
- rsa_mod_exp - Perform RSA Modular Exponentiation
- Operation: out[] = sig ^ exponent % modulus
- @udev: RSA Device
- @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
How big is this array?
- */
+int rsa_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len,
struct key_prop *node, uint8_t *out);
+/**
- struct struct rsa_ops - Driver model for RSA operations
- The uclass interface is implemented by all crypto devices which use
- driver model.
- */
+struct rsa_ops {
/**
* Perform Modular Exponentiation
*
* Operation: out[] = sig ^ exponent % modulus
*
* @dev: RSA Device
* @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
How big is this array?
* Returns: 0 if exponentiation is succesful, or a negative value
successful
* if it wasn't.
*/
int (*get_mod_exp)(struct udevice *dev, const uint8_t *sig,
mod_exp() is better I think, since it matches your function above.
uint32_t sig_len, struct key_prop *node,
uint8_t *out);
+};
#endif
1.8.1.4
Regards, Simon

For the platforms which use,CONFIG_FIT_SIGNATURE, the required configs are moved to the platform's defconfig file. Selecting CONFIG_FIT_SIGNATURE using defconfig automatically resolves the dependencies for signature verification. The RSA library gets automatically selected and user does not have to define CONFIG_RSA manually.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: New patch
configs/ids8313_defconfig | 2 ++ configs/sandbox_defconfig | 3 +++ configs/zynq_microzed_defconfig | 3 +++ configs/zynq_zc70x_defconfig | 3 +++ configs/zynq_zc770_xm010_defconfig | 3 +++ configs/zynq_zc770_xm012_defconfig | 3 +++ configs/zynq_zc770_xm013_defconfig | 3 +++ configs/zynq_zed_defconfig | 3 +++ configs/zynq_zybo_defconfig | 3 +++ include/configs/am335x_evm.h | 4 ++-- include/configs/ids8313.h | 3 --- include/configs/sandbox.h | 3 --- include/configs/zynq-common.h | 6 ------ 13 files changed, 28 insertions(+), 14 deletions(-)
diff --git a/configs/ids8313_defconfig b/configs/ids8313_defconfig index 1c665aa..8479cd4 100644 --- a/configs/ids8313_defconfig +++ b/configs/ids8313_defconfig @@ -1,4 +1,6 @@ CONFIG_SYS_EXTRA_OPTIONS="SYS_TEXT_BASE=0xFFF00000" CONFIG_PPC=y CONFIG_MPC83xx=y +CONFIG_FIT=y +CONFIG_FIT_SIGNATURE=y CONFIG_TARGET_IDS8313=y diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index 47d8400..0111f25 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -1,3 +1,6 @@ CONFIG_OF_CONTROL=y CONFIG_OF_HOSTFILE=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y CONFIG_DEFAULT_DEVICE_TREE="sandbox" diff --git a/configs/zynq_microzed_defconfig b/configs/zynq_microzed_defconfig index 9588849..b9a6fe5 100644 --- a/configs/zynq_microzed_defconfig +++ b/configs/zynq_microzed_defconfig @@ -3,4 +3,7 @@ CONFIG_SPL=y +S:CONFIG_ZYNQ=y +S:CONFIG_TARGET_ZYNQ_MICROZED=y CONFIG_OF_CONTROL=y +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y CONFIG_DEFAULT_DEVICE_TREE="zynq-microzed" diff --git a/configs/zynq_zc70x_defconfig b/configs/zynq_zc70x_defconfig index cf50730..dc8aa84 100644 --- a/configs/zynq_zc70x_defconfig +++ b/configs/zynq_zc70x_defconfig @@ -4,3 +4,6 @@ CONFIG_SPL=y +S:CONFIG_TARGET_ZYNQ_ZC70X=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc702" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/configs/zynq_zc770_xm010_defconfig b/configs/zynq_zc770_xm010_defconfig index 8bb405d..2f5fa8c 100644 --- a/configs/zynq_zc770_xm010_defconfig +++ b/configs/zynq_zc770_xm010_defconfig @@ -5,3 +5,6 @@ CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM010" +S:CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm010" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/configs/zynq_zc770_xm012_defconfig b/configs/zynq_zc770_xm012_defconfig index 0ba5da5..a92d495 100644 --- a/configs/zynq_zc770_xm012_defconfig +++ b/configs/zynq_zc770_xm012_defconfig @@ -5,3 +5,6 @@ CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM012" +S:CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm012" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/configs/zynq_zc770_xm013_defconfig b/configs/zynq_zc770_xm013_defconfig index 13f8112..3a02f75 100644 --- a/configs/zynq_zc770_xm013_defconfig +++ b/configs/zynq_zc770_xm013_defconfig @@ -5,3 +5,6 @@ CONFIG_SYS_EXTRA_OPTIONS="ZC770_XM013" +S:CONFIG_TARGET_ZYNQ_ZC770=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zc770-xm013" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/configs/zynq_zed_defconfig b/configs/zynq_zed_defconfig index eb057fa..1d816f6 100644 --- a/configs/zynq_zed_defconfig +++ b/configs/zynq_zed_defconfig @@ -4,3 +4,6 @@ CONFIG_SPL=y +S:CONFIG_TARGET_ZYNQ_ZED=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zed" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/configs/zynq_zybo_defconfig b/configs/zynq_zybo_defconfig index 12311cd..9183629 100644 --- a/configs/zynq_zybo_defconfig +++ b/configs/zynq_zybo_defconfig @@ -4,3 +4,6 @@ CONFIG_SPL=y +S:CONFIG_TARGET_ZYNQ_ZYBO=y CONFIG_OF_CONTROL=y CONFIG_DEFAULT_DEVICE_TREE="zynq-zybo" +CONFIG_FIT=y +CONFIG_FIT_VERBOSE=y +CONFIG_FIT_SIGNATURE=y diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index 560e3bf..cc36985 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -23,8 +23,8 @@ # define CONFIG_TIMESTAMP # define CONFIG_LZO # ifdef CONFIG_ENABLE_VBOOT -# define CONFIG_FIT_SIGNATURE -# define CONFIG_RSA +# define CONFIG_FIT_SIGNATURE +# define CONFIG_RSA # endif #endif
diff --git a/include/configs/ids8313.h b/include/configs/ids8313.h index f084834..2384864 100644 --- a/include/configs/ids8313.h +++ b/include/configs/ids8313.h @@ -575,12 +575,9 @@
#define CONFIG_VERSION_VARIABLE
-#define CONFIG_FIT -#define CONFIG_FIT_SIGNATURE #define CONFIG_IMAGE_FORMAT_LEGACY #define CONFIG_CMD_FDT #define CONFIG_CMD_HASH -#define CONFIG_RSA #define CONFIG_SHA1 #define CONFIG_SHA256
diff --git a/include/configs/sandbox.h b/include/configs/sandbox.h index 657f751..6fd29b9 100644 --- a/include/configs/sandbox.h +++ b/include/configs/sandbox.h @@ -41,9 +41,6 @@
#define CONFIG_OF_LIBFDT #define CONFIG_LMB -#define CONFIG_FIT -#define CONFIG_FIT_SIGNATURE -#define CONFIG_RSA #define CONFIG_CMD_FDT #define CONFIG_ANDROID_BOOT_IMAGE
diff --git a/include/configs/zynq-common.h b/include/configs/zynq-common.h index 87b4fff..3894517 100644 --- a/include/configs/zynq-common.h +++ b/include/configs/zynq-common.h @@ -219,17 +219,11 @@ #define CONFIG_OF_LIBFDT
/* FIT support */ -#define CONFIG_FIT -#define CONFIG_FIT_VERBOSE 1 /* enable fit_format_{error,warning}() */ #define CONFIG_IMAGE_FORMAT_LEGACY /* enable also legacy image format */
/* FDT support */ #define CONFIG_DISPLAY_BOARDINFO_LATE
-/* RSA support */ -#define CONFIG_FIT_SIGNATURE -#define CONFIG_RSA - /* Extend size of kernel image for uncompression */ #define CONFIG_SYS_BOOTM_LEN (60 * 1024 * 1024)

On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
For the platforms which use,CONFIG_FIT_SIGNATURE, the required configs are moved to the platform's defconfig file. Selecting CONFIG_FIT_SIGNATURE using defconfig automatically resolves the dependencies for signature verification. The RSA library gets automatically selected and user does not have to define CONFIG_RSA manually.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Acked-by: Simon Glass sjg@chromium.org
Changes in v3: New patch
configs/ids8313_defconfig | 2 ++ configs/sandbox_defconfig | 3 +++ configs/zynq_microzed_defconfig | 3 +++ configs/zynq_zc70x_defconfig | 3 +++ configs/zynq_zc770_xm010_defconfig | 3 +++ configs/zynq_zc770_xm012_defconfig | 3 +++ configs/zynq_zc770_xm013_defconfig | 3 +++ configs/zynq_zed_defconfig | 3 +++ configs/zynq_zybo_defconfig | 3 +++ include/configs/am335x_evm.h | 4 ++-- include/configs/ids8313.h | 3 --- include/configs/sandbox.h | 3 --- include/configs/zynq-common.h | 6 ------ 13 files changed, 28 insertions(+), 14 deletions(-)

Modify rsa_verify to use the rsa driver of DM library available.The tools and the configurations which don't use Driver Model, will continue to use the same RSA sw library. The software implementation of RSA Modular Exponentation is now compiled if RSA_MOD_EXP_SW is selected.
Kconfig options are also added for rsa library.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: New patch
include/configs/am335x_evm.h | 1 + lib/Kconfig | 6 +----- lib/rsa/Kconfig | 31 +++++++++++++++++++++++++++++++ lib/rsa/Makefile | 3 ++- lib/rsa/rsa-verify.c | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 lib/rsa/Kconfig
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index cc36985..aa79841 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -25,6 +25,7 @@ # ifdef CONFIG_ENABLE_VBOOT # define CONFIG_FIT_SIGNATURE # define CONFIG_RSA +# define CONFIG_RSA_MOD_EXP_SW # endif #endif
diff --git a/lib/Kconfig b/lib/Kconfig index 602dd37..a1f30a2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -27,10 +27,6 @@ config SYS_HZ get_timer() must operate in milliseconds and this option must be set to 1000.
-config RSA - bool "Use RSA Library" - help - RSA support.This enables the RSA algorithm used for FIT image - verification in U-Boot. +source lib/rsa/Kconfig
endmenu diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig new file mode 100644 index 0000000..8f9aa44 --- /dev/null +++ b/lib/rsa/Kconfig @@ -0,0 +1,31 @@ +config RSA + bool "Use RSA Library" + select RSA_MOD_EXP_SW if !DM + select DM_RSA if DM + help + RSA support.This enables the RSA algorithm used for FIT image + verification in U-Boot. + See doc/uImage.FIT/signature.txt for more details. + +if RSA && DM_RSA + +config RSA_SW + bool "User driver Model for RSA Modular Exponentiation in software" + depends on DM && DM_RSA && RSA + select RSA_MOD_EXP_SW + default y + help + Enables driver for modular exponentiation in software. This is a RSA + algorithm used in FIT image verification. It required RSA Key as + input. + See doc/uImage.FIT/signature.txt for more details. + +endif + +config RSA_MOD_EXP_SW + bool + default n + help + Library for SW implementation of RSA Modular Exponentiation. This + library is used by the mkimage tool(not selected through this option) + as well as by the RSA driver model with SW implementation. diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile index cc25b3c..ccc6060 100644 --- a/lib/rsa/Makefile +++ b/lib/rsa/Makefile @@ -7,4 +7,5 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o rsa-mod-exp.o +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-verify.c b/lib/rsa/rsa-verify.c index f8bc086..27f10ef 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -12,6 +12,7 @@ #include <asm/errno.h> #include <asm/types.h> #include <asm/unaligned.h> +#include <dm.h> #else #include "fdt_host.h" #include "mkimage.h" @@ -43,6 +44,9 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig, const uint8_t *padding; int pad_len; int ret; +#if defined(CONFIG_DM_RSA) && !defined(USE_HOSTCC) + struct udevice *rsa_dev; +#endif
if (!prop || !sig || !hash || !algo) return -EIO; @@ -63,11 +67,25 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
uint8_t buf[sig_len];
+#if defined(CONFIG_DM_RSA) && !defined(USE_HOSTCC) + ret = uclass_get_device(UCLASS_RSA, 0, &rsa_dev); + if (!ret) { + ret = rsa_mod_exp(rsa_dev, sig, sig_len, prop, buf); + if (ret) { + debug("Error in Modular exponentation\n"); + return ret; + } + } else { + printf("RSA: Can't find Mod Exp implemnetation\n"); + return -EINVAL; + } +#else ret = rsa_mod_exp_sw(sig, sig_len, prop, buf); if (ret) { debug("Error in Modular exponentation\n"); return ret; } +#endif
padding = algo->rsa_padding; pad_len = algo->pad_len - algo->checksum_len;

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Modify rsa_verify to use the rsa driver of DM library available.The tools and the configurations which don't use Driver Model, will continue to use the same RSA sw library. The software implementation of RSA Modular Exponentation is now compiled if RSA_MOD_EXP_SW is selected.
Kconfig options are also added for rsa library.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: New patch
include/configs/am335x_evm.h | 1 + lib/Kconfig | 6 +----- lib/rsa/Kconfig | 31 +++++++++++++++++++++++++++++++ lib/rsa/Makefile | 3 ++- lib/rsa/rsa-verify.c | 18 ++++++++++++++++++ 5 files changed, 53 insertions(+), 6 deletions(-) create mode 100644 lib/rsa/Kconfig
diff --git a/include/configs/am335x_evm.h b/include/configs/am335x_evm.h index cc36985..aa79841 100644 --- a/include/configs/am335x_evm.h +++ b/include/configs/am335x_evm.h @@ -25,6 +25,7 @@ # ifdef CONFIG_ENABLE_VBOOT # define CONFIG_FIT_SIGNATURE # define CONFIG_RSA +# define CONFIG_RSA_MOD_EXP_SW
This should go in am335x_boneblack_vboot_defconfig I think.
# endif #endif
diff --git a/lib/Kconfig b/lib/Kconfig index 602dd37..a1f30a2 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -27,10 +27,6 @@ config SYS_HZ get_timer() must operate in milliseconds and this option must be set to 1000.
-config RSA
bool "Use RSA Library"
help
RSA support.This enables the RSA algorithm used for FIT image
verification in U-Boot.
+source lib/rsa/Kconfig
endmenu diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig new file mode 100644 index 0000000..8f9aa44 --- /dev/null +++ b/lib/rsa/Kconfig @@ -0,0 +1,31 @@ +config RSA
bool "Use RSA Library"
select RSA_MOD_EXP_SW if !DM
select DM_RSA if DM
help
RSA support.This enables the RSA algorithm used for FIT image
verification in U-Boot.
See doc/uImage.FIT/signature.txt for more details.
+if RSA && DM_RSA
+config RSA_SW
bool "User driver Model for RSA Modular Exponentiation in software"
depends on DM && DM_RSA && RSA
select RSA_MOD_EXP_SW
default y
help
Enables driver for modular exponentiation in software. This is a RSA
algorithm used in FIT image verification. It required RSA Key as
input.
See doc/uImage.FIT/signature.txt for more details.
+endif
+config RSA_MOD_EXP_SW
bool
default n
help
Library for SW implementation of RSA Modular Exponentiation. This
library is used by the mkimage tool(not selected through this option)
as well as by the RSA driver model with SW implementation.
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile index cc25b3c..ccc6060 100644 --- a/lib/rsa/Makefile +++ b/lib/rsa/Makefile @@ -7,4 +7,5 @@ # SPDX-License-Identifier: GPL-2.0+ #
-obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o rsa-mod-exp.o +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-verify.c b/lib/rsa/rsa-verify.c index f8bc086..27f10ef 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -12,6 +12,7 @@ #include <asm/errno.h> #include <asm/types.h> #include <asm/unaligned.h> +#include <dm.h> #else #include "fdt_host.h" #include "mkimage.h" @@ -43,6 +44,9 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig, const uint8_t *padding; int pad_len; int ret; +#if defined(CONFIG_DM_RSA) && !defined(USE_HOSTCC)
struct udevice *rsa_dev;
+#endif
if (!prop || !sig || !hash || !algo) return -EIO;
@@ -63,11 +67,25 @@ static int rsa_verify_key(struct key_prop *prop, const uint8_t *sig,
uint8_t buf[sig_len];
+#if defined(CONFIG_DM_RSA) && !defined(USE_HOSTCC)
ret = uclass_get_device(UCLASS_RSA, 0, &rsa_dev);
if (!ret) {
ret = rsa_mod_exp(rsa_dev, sig, sig_len, prop, buf);
if (ret) {
debug("Error in Modular exponentation\n");
return ret;
}
} else {
printf("RSA: Can't find Mod Exp implemnetation\n");
return -EINVAL;
}
+#else ret = rsa_mod_exp_sw(sig, sig_len, prop, buf); if (ret) { debug("Error in Modular exponentation\n"); return ret; } +#endif
This should use the uclass regardless I think. The software implementation should just be a driver like the hardware implementation.
padding = algo->rsa_padding; pad_len = algo->pad_len - algo->checksum_len;
-- 1.8.1.4
Regards, Simon

Driver added for RSA Modular Exponentiation using Freescale Hardware Accelerator CAAM. The driver used uclass rsa.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: Moved to integrate with RSA UCLASS
drivers/crypto/Kconfig | 2 ++ drivers/crypto/fsl/Kconfig | 6 +++++ drivers/crypto/fsl/Makefile | 1 + drivers/crypto/fsl/fsl_rsa.c | 62 +++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/fsl/jobdesc.c | 28 +++++++++++++++++++ drivers/crypto/fsl/jobdesc.h | 5 ++++ drivers/crypto/fsl/rsa_caam.h | 28 +++++++++++++++++++ 7 files changed, 132 insertions(+) create mode 100644 drivers/crypto/fsl/Kconfig create mode 100644 drivers/crypto/fsl/fsl_rsa.c create mode 100644 drivers/crypto/fsl/rsa_caam.h
diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 75f3479..4100df1 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -1 +1,3 @@ source drivers/crypto/rsa/Kconfig + +source drivers/crypto/fsl/Kconfig diff --git a/drivers/crypto/fsl/Kconfig b/drivers/crypto/fsl/Kconfig new file mode 100644 index 0000000..86b2f2f --- /dev/null +++ b/drivers/crypto/fsl/Kconfig @@ -0,0 +1,6 @@ +config FSL_CAAM + bool "Freescale Crypto Driver Support" + help + Enables the Freescale's Cryptographic Accelerator and Assurance + Module (CAAM), also known as the SEC version 4 (SEC4). The driver uses + Job Ring as interface to communicate with CAAM. diff --git a/drivers/crypto/fsl/Makefile b/drivers/crypto/fsl/Makefile index 067d0a9..10d10c9 100644 --- a/drivers/crypto/fsl/Makefile +++ b/drivers/crypto/fsl/Makefile @@ -9,3 +9,4 @@ obj-y += sec.o obj-$(CONFIG_FSL_CAAM) += jr.o fsl_hash.o jobdesc.o error.o obj-$(CONFIG_CMD_BLOB) += fsl_blob.o +obj-$(CONFIG_FSL_RSA) += fsl_rsa.o diff --git a/drivers/crypto/fsl/fsl_rsa.c b/drivers/crypto/fsl/fsl_rsa.c new file mode 100644 index 0000000..4f556e9 --- /dev/null +++ b/drivers/crypto/fsl/fsl_rsa.c @@ -0,0 +1,62 @@ +/* + * (C) Copyright 2014 Freescale Semiconductor, Inc. + * Author: Nitin Garg nitin.garg@freescale.com + * Ye Li Ye.Li@freescale.com + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <config.h> +#include <common.h> +#include <dm.h> +#include <asm/types.h> +#include <malloc.h> +#include "jobdesc.h" +#include "desc.h" +#include "jr.h" +#include "rsa_caam.h" +#include <u-boot/rsa-mod-exp.h> + +int fsl_mod_exp(struct udevice *dev, const uint8_t *sig, uint32_t sig_len, + struct key_prop *prop, uint8_t *out) +{ + uint32_t keylen; + struct pk_in_params pkin; + uint32_t desc[MAX_CAAM_DESCSIZE]; + int ret; + + /* Length in bytes */ + keylen = prop->num_bits / 8; + + pkin.a = sig; + pkin.a_siz = sig_len; + pkin.n = prop->modulus; + pkin.n_siz = keylen; + pkin.e = prop->public_exponent; + pkin.e_siz = prop->exp_len; + + inline_cnstr_jobdesc_pkha_rsaexp(desc, &pkin, out, sig_len); + + ret = run_descriptor_jr(desc); + + if (ret) { + debug("%s: RSA failed to verify: %d\n", __func__, ret); + return -EFAULT; + } + + return 0; +} + +static const struct rsa_ops fsl_rsa_ops = { + .get_mod_exp = fsl_mod_exp, +}; + +U_BOOT_DRIVER(fsl_rsa) = { + .name = "fsl_rsa", + .id = UCLASS_RSA, + .ops = &fsl_rsa_ops, +}; + +U_BOOT_DEVICE(fsl_rsa) = { + .name = "fsl_rsa", +}; diff --git a/drivers/crypto/fsl/jobdesc.c b/drivers/crypto/fsl/jobdesc.c index 1386bae..cc0dced 100644 --- a/drivers/crypto/fsl/jobdesc.c +++ b/drivers/crypto/fsl/jobdesc.c @@ -11,6 +11,7 @@ #include <common.h> #include "desc_constr.h" #include "jobdesc.h" +#include "rsa_caam.h"
#define KEY_BLOB_SIZE 32 #define MAC_SIZE 16 @@ -123,3 +124,30 @@ void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc) append_operation(desc, OP_TYPE_CLASS1_ALG | OP_ALG_ALGSEL_RNG | OP_ALG_RNG4_SK); } + +/* Change key size to bytes form bits in calling function*/ +void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz) +{ + dma_addr_t dma_addr_e, dma_addr_a, dma_addr_n, dma_addr_out; + + dma_addr_e = virt_to_phys((void *)pkin->e); + dma_addr_a = virt_to_phys((void *)pkin->a); + dma_addr_n = virt_to_phys((void *)pkin->n); + dma_addr_out = virt_to_phys((void *)out); + + init_job_desc(desc, 0); + append_key(desc, dma_addr_e, pkin->e_siz, KEY_DEST_PKHA_E | CLASS_1); + + append_fifo_load(desc, dma_addr_a, + pkin->a_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_A); + + append_fifo_load(desc, dma_addr_n, + pkin->n_siz, LDST_CLASS_1_CCB | FIFOLD_TYPE_PK_N); + + append_operation(desc, OP_TYPE_PK | OP_ALG_PK | OP_ALG_PKMODE_MOD_EXPO); + + append_fifo_store(desc, dma_addr_out, out_siz, + LDST_CLASS_1_CCB | FIFOST_TYPE_PKHA_B); +} diff --git a/drivers/crypto/fsl/jobdesc.h b/drivers/crypto/fsl/jobdesc.h index 3cf7226..84b3edd 100644 --- a/drivers/crypto/fsl/jobdesc.h +++ b/drivers/crypto/fsl/jobdesc.h @@ -10,6 +10,7 @@
#include <common.h> #include <asm/io.h> +#include "rsa_caam.h"
#define KEY_IDNFR_SZ_BYTES 16
@@ -26,4 +27,8 @@ void inline_cnstr_jobdesc_blob_decap(uint32_t *desc, uint8_t *key_idnfr, uint32_t out_sz);
void inline_cnstr_jobdesc_rng_instantiation(uint32_t *desc); + +void inline_cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz); #endif diff --git a/drivers/crypto/fsl/rsa_caam.h b/drivers/crypto/fsl/rsa_caam.h new file mode 100644 index 0000000..4ff87ef --- /dev/null +++ b/drivers/crypto/fsl/rsa_caam.h @@ -0,0 +1,28 @@ +/* + * Copyright 2014 Freescale Semiconductor, Inc. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __RSA_CAAM_H +#define __RSA_CAAM_H + +#include <common.h> + +/** + * struct pk_in_params - holder for input to PKHA block in CAAM + * These parameters are required to perform Modular Exponentiation + * using PKHA Block in CAAM + */ +struct pk_in_params { + const uint8_t *e; /* public exponent as byte array */ + uint32_t e_siz; /* size of e[] in number of bytes */ + const uint8_t *n; /* modulus as byte array */ + uint32_t n_siz; /* size of n[] in number of bytes */ + const uint8_t *a; /* Signature as byte array */ + uint32_t a_siz; /* size of a[] in number of bytes */ + uint8_t *b; /* Result exp. modulus in number of bytes */ + uint32_t b_siz; /* size of b[] in number of bytes */ +}; + +#endif

On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Driver added for RSA Modular Exponentiation using Freescale Hardware Accelerator CAAM. The driver used uclass rsa.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: Moved to integrate with RSA UCLASS
Acked-by: Simon Glass sjg@chromium.org
drivers/crypto/Kconfig | 2 ++ drivers/crypto/fsl/Kconfig | 6 +++++ drivers/crypto/fsl/Makefile | 1 + drivers/crypto/fsl/fsl_rsa.c | 62 +++++++++++++++++++++++++++++++++++++++++++ drivers/crypto/fsl/jobdesc.c | 28 +++++++++++++++++++ drivers/crypto/fsl/jobdesc.h | 5 ++++ drivers/crypto/fsl/rsa_caam.h | 28 +++++++++++++++++++ 7 files changed, 132 insertions(+) create mode 100644 drivers/crypto/fsl/Kconfig create mode 100644 drivers/crypto/fsl/fsl_rsa.c create mode 100644 drivers/crypto/fsl/rsa_caam.h

Kconfig option added for devices which support RSA Verification (Modular Exponentiation) operation in hardware
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: New patch
lib/rsa/Kconfig | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index 8f9aa44..fc8a1e7 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -11,7 +11,7 @@ if RSA && DM_RSA
config RSA_SW bool "User driver Model for RSA Modular Exponentiation in software" - depends on DM && DM_RSA && RSA + depends on DM && DM_RSA && RSA && !RSA_HW select RSA_MOD_EXP_SW default y help @@ -20,6 +20,27 @@ config RSA_SW input. See doc/uImage.FIT/signature.txt for more details.
+menuconfig RSA_HW + bool "Use crypto devices to implement RSA Modular Exponentiation" + default y + help + Say Y here to get to see options for hardware crypto devices and + processors. This option alone does not enable the crypto device. + + If you say N,all options in this submenu will be skipped and disabled. + +if RSA_HW + +config FSL_RSA + bool "Implement RSA Modular Exponentiation with FSL crypto accelerator" + depends on DM && DM_RSA && RSA && FSL_CAAM + default y + help + Enables driver for RSA modular exponentiation using Freescale's + cryptographic accelerator - CAAM. + +endif + endif
config RSA_MOD_EXP_SW

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Kconfig option added for devices which support RSA Verification (Modular Exponentiation) operation in hardware
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: New patch
lib/rsa/Kconfig | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
I think this needs tweaking such that RSA_SW is a driver (use RSA_SOFTWARE might be better).
For your freescale one, it should be RSA_FREESCALE_EXP or similar. We might want to support multiple such devices. Don't use RSA_HW - that's not a descriptive name.
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index 8f9aa44..fc8a1e7 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -11,7 +11,7 @@ if RSA && DM_RSA
config RSA_SW bool "User driver Model for RSA Modular Exponentiation in software"
depends on DM && DM_RSA && RSA
depends on DM && DM_RSA && RSA && !RSA_HW
You should drop the last term since it should be possible to have both software and hardware.
select RSA_MOD_EXP_SW default y help
@@ -20,6 +20,27 @@ config RSA_SW input. See doc/uImage.FIT/signature.txt for more details.
+menuconfig RSA_HW
bool "Use crypto devices to implement RSA Modular Exponentiation"
default y
help
Say Y here to get to see options for hardware crypto devices and
processors. This option alone does not enable the crypto device.
If you say N,all options in this submenu will be skipped and disabled.
Space after N
+if RSA_HW
+config FSL_RSA
bool "Implement RSA Modular Exponentiation with FSL crypto accelerator"
depends on DM && DM_RSA && RSA && FSL_CAAM
default y
help
Enables driver for RSA modular exponentiation using Freescale's
cryptographic accelerator - CAAM.
+endif
endif
config RSA_MOD_EXP_SW
1.8.1.4
Regards, Simon

Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Wednesday, December 24, 2014 6:20 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495 Subject: Re: [PATCH 7/9] [v3] lib/rsa: Add Kconfig option for HW accelerated RSA
Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Kconfig option added for devices which support RSA Verification (Modular Exponentiation) operation in hardware
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: New patch
lib/rsa/Kconfig | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
I think this needs tweaking such that RSA_SW is a driver (use RSA_SOFTWARE might be better).
For your freescale one, it should be RSA_FREESCALE_EXP or similar. We might want to support multiple such devices. Don't use RSA_HW - that's not a descriptive name.
If we are using driver Model, can multiple devices be selected at the same time for the RSA_UCLASS ? I am little confused.
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index 8f9aa44..fc8a1e7 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -11,7 +11,7 @@ if RSA && DM_RSA
config RSA_SW bool "User driver Model for RSA Modular Exponentiation in software"
depends on DM && DM_RSA && RSA
depends on DM && DM_RSA && RSA && !RSA_HW
You should drop the last term since it should be possible to have both software and hardware.
This option selects the driver model for RSA software implementation suing RSA uclass. If I define both I get this error :
drivers/crypto/fsl/built-in.o:(.u_boot_list_2_driver_2_fsl_rsa+0x0): multiple definition of `_u_boot_list_2_driver_2_fsl_rsa' drivers/crypto/rsa/built-in.o:(.u_boot_list_2_driver_2_fsl_rsa+0x0): first defined here
select RSA_MOD_EXP_SW default y help
@@ -20,6 +20,27 @@ config RSA_SW input. See doc/uImage.FIT/signature.txt for more details.
+menuconfig RSA_HW
bool "Use crypto devices to implement RSA Modular Exponentiation"
default y
help
Say Y here to get to see options for hardware crypto devices and
processors. This option alone does not enable the crypto device.
If you say N,all options in this submenu will be skipped and
disabled.
Space after N
+if RSA_HW
+config FSL_RSA
bool "Implement RSA Modular Exponentiation with FSL crypto
accelerator"
depends on DM && DM_RSA && RSA && FSL_CAAM
default y
help
Enables driver for RSA modular exponentiation using Freescale's
cryptographic accelerator - CAAM.
+endif
endif
config RSA_MOD_EXP_SW
1.8.1.4
Regards, Simon
Regards, Ruchika

Hi Ruchika,
On 29 December 2014 at 00:05, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Wednesday, December 24, 2014 6:20 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495 Subject: Re: [PATCH 7/9] [v3] lib/rsa: Add Kconfig option for HW accelerated RSA
Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Kconfig option added for devices which support RSA Verification (Modular Exponentiation) operation in hardware
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: New patch
lib/rsa/Kconfig | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
I think this needs tweaking such that RSA_SW is a driver (use RSA_SOFTWARE might be better).
For your freescale one, it should be RSA_FREESCALE_EXP or similar. We might want to support multiple such devices. Don't use RSA_HW - that's not a descriptive name.
If we are using driver Model, can multiple devices be selected at the same time for the RSA_UCLASS ? I am little confused.
Yes, they can be accessed using uclass_get_device_by_seq() if they are numbered in the aliases:
aliases { mod_exp0 = "/path/to/hardware-node"; mod_exp1 = "/path/to/software-node"; }
or uclass_get_device() if there is no sequence numbering.
diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig index 8f9aa44..fc8a1e7 100644 --- a/lib/rsa/Kconfig +++ b/lib/rsa/Kconfig @@ -11,7 +11,7 @@ if RSA && DM_RSA
config RSA_SW bool "User driver Model for RSA Modular Exponentiation in software"
depends on DM && DM_RSA && RSA
depends on DM && DM_RSA && RSA && !RSA_HW
You should drop the last term since it should be possible to have both software and hardware.
This option selects the driver model for RSA software implementation suing RSA uclass. If I define both I get this error :
drivers/crypto/fsl/built-in.o:(.u_boot_list_2_driver_2_fsl_rsa+0x0): multiple definition of `_u_boot_list_2_driver_2_fsl_rsa' drivers/crypto/rsa/built-in.o:(.u_boot_list_2_driver_2_fsl_rsa+0x0): first defined here
Make sure you use a different name - it seems like you are using fsl_rsa for both.
select RSA_MOD_EXP_SW default y help
@@ -20,6 +20,27 @@ config RSA_SW input. See doc/uImage.FIT/signature.txt for more details.
+menuconfig RSA_HW
bool "Use crypto devices to implement RSA Modular Exponentiation"
default y
help
Say Y here to get to see options for hardware crypto devices and
processors. This option alone does not enable the crypto device.
If you say N,all options in this submenu will be skipped and
disabled.
Space after N
+if RSA_HW
+config FSL_RSA
bool "Implement RSA Modular Exponentiation with FSL crypto
accelerator"
depends on DM && DM_RSA && RSA && FSL_CAAM
default y
help
Enables driver for RSA modular exponentiation using Freescale's
cryptographic accelerator - CAAM.
+endif
endif
config RSA_MOD_EXP_SW
1.8.1.4
Regards, Simon

The hash_algo structure has some implementations in which progressive hash API's are not defined. These are basically the hardware based implementations of SHA. An API is added to find the algo which has progressive hash API's defined. This can then be integrated with RSA checksum library which uses Progressive Hash API's.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3 : Corrected ifdef for SHA1
Changes in v2 : Added commit message
common/hash.c | 33 ++++++++++++++++++++++++--------- include/hash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 12d6759..ea1ec60 100644 --- a/common/hash.c +++ b/common/hash.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include <asm/errno.h>
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1 static int hash_init_sha1(struct hash_algo *algo, void **ctxp) { sha1_context *ctx = malloc(sizeof(sha1_context)); @@ -125,12 +125,7 @@ static struct hash_algo hash_algo[] = { CHUNKSZ_SHA256, }, #endif - /* - * This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise - * it bloats the code for boards which use SHA1 but not the 'hash' - * or 'sha1sum' commands. - */ -#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1 { "sha1", SHA1_SUM_LEN, @@ -140,7 +135,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha1, hash_finish_sha1, }, -#define MULTI_HASH #endif #ifdef CONFIG_SHA256 { @@ -152,7 +146,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha256, hash_finish_sha256, }, -#define MULTI_HASH #endif { "crc32", @@ -165,6 +158,10 @@ static struct hash_algo hash_algo[] = { }, };
+#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) +#define MULTI_HASH +#endif + #if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) #define MULTI_HASH #endif @@ -311,6 +308,24 @@ int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) return -EPROTONOSUPPORT; }
+int hash_progressive_lookup_algo(const char *algo_name, + struct hash_algo **algop) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hash_algo); i++) { + if (!strcmp(algo_name, hash_algo[i].name)) { + if (hash_algo[i].hash_init) { + *algop = &hash_algo[i]; + return 0; + } + } + } + + debug("Unknown hash algorithm '%s'\n", algo_name); + return -EPROTONOSUPPORT; +} + void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) { int i; diff --git a/include/hash.h b/include/hash.h index d8ec4f0..059f84e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -128,6 +128,21 @@ int hash_block(const char *algo_name, const void *data, unsigned int len, int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
/** + * hash_progressive_lookup_algo() - Look up the hash_algo struct with progressive + * hash support for an algorithm + * + * The function returns the pointer to the struct or -EPROTONOSUPPORT if the + * algorithm is not available with progressive hash support. + * + * @algo_name: Hash algorithm to look up + * @algop: Pointer to the hash_algo struct if found + * + * @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm. + */ +int hash_progressive_lookup_algo(const char *algo_name, + struct hash_algo **algop); + +/** * hash_show() - Print out a hash algorithm and value * * You will get a message like this (without a newline at the end):

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
The hash_algo structure has some implementations in which progressive hash API's are not defined. These are basically the hardware based implementations of SHA. An API is added to find the algo which has progressive hash API's defined. This can then be integrated with RSA checksum library which uses Progressive Hash API's.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3 : Corrected ifdef for SHA1
Changes in v2 : Added commit message
common/hash.c | 33 ++++++++++++++++++++++++--------- include/hash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 12d6759..ea1ec60 100644 --- a/common/hash.c +++ b/common/hash.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include <asm/errno.h>
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1
I'm still not sure about this. I suspect this will bloat the code for boards that use CONFIG_SHA1 (most) but not CONFIG_CMD_SHA1SUM. You could check that, but I went through some contortions to make sure that the hash API was not compiled in when not needed.
static int hash_init_sha1(struct hash_algo *algo, void **ctxp) { sha1_context *ctx = malloc(sizeof(sha1_context)); @@ -125,12 +125,7 @@ static struct hash_algo hash_algo[] = { CHUNKSZ_SHA256, }, #endif
/*
* This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since otherwise
* it bloats the code for boards which use SHA1 but not the 'hash'
* or 'sha1sum' commands.
*/
This is the comment referring to the above.
Is it possible to leave this logic as it is?
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1 { "sha1", SHA1_SUM_LEN, @@ -140,7 +135,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha1, hash_finish_sha1, }, -#define MULTI_HASH #endif #ifdef CONFIG_SHA256 { @@ -152,7 +146,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha256, hash_finish_sha256, }, -#define MULTI_HASH #endif { "crc32", @@ -165,6 +158,10 @@ static struct hash_algo hash_algo[] = { }, };
+#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) +#define MULTI_HASH +#endif
#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) #define MULTI_HASH #endif @@ -311,6 +308,24 @@ int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) return -EPROTONOSUPPORT; }
+int hash_progressive_lookup_algo(const char *algo_name,
struct hash_algo **algop)
+{
int i;
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
if (!strcmp(algo_name, hash_algo[i].name)) {
if (hash_algo[i].hash_init) {
*algop = &hash_algo[i];
return 0;
}
}
}
debug("Unknown hash algorithm '%s'\n", algo_name);
return -EPROTONOSUPPORT;
+}
void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) { int i; diff --git a/include/hash.h b/include/hash.h index d8ec4f0..059f84e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -128,6 +128,21 @@ int hash_block(const char *algo_name, const void *data, unsigned int len, int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
/**
- hash_progressive_lookup_algo() - Look up the hash_algo struct with progressive
hash support for an algorithm
Try to get that on one line if you can.
- The function returns the pointer to the struct or -EPROTONOSUPPORT if the
- algorithm is not available with progressive hash support.
- @algo_name: Hash algorithm to look up
- @algop: Pointer to the hash_algo struct if found
- @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
- */
+int hash_progressive_lookup_algo(const char *algo_name,
struct hash_algo **algop);
+/**
- hash_show() - Print out a hash algorithm and value
- You will get a message like this (without a newline at the end):
-- 1.8.1.4
Regards, Simon

Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Wednesday, December 24, 2014 6:20 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495 Subject: Re: [PATCH 8/9] [v3] hash: Add function to find hash_algo struct with progressive hash
Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
The hash_algo structure has some implementations in which progressive hash API's are not defined. These are basically the hardware based implementations of SHA. An API is added to find the algo which has progressive hash API's defined. This can then be integrated with RSA checksum library which uses Progressive Hash API's.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3 : Corrected ifdef for SHA1
Changes in v2 : Added commit message
common/hash.c | 33 ++++++++++++++++++++++++--------- include/hash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 12d6759..ea1ec60 100644 --- a/common/hash.c +++ b/common/hash.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include <asm/errno.h>
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1
I'm still not sure about this. I suspect this will bloat the code for boards that use CONFIG_SHA1 (most) but not CONFIG_CMD_SHA1SUM. You could check that, but I went through some contortions to make sure that the hash API was not compiled in when not needed.
Since we will be using this API now in RSA checksum, defining CONFIG_SHA1 should allow the compilation of this structure. Asking user to enable CONFIG_CMD_SHA1SUM for using rsa-checksum doesn’t look right. Please suggest.
static int hash_init_sha1(struct hash_algo *algo, void **ctxp) { sha1_context *ctx = malloc(sizeof(sha1_context)); @@ -125,12 +125,7 @@ static struct hash_algo hash_algo[] = { CHUNKSZ_SHA256, }, #endif
/*
* This is CONFIG_CMD_SHA1SUM instead of CONFIG_SHA1 since
otherwise
* it bloats the code for boards which use SHA1 but not the 'hash'
* or 'sha1sum' commands.
*/
This is the comment referring to the above.
Is it possible to leave this logic as it is?
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1 { "sha1", SHA1_SUM_LEN, @@ -140,7 +135,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha1, hash_finish_sha1, }, -#define MULTI_HASH #endif #ifdef CONFIG_SHA256 { @@ -152,7 +146,6 @@ static struct hash_algo hash_algo[] = { hash_update_sha256, hash_finish_sha256, }, -#define MULTI_HASH #endif { "crc32", @@ -165,6 +158,10 @@ static struct hash_algo hash_algo[] = { }, };
+#if defined(CONFIG_SHA256) || defined(CONFIG_CMD_SHA1SUM) #define +MULTI_HASH #endif
#if defined(CONFIG_HASH_VERIFY) || defined(CONFIG_CMD_HASH) #define MULTI_HASH #endif @@ -311,6 +308,24 @@ int hash_lookup_algo(const char *algo_name, struct hash_algo **algop) return -EPROTONOSUPPORT; }
+int hash_progressive_lookup_algo(const char *algo_name,
struct hash_algo **algop) {
int i;
for (i = 0; i < ARRAY_SIZE(hash_algo); i++) {
if (!strcmp(algo_name, hash_algo[i].name)) {
if (hash_algo[i].hash_init) {
*algop = &hash_algo[i];
return 0;
}
}
}
debug("Unknown hash algorithm '%s'\n", algo_name);
return -EPROTONOSUPPORT;
+}
void hash_show(struct hash_algo *algo, ulong addr, ulong len, uint8_t *output) { int i; diff --git a/include/hash.h b/include/hash.h index d8ec4f0..059f84e 100644 --- a/include/hash.h +++ b/include/hash.h @@ -128,6 +128,21 @@ int hash_block(const char *algo_name, const void *data, unsigned int len, int hash_lookup_algo(const char *algo_name, struct hash_algo **algop);
/**
- hash_progressive_lookup_algo() - Look up the hash_algo struct with
progressive
hash support for an algorithm
Try to get that on one line if you can.
- The function returns the pointer to the struct or -EPROTONOSUPPORT
+if the
- algorithm is not available with progressive hash support.
- @algo_name: Hash algorithm to look up
- @algop: Pointer to the hash_algo struct if found
- @return 0 if ok, -EPROTONOSUPPORT for an unknown algorithm.
- */
+int hash_progressive_lookup_algo(const char *algo_name,
struct hash_algo **algop);
+/**
- hash_show() - Print out a hash algorithm and value
- You will get a message like this (without a newline at the end):
-- 1.8.1.4
Regards, Simon
Regards, Ruchika

+Wolfgang
Hi Ruchika,
On 29 December 2014 at 00:07, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Wednesday, December 24, 2014 6:20 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495 Subject: Re: [PATCH 8/9] [v3] hash: Add function to find hash_algo struct with progressive hash
Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
The hash_algo structure has some implementations in which progressive hash API's are not defined. These are basically the hardware based implementations of SHA. An API is added to find the algo which has progressive hash API's defined. This can then be integrated with RSA checksum library which uses Progressive Hash API's.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3 : Corrected ifdef for SHA1
Changes in v2 : Added commit message
common/hash.c | 33 ++++++++++++++++++++++++--------- include/hash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 12d6759..ea1ec60 100644 --- a/common/hash.c +++ b/common/hash.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include <asm/errno.h>
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1
I'm still not sure about this. I suspect this will bloat the code for boards that use CONFIG_SHA1 (most) but not CONFIG_CMD_SHA1SUM. You could check that, but I went through some contortions to make sure that the hash API was not compiled in when not needed.
Since we will be using this API now in RSA checksum, defining CONFIG_SHA1 should allow the compilation of this structure. Asking user to enable CONFIG_CMD_SHA1SUM for using rsa-checksum doesn’t look right. Please suggest.
Agreed it doesn't, it was just a code size hack. Wolfgang might be able to chime in with thoughts here (+Cc).
But still, do you need to change it? After all, CONFIG_CMD_SHA1SUM should be a superest for CONFIG_SHA1.
[snip]
Regards, Simon

Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Tuesday, December 30, 2014 2:44 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495; Wolfgang Denk Subject: Re: [PATCH 8/9] [v3] hash: Add function to find hash_algo struct with progressive hash
+Wolfgang
Hi Ruchika,
On 29 December 2014 at 00:07, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Hi Simon,
-----Original Message----- From: sjg@google.com [mailto:sjg@google.com] On Behalf Of Simon Glass Sent: Wednesday, December 24, 2014 6:20 AM To: Gupta Ruchika-R66431 Cc: U-Boot Mailing List; Sun York-R58495 Subject: Re: [PATCH 8/9] [v3] hash: Add function to find hash_algo struct with progressive hash
Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
The hash_algo structure has some implementations in which progressive hash API's are not defined. These are basically the hardware based implementations of SHA. An API is added to find the algo which has progressive hash API's defined. This can then be integrated with RSA checksum library which uses Progressive Hash API's.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3 : Corrected ifdef for SHA1
Changes in v2 : Added commit message
common/hash.c | 33 ++++++++++++++++++++++++--------- include/hash.h | 15 +++++++++++++++ 2 files changed, 39 insertions(+), 9 deletions(-)
diff --git a/common/hash.c b/common/hash.c index 12d6759..ea1ec60 100644 --- a/common/hash.c +++ b/common/hash.c @@ -20,7 +20,7 @@ #include <asm/io.h> #include <asm/errno.h>
-#ifdef CONFIG_CMD_SHA1SUM +#ifdef CONFIG_SHA1
I'm still not sure about this. I suspect this will bloat the code for boards that use CONFIG_SHA1 (most) but not CONFIG_CMD_SHA1SUM. You could check that, but I went through some contortions to make sure that the hash API was not compiled in when not needed.
Since we will be using this API now in RSA checksum, defining CONFIG_SHA1
should allow the compilation of this structure. Asking user to enable CONFIG_CMD_SHA1SUM for using rsa-checksum doesn’t look right. Please suggest.
Agreed it doesn't, it was just a code size hack. Wolfgang might be able to chime in with thoughts here (+Cc).
But still, do you need to change it? After all, CONFIG_CMD_SHA1SUM should be a superest for CONFIG_SHA1.
With CONFIG_FIT_SIGNATURE, CONFIG_SHA1 and CONFIG_SHA256 get automatically defined in include/image.h. I need to use the structure hash_algos to find the functions to be used for algo SHA1. If I leave this as it is, it would mean that I will have to modify include/image.h to define CONFIG_CMD_SHA1SUM for FIT signatures. I am not sure whether that would be the right thing to do.
[snip]
Regards, Simon
Regards, Ruchika

Currently the hash functions used in RSA are called directly from the sha1 and sha256 libraries. Change the RSA checksum library to use the progressive hash API's registered with struct hash_algo. This will allow the checksum library to use the hardware accelerated progressive hash API's once available.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org --- Changes in v3: Modified rsa-verify to check for return from checksum function
Changes in v2: Added generic function hash_calculate. Pass an additional argument as name of algorithm.
common/image-sig.c | 6 ++--- include/image.h | 5 ++-- include/u-boot/rsa-checksum.h | 7 +++--- lib/rsa/rsa-checksum.c | 53 +++++++++++++++++++++++++++++++++++++++---- lib/rsa/rsa-verify.c | 7 +++++- 5 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/common/image-sig.c b/common/image-sig.c index 8601eda..2c9f0cd 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -38,7 +38,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha1, #endif - sha1_calculate, + hash_calculate, padding_sha1_rsa2048, }, { @@ -48,7 +48,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha256, #endif - sha256_calculate, + hash_calculate, padding_sha256_rsa2048, }, { @@ -58,7 +58,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha256, #endif - sha256_calculate, + hash_calculate, padding_sha256_rsa4096, }
diff --git a/include/image.h b/include/image.h index af30d60..ec55f23 100644 --- a/include/image.h +++ b/include/image.h @@ -926,8 +926,9 @@ struct checksum_algo { #if IMAGE_ENABLE_SIGN const EVP_MD *(*calculate_sign)(void); #endif - void (*calculate)(const struct image_region region[], - int region_count, uint8_t *checksum); + int (*calculate)(const char *name, + const struct image_region region[], + int region_count, uint8_t *checksum); const uint8_t *rsa_padding; };
diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h index c996fb3..c546c80 100644 --- a/include/u-boot/rsa-checksum.h +++ b/include/u-boot/rsa-checksum.h @@ -16,9 +16,8 @@ extern const uint8_t padding_sha256_rsa4096[]; 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); +int hash_calculate(const char *name, + const struct image_region region[], int region_count, + uint8_t *checksum);
#endif diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c index 8d8b59f..7f1909a 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/rsa/rsa-checksum.c @@ -10,12 +10,13 @@ #include <asm/byteorder.h> #include <asm/errno.h> #include <asm/unaligned.h> +#include <hash.h> #else #include "fdt_host.h" -#endif -#include <u-boot/rsa.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#endif +#include <u-boot/rsa.h>
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
@@ -136,7 +137,33 @@ const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_SUM_LEN] = { 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
-void sha1_calculate(const struct image_region region[], int region_count, +#ifndef USE_HOSTCC +int hash_calculate(const char *name, + const struct image_region region[], + int region_count, uint8_t *checksum) +{ + struct hash_algo *algo; + int ret = 0; + void *ctx; + uint32_t i; + i = 0; + + ret = hash_progressive_lookup_algo(name, &algo); + if (ret) + return ret; + + algo->hash_init(algo, &ctx); + for (i = 0; i < region_count - 1; i++) + algo->hash_update(algo, ctx, region[i].data, region[i].size, 0); + + algo->hash_update(algo, ctx, region[i].data, region[i].size, 1); + algo->hash_finish(algo, ctx, checksum, algo->digest_size); + + return 0; +} + +#else +int sha1_calculate(const struct image_region region[], int region_count, uint8_t *checksum) { sha1_context ctx; @@ -147,9 +174,11 @@ void sha1_calculate(const struct image_region region[], int region_count, for (i = 0; i < region_count; i++) sha1_update(&ctx, region[i].data, region[i].size); sha1_finish(&ctx, checksum); + + return 0; }
-void sha256_calculate(const struct image_region region[], int region_count, +int sha256_calculate(const struct image_region region[], int region_count, uint8_t *checksum) { sha256_context ctx; @@ -160,4 +189,20 @@ void sha256_calculate(const struct image_region region[], int region_count, for (i = 0; i < region_count; i++) sha256_update(&ctx, region[i].data, region[i].size); sha256_finish(&ctx, checksum); + + return 0; } + +int hash_calculate(const char *name, + const struct image_region region[], int region_count, + uint8_t *checksum) +{ + if (!strcmp(name, "sha1")) + sha1_calculate(region, region_count, checksum); + + if (!strcmp(name, "sha256")) + sha256_calculate(region, region_count, checksum); + + return 0; +} +#endif diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 27f10ef..0028304 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -188,7 +188,12 @@ int rsa_verify(struct image_sign_info *info, }
/* Calculate checksum with checksum-algorithm */ - info->algo->checksum->calculate(region, region_count, hash); + ret = info->algo->checksum->calculate(info->algo->checksum->name, + region, region_count, hash); + if (ret < 0) { + debug("%s: Error in checksum calculation\n", __func__); + return -EINVAL; + }
/* See if we must use a particular key */ if (info->required_keynode != -1) {

Hi Ruchika,
On 23 December 2014 at 04:32, Ruchika Gupta ruchika.gupta@freescale.com wrote:
Currently the hash functions used in RSA are called directly from the sha1 and sha256 libraries. Change the RSA checksum library to use the progressive hash API's registered with struct hash_algo. This will allow the checksum library to use the hardware accelerated progressive hash API's once available.
Signed-off-by: Ruchika Gupta ruchika.gupta@freescale.com CC: Simon Glass sjg@chromium.org
Changes in v3: Modified rsa-verify to check for return from checksum function
Changes in v2: Added generic function hash_calculate. Pass an additional argument as name of algorithm.
common/image-sig.c | 6 ++--- include/image.h | 5 ++-- include/u-boot/rsa-checksum.h | 7 +++--- lib/rsa/rsa-checksum.c | 53 +++++++++++++++++++++++++++++++++++++++---- lib/rsa/rsa-verify.c | 7 +++++- 5 files changed, 64 insertions(+), 14 deletions(-)
diff --git a/common/image-sig.c b/common/image-sig.c index 8601eda..2c9f0cd 100644 --- a/common/image-sig.c +++ b/common/image-sig.c @@ -38,7 +38,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha1, #endif
sha1_calculate,
hash_calculate, padding_sha1_rsa2048, }, {
@@ -48,7 +48,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha256, #endif
sha256_calculate,
hash_calculate, padding_sha256_rsa2048, }, {
@@ -58,7 +58,7 @@ struct checksum_algo checksum_algos[] = { #if IMAGE_ENABLE_SIGN EVP_sha256, #endif
sha256_calculate,
hash_calculate, padding_sha256_rsa4096, }
diff --git a/include/image.h b/include/image.h index af30d60..ec55f23 100644 --- a/include/image.h +++ b/include/image.h @@ -926,8 +926,9 @@ struct checksum_algo { #if IMAGE_ENABLE_SIGN const EVP_MD *(*calculate_sign)(void); #endif
void (*calculate)(const struct image_region region[],
int region_count, uint8_t *checksum);
int (*calculate)(const char *name,
const struct image_region region[],
int region_count, uint8_t *checksum); const uint8_t *rsa_padding;
};
diff --git a/include/u-boot/rsa-checksum.h b/include/u-boot/rsa-checksum.h index c996fb3..c546c80 100644 --- a/include/u-boot/rsa-checksum.h +++ b/include/u-boot/rsa-checksum.h @@ -16,9 +16,8 @@ extern const uint8_t padding_sha256_rsa4096[]; 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);
+int hash_calculate(const char *name,
const struct image_region region[], int region_count,
uint8_t *checksum);
This could use a function comment.
#endif diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c index 8d8b59f..7f1909a 100644 --- a/lib/rsa/rsa-checksum.c +++ b/lib/rsa/rsa-checksum.c @@ -10,12 +10,13 @@ #include <asm/byteorder.h> #include <asm/errno.h> #include <asm/unaligned.h> +#include <hash.h> #else #include "fdt_host.h" -#endif -#include <u-boot/rsa.h> #include <u-boot/sha1.h> #include <u-boot/sha256.h> +#endif +#include <u-boot/rsa.h>
/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
@@ -136,7 +137,33 @@ const uint8_t padding_sha256_rsa4096[RSA4096_BYTES - SHA256_SUM_LEN] = { 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20 };
-void sha1_calculate(const struct image_region region[], int region_count, +#ifndef USE_HOSTCC +int hash_calculate(const char *name,
const struct image_region region[],
int region_count, uint8_t *checksum)
+{
struct hash_algo *algo;
int ret = 0;
void *ctx;
uint32_t i;
i = 0;
ret = hash_progressive_lookup_algo(name, &algo);
if (ret)
return ret;
algo->hash_init(algo, &ctx);
for (i = 0; i < region_count - 1; i++)
algo->hash_update(algo, ctx, region[i].data, region[i].size, 0);
algo->hash_update(algo, ctx, region[i].data, region[i].size, 1);
algo->hash_finish(algo, ctx, checksum, algo->digest_size);
return 0;
+}
+#else
The above looks good, but what is happening here? Why do you need to do something different for USE_HOSTCC?
+int sha1_calculate(const struct image_region region[], int region_count, uint8_t *checksum) { sha1_context ctx; @@ -147,9 +174,11 @@ void sha1_calculate(const struct image_region region[], int region_count, for (i = 0; i < region_count; i++) sha1_update(&ctx, region[i].data, region[i].size); sha1_finish(&ctx, checksum);
return 0;
}
-void sha256_calculate(const struct image_region region[], int region_count, +int sha256_calculate(const struct image_region region[], int region_count, uint8_t *checksum) { sha256_context ctx; @@ -160,4 +189,20 @@ void sha256_calculate(const struct image_region region[], int region_count, for (i = 0; i < region_count; i++) sha256_update(&ctx, region[i].data, region[i].size); sha256_finish(&ctx, checksum);
return 0;
}
+int hash_calculate(const char *name,
const struct image_region region[], int region_count,
uint8_t *checksum)
+{
if (!strcmp(name, "sha1"))
sha1_calculate(region, region_count, checksum);
if (!strcmp(name, "sha256"))
sha256_calculate(region, region_count, checksum);
return 0;
+} +#endif diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 27f10ef..0028304 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -188,7 +188,12 @@ int rsa_verify(struct image_sign_info *info, }
/* Calculate checksum with checksum-algorithm */
info->algo->checksum->calculate(region, region_count, hash);
ret = info->algo->checksum->calculate(info->algo->checksum->name,
region, region_count, hash);
if (ret < 0) {
debug("%s: Error in checksum calculation\n", __func__);
return -EINVAL;
} /* See if we must use a particular key */ if (info->required_keynode != -1) {
-- 1.8.1.4
Regards, Simon
participants (2)
-
Ruchika Gupta
-
Simon Glass