[U-Boot] [PATCH v3 4/6] lib: rsa: generate additional parameters for public key

Simon Glass sjg at chromium.org
Wed Nov 20 02:59:59 UTC 2019


Hi Takahiro,

On Tue, 12 Nov 2019 at 16:47, AKASHI Takahiro
<takahiro.akashi at linaro.org> wrote:
>
> In the current implementation of FIT_SIGNATURE, five parameters for
> a RSA public key are required while only two of them are essential.
> (See rsa-mod-exp.h and uImage.FIT/signature.txt)
> This is a result of considering relatively limited computer power
> and resources on embedded systems, while such a assumption may not
> be quite practical for other use cases.
>
> In this patch, added is a function, rsa_gen_key_prop(), which will
> generate additional parameters for other uses, in particular
> UEFI secure boot, on the fly.
>
> Note: the current code uses some "big number" routines from BearSSL
> for the calculation.
>
> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> ---
>  include/u-boot/rsa-mod-exp.h |  21 +
>  lib/rsa/Kconfig              |   1 +
>  lib/rsa/Makefile             |   1 +
>  lib/rsa/rsa-keyprop.c        | 717 +++++++++++++++++++++++++++++++++++
>  4 files changed, 740 insertions(+)
>  create mode 100644 lib/rsa/rsa-keyprop.c
>
> diff --git a/include/u-boot/rsa-mod-exp.h b/include/u-boot/rsa-mod-exp.h
> index 8a428c4b6a1a..374169b8304e 100644
> --- a/include/u-boot/rsa-mod-exp.h
> +++ b/include/u-boot/rsa-mod-exp.h
> @@ -26,6 +26,27 @@ struct key_prop {
>         uint32_t exp_len;       /* Exponent length in number of uint8_t */
>  };
>
> +/**
> + * rsa_gen_key_prop() - Generate key properties of RSA public key
> + * @key:       Specifies key data in DER format
> + * @keylen:    Length of @key
> + *
> + * This function takes a blob of encoded RSA public key data in DER
> + * format, parse it and generate all the relevant properties
> + * in key_prop structure.
> + *
> + * Return:     Pointer to struct key_prop on success, NULL on error
> + */
> +struct key_prop *rsa_gen_key_prop(const void *key, uint32_t keylen);
> +
> +/**
> + * rsa_free_key_prop() - Free key properties
> + * @prop:      Pointer to struct key_prop
> + *
> + * This function frees all the memories allocated by rsa_gen_key_prop().
> + */
> +void rsa_free_key_prop(struct key_prop *prop);
> +
>  /**
>   * rsa_mod_exp_sw() - Perform RSA Modular Exponentiation in sw
>   *
> diff --git a/lib/rsa/Kconfig b/lib/rsa/Kconfig
> index 71e4c06bf883..d1d6f6cf64a3 100644
> --- a/lib/rsa/Kconfig
> +++ b/lib/rsa/Kconfig
> @@ -33,6 +33,7 @@ config RSA_VERIFY
>  config RSA_VERIFY_WITH_PKEY
>         bool "Execute RSA verification without key parameters from FDT"
>         depends on RSA
> +       imply RSA_PUBLIC_KEY_PARSER
>         help
>           The standard RSA-signature verification code (FIT_SIGNATURE) uses
>           pre-calculated key properties, that are stored in fdt blob, in
> diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
> index c07305188e0c..14ed3cb4012b 100644
> --- a/lib/rsa/Makefile
> +++ b/lib/rsa/Makefile
> @@ -6,4 +6,5 @@
>  # Wolfgang Denk, DENX Software Engineering, wd at denx.de.
>
>  obj-$(CONFIG_$(SPL_)RSA_VERIFY) += rsa-verify.o rsa-checksum.o
> +obj-$(CONFIG_RSA_VERIFY_WITH_PKEY) += rsa-keyprop.o
>  obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o
> diff --git a/lib/rsa/rsa-keyprop.c b/lib/rsa/rsa-keyprop.c
> new file mode 100644
> index 000000000000..9458337cc608
> --- /dev/null
> +++ b/lib/rsa/rsa-keyprop.c
> @@ -0,0 +1,717 @@
> +// SPDX-License-Identifier: GPL-2.0+ and MIT
> +/*
> + * RSA library - generate parameters for a public key
> + *
> + * Copyright (c) 2019 Linaro Limited
> + * Author: AKASHI Takahiro
> + *
> + * Big number routines in this file come from BearSSL:

Can we put these in their own file if we expect to update them? Really
should be called by the original filename and go in lib/bearsll.

[..]

> +/**
> + * rsa_gen_key_prop() - Generate key properties of RSA public key
> + * @key:       Specifies key data in DER format
> + * @keylen:    Length of @key
> + *
> + * This function takes a blob of encoded RSA public key data in DER
> + * format, parse it and generate all the relevant properties
> + * in key_prop structure.
> + *
> + * Return:     Pointer to struct key_prop on success, NULL on error
> + */
> +struct key_prop *rsa_gen_key_prop(const void *key, uint32_t keylen)
> +{
> +       struct key_prop *prop;
> +       struct rsa_key rsa_key;
> +#define BR_MAX_RSA_SIZE 4096

const int?

> +       uint32_t *n, *rr, *rrtmp;
> +       int rlen, i, ret;
> +
> +       prop = calloc(sizeof(*prop), 1);
> +       if (!prop)
> +               return NULL;
> +       n = calloc(sizeof(uint32_t), 1 + (BR_MAX_RSA_SIZE >> 5));
> +       rr = calloc(sizeof(uint32_t), 1 + (BR_MAX_RSA_SIZE >> 5));
> +       rrtmp = calloc(sizeof(uint32_t), 1 + (BR_MAX_RSA_SIZE >> 5));
> +       if (!n || !rr || !rrtmp)
> +               return NULL;

This can cause memory leak and will likely generate a coverity warning.

> +
> +       ret = rsa_parse_pub_key(&rsa_key, key, keylen);
> +       if (ret)
> +               goto err;
> +
> +       /* modulus */
> +       /* removing leading 0's */
> +       for (i = 0; i < rsa_key.n_sz && !rsa_key.n[i]; i++)
> +               ;
> +       prop->num_bits = (rsa_key.n_sz - i) * 8;
> +       prop->modulus = malloc(rsa_key.n_sz - i);
> +       if (!prop->modulus)
> +               goto err;
> +       memcpy((void *)prop->modulus, &rsa_key.n[i], rsa_key.n_sz - i);
> +
> +       /* exponent */
> +       prop->public_exponent = calloc(1, sizeof(uint64_t));
> +       if (!prop->public_exponent)
> +               goto err;
> +       memcpy((void *)prop->public_exponent + sizeof(uint64_t) - rsa_key.e_sz,
> +              rsa_key.e, rsa_key.e_sz);
> +       prop->exp_len = rsa_key.e_sz;
> +
> +       /* n0 inverse */
> +       br_i32_decode(n, &rsa_key.n[i], rsa_key.n_sz - i);
> +       prop->n0inv = br_i32_ninv32(n[1]);
> +
> +       /* R^2 mod n; R = 2^(num_bits) */
> +       rlen = prop->num_bits * 2; /* #bits of R^2 = (2^num_bits)^2 */
> +       rr[0] = 0;
> +       *(uint8_t *)&rr[0] = (1 << (rlen % 8));
> +       for (i = 1; i < (((rlen + 31) >> 5) + 1); i++)
> +               rr[i] = 0;
> +       br_i32_decode(rrtmp, rr, ((rlen + 7) >> 3) + 1);
> +       br_i32_reduce(rr, rrtmp, n);
> +
> +       rlen = (prop->num_bits + 7) >> 3; /* #bytes of R^2 mod n */
> +       prop->rr = malloc(rlen);
> +       if (!prop->rr)
> +               goto err;
> +       br_i32_encode((void *)prop->rr, rlen, rr);
> +
> +       return prop;
> +
> +err:
> +       free(n);
> +       free(rr);
> +       free(rrtmp);
> +       rsa_free_key_prop(prop);
> +       return NULL;

This should return -ENOMEM if we are out of memory. The caller cannot
divine what went wrong.

> +}
> --
> 2.21.0
>

Regards,
Simon


More information about the U-Boot mailing list