[U-Boot] [PATCH v2 4/8] rsa: add sha256-rsa2048 algorithm

Simon Glass sjg at chromium.org
Sun Feb 16 00:11:55 CET 2014


Hi Heiko,

On 8 February 2014 22:34, Heiko Schocher <hs at denx.de> wrote:
> based on patch from andreas at oetken.name:
>
> http://patchwork.ozlabs.org/patch/294318/
> commit message:
> I currently need support for rsa-sha256 signatures in u-boot and found out that
> the code for signatures is not very generic. Thus adding of different
> hash-algorithms for rsa-signatures is not easy to do without copy-pasting the
> rsa-code. I attached a patch for how I think it could be better and included
> support for rsa-sha256. This is a fast first shot.
>
> aditionally work:
> - removed checkpatch warnings
> - removed compiler warnings
> - rebased against current head
>
> Signed-off-by: Heiko Schocher <hs at denx.de>
> Cc: andreas at oetken.name
> Cc: Simon Glass <sjg at chromium.org>
>
> ---
> changes for v2:
> - add comment from Simon Glass:
>   - add commit message from original patch
>   - remove unnecessary function declaration
>     rsa_verify_256()
>   - sandbox: add sha256 tests
>
>  common/image-sig.c                                 | 33 ++++++++
>  doc/uImage.FIT/signature.txt                       | 25 +++++-
>  include/image.h                                    | 21 +++++
>  include/rsa-checksum.h                             | 25 ++++++
>  include/rsa.h                                      | 14 ++++
>  lib/rsa/Makefile                                   |  2 +-
>  lib/rsa/rsa-checksum.c                             | 98 ++++++++++++++++++++++
>  lib/rsa/rsa-sign.c                                 | 10 ++-
>  lib/rsa/rsa-verify.c                               | 83 ++++++------------
>  .../{sign-configs.its => sign-configs-sha1.its}    |  0
>  test/vboot/sign-configs-sha256.its                 | 45 ++++++++++
>  .../{sign-images.its => sign-images-sha1.its}      |  0
>  test/vboot/sign-images-sha256.its                  | 42 ++++++++++
>  test/vboot/vboot_test.sh                           | 18 ++--
>  14 files changed, 346 insertions(+), 70 deletions(-)
>  create mode 100644 include/rsa-checksum.h
>  create mode 100644 lib/rsa/rsa-checksum.c
>  rename test/vboot/{sign-configs.its => sign-configs-sha1.its} (100%)
>  create mode 100644 test/vboot/sign-configs-sha256.its
>  rename test/vboot/{sign-images.its => sign-images-sha1.its} (100%)
>  create mode 100644 test/vboot/sign-images-sha256.its
>
> diff --git a/common/image-sig.c b/common/image-sig.c
> index 973b06d..8b212a7 100644
> --- a/common/image-sig.c
> +++ b/common/image-sig.c
> @@ -14,15 +14,47 @@ DECLARE_GLOBAL_DATA_PTR;
>  #endif /* !USE_HOSTCC*/
>  #include <image.h>
>  #include <rsa.h>
> +#include <rsa-checksum.h>
>
>  #define IMAGE_MAX_HASHED_NODES         100
>
> +#if defined(CONFIG_FIT_SIGNATURE)

This is already in the Makefile for image-sig.c

> +struct checksum_algo checksum_algos[] = {
> +       {
> +               "sha1",
> +               SHA1_SUM_LEN,
> +#if IMAGE_ENABLE_SIGN
> +               EVP_sha1,
> +#else
> +               sha1_calculate,
> +               padding_sha1_rsa2048,
> +#endif
> +       },
> +       {
> +               "sha256",
> +               SHA256_SUM_LEN,
> +#if IMAGE_ENABLE_SIGN
> +               EVP_sha256,
> +#else
> +               sha256_calculate,
> +               padding_sha256_rsa2048,
> +#endif
> +       }
> +};
>  struct image_sig_algo image_sig_algos[] = {
>         {
>                 "sha1,rsa2048",
>                 rsa_sign,
>                 rsa_add_verify_data,
>                 rsa_verify,
> +               &checksum_algos[0],
> +       },
> +       {
> +               "sha256,rsa2048",
> +               rsa_sign,
> +               rsa_add_verify_data,
> +               rsa_verify,
> +               &checksum_algos[1],
>         }
>  };
>
> @@ -407,3 +439,4 @@ int fit_config_verify(const void *fit, int conf_noffset)
>         return !fit_config_verify_required_sigs(fit, conf_noffset,
>                                                 gd_fdt_blob());
>  }
> +#endif
> diff --git a/doc/uImage.FIT/signature.txt b/doc/uImage.FIT/signature.txt
> index bc9f3fa..5bd229f 100644
> --- a/doc/uImage.FIT/signature.txt
> +++ b/doc/uImage.FIT/signature.txt
> @@ -346,6 +346,7 @@ Simple Verified Boot Test
>
>  Please see doc/uImage.FIT/verified-boot.txt for more information
>
> +/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
>  Build keys
>  Build FIT with signed images
>  Test Verified Boot Run: unsigned signatures:: OK
> @@ -355,9 +356,31 @@ Build FIT with signed configuration
>  Test Verified Boot Run: unsigned config: OK
>  Sign images
>  Test Verified Boot Run: signed config: OK
> +Test Verified Boot Run: signed config with bad hash: OK
>
> -Test passed
> +Test sha1 passed
>
> +Or for testing sha256:
> +
> +$ O=sandbox ./test/vboot/vboot_test.sh sha256
> +Simple Verified Boot Test
> +=========================
> +
> +Please see doc/uImage.FIT/verified-boot.txt for more information
> +
> +/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
> +Build keys
> +Build FIT with signed images
> +Test Verified Boot Run: unsigned signatures:: OK
> +Sign images
> +Test Verified Boot Run: signed images: OK
> +Build FIT with signed configuration
> +Test Verified Boot Run: unsigned config: OK
> +Sign images
> +Test Verified Boot Run: signed config: OK
> +Test Verified Boot Run: signed config with bad hash: OK
> +
> +Test sha256 passed
>
>  Future Work
>  -----------
> diff --git a/include/image.h b/include/image.h
> index f001a5f..eb3429f 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -832,6 +832,7 @@ int calculate_hash(const void *data, int data_len, const char *algo,
>  # ifdef USE_HOSTCC
>  #  define IMAGE_ENABLE_SIGN    1
>  #  define IMAGE_ENABLE_VERIFY  0
> +# include  <openssl/evp.h>
>  #else
>  #  define IMAGE_ENABLE_SIGN    0
>  #  define IMAGE_ENABLE_VERIFY  1
> @@ -871,6 +872,23 @@ struct image_region {
>         int size;
>  };
>
> +#if IMAGE_ENABLE_VERIFY
> +# include <rsa-checksum.h>
> +#endif
> +struct checksum_algo {
> +       const char *name;
> +       const int checksum_len;
> +#if IMAGE_ENABLE_SIGN
> +       const EVP_MD *(*calculate)(void);
> +#else
> +#if IMAGE_ENABLE_VERIFY
> +       void (*calculate)(const struct image_region region[],
> +                         int region_count, uint8_t *checksum);
> +       const uint8_t *rsa_padding;
> +#endif
> +#endif
> +};
> +
>  struct image_sig_algo {
>         const char *name;               /* Name of algorithm */
>
> @@ -921,6 +939,9 @@ struct image_sig_algo {
>         int (*verify)(struct image_sign_info *info,
>                       const struct image_region region[], int region_count,
>                       uint8_t *sig, uint sig_len);
> +
> +       /* pointer to checksum algorithm */
> +       struct checksum_algo *checksum;
>  };
>
>  /**
> diff --git a/include/rsa-checksum.h b/include/rsa-checksum.h
> new file mode 100644
> index 0000000..12494a6
> --- /dev/null
> +++ b/include/rsa-checksum.h
> @@ -0,0 +1,25 @@
> +/*
> + * Copyright (c) 2013, Andreas Oetken.
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> +*/
> +
> +#ifndef _RSA_CHECKSUM_H
> +#define _RSA_CHECKSUM_H
> +
> +#include <errno.h>
> +#include <image.h>
> +#include <sha1.h>
> +#include <sha256.h>
> +
> +#if IMAGE_ENABLE_VERIFY

I don't think we need this in a header file.


> +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);
> +#endif
> +
> +#endif
> diff --git a/include/rsa.h b/include/rsa.h
> index add4c78..0367671 100644
> --- a/include/rsa.h
> +++ b/include/rsa.h
> @@ -15,6 +15,20 @@
>  #include <errno.h>
>  #include <image.h>
>
> +/**
> + * struct rsa_public_key - holder for a public key
> + *
> + * An RSA public key consists of a modulus (typically called N), the inverse
> + * and R^2, where R is 2^(# key bits).
> + */
> +
> +struct rsa_public_key {
> +       uint len;        /* Length of modulus[] in number of uint32_t */
> +       uint32_t n0inv;        /* -1 / modulus[0] mod 2^32 */
> +       uint32_t *modulus;    /* modulus as little endian array */
> +       uint32_t *rr;        /* R^2 as little endian array */

Nice to left-align the comments?

> +};
> +
>  #if IMAGE_ENABLE_SIGN
>  /**
>   * sign() - calculate and return signature for given input data
> diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile
> index 164ab39..a5a96cb6 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
> +obj-$(CONFIG_FIT_SIGNATURE) += rsa-verify.o rsa-checksum.o
> diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c
> new file mode 100644
> index 0000000..e520e1c
> --- /dev/null
> +++ b/lib/rsa/rsa-checksum.c
> @@ -0,0 +1,98 @@
> +/*
> + * Copyright (c) 2013, Andreas Oetken.
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <rsa.h>
> +#include <sha1.h>
> +#include <sha256.h>
> +#include <asm/byteorder.h>
> +#include <asm/errno.h>
> +#include <asm/unaligned.h>
> +
> +#define RSA2048_BYTES 256
> +
> +/* PKCS 1.5 paddings as described in the RSA PKCS#1 v2.1 standard. */
> +
> +const uint8_t padding_sha256_rsa2048[RSA2048_BYTES - SHA256_SUM_LEN] = {
> +0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30,
> +0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
> +0x00, 0x04, 0x20
> +};
> +
> +const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
> +       0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> +       0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
> +       0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
> +       0x05, 0x00, 0x04, 0x14
> +};
> +
> +void sha1_calculate(const struct image_region region[], int region_count,
> +                   uint8_t *checksum)
> +{
> +       sha1_context ctx;
> +       uint32_t i;
> +       i = 0;
> +
> +       sha1_starts(&ctx);
> +       for (i = 0; i < region_count; i++)
> +               sha1_update(&ctx, region[i].data, region[i].size);
> +       sha1_finish(&ctx, checksum);
> +}
> +
> +void sha256_calculate(const struct image_region region[], int region_count,
> +                     uint8_t *checksum)
> +{
> +       sha256_context ctx;
> +       uint32_t i;
> +       i = 0;
> +
> +       sha256_starts(&ctx);
> +       for (i = 0; i < region_count; i++)
> +               sha256_update(&ctx, region[i].data, region[i].size);
> +       sha256_finish(&ctx, checksum);
> +}
> diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c
> index 549130e..0fe6e9f 100644
> --- a/lib/rsa/rsa-sign.c
> +++ b/lib/rsa/rsa-sign.c
> @@ -159,8 +159,9 @@ static void rsa_remove(void)
>         EVP_cleanup();
>  }
>
> -static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
> -               int region_count, uint8_t **sigp, uint *sig_size)
> +static int rsa_sign_with_key(RSA *rsa, struct checksum_algo *checksum_algo,
> +               const struct image_region region[], int region_count,
> +               uint8_t **sigp, uint *sig_size)
>  {
>         EVP_PKEY *key;
>         EVP_MD_CTX *context;
> @@ -192,7 +193,7 @@ static int rsa_sign_with_key(RSA *rsa, const struct image_region region[],
>                 goto err_create;
>         }
>         EVP_MD_CTX_init(context);
> -       if (!EVP_SignInit(context, EVP_sha1())) {
> +       if (!EVP_SignInit(context, checksum_algo->calculate())) {
>                 ret = rsa_err("Signer setup failed");
>                 goto err_sign;
>         }
> @@ -242,7 +243,8 @@ int rsa_sign(struct image_sign_info *info,
>         ret = rsa_get_priv_key(info->keydir, info->keyname, &rsa);
>         if (ret)
>                 goto err_priv;
> -       ret = rsa_sign_with_key(rsa, region, region_count, sigp, sig_len);
> +       ret = rsa_sign_with_key(rsa, info->algo->checksum, region,
> +                               region_count, sigp, sig_len);
>         if (ret)
>                 goto err_sign;
>
> diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
> index 02cc4e3..b3573a8 100644
> --- a/lib/rsa/rsa-verify.c
> +++ b/lib/rsa/rsa-verify.c
> @@ -8,23 +8,11 @@
>  #include <fdtdec.h>
>  #include <rsa.h>
>  #include <sha1.h>
> +#include <sha256.h>
>  #include <asm/byteorder.h>
>  #include <asm/errno.h>
>  #include <asm/unaligned.h>
>
> -/**
> - * struct rsa_public_key - holder for a public key
> - *
> - * An RSA public key consists of a modulus (typically called N), the inverse
> - * and R^2, where R is 2^(# key bits).
> - */
> -struct rsa_public_key {
> -       uint len;               /* Length of modulus[] in number of uint32_t */
> -       uint32_t n0inv;         /* -1 / modulus[0] mod 2^32 */
> -       uint32_t *modulus;      /* modulus as little endian array */
> -       uint32_t *rr;           /* R^2 as little endian array */
> -};
> -
>  #define UINT64_MULT32(v, multby)  (((uint64_t)(v)) * ((uint32_t)(multby)))
>
>  #define RSA2048_BYTES  (2048 / 8)
> @@ -36,39 +24,6 @@ struct rsa_public_key {
>  /* This is the maximum signature length that we support, in bits */
>  #define RSA_MAX_SIG_BITS       2048
>
> -static const uint8_t padding_sha1_rsa2048[RSA2048_BYTES - SHA1_SUM_LEN] = {
> -       0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
> -       0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30,
> -       0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a,
> -       0x05, 0x00, 0x04, 0x14
> -};
> -
>  /**
>   * subtract_modulus() - subtract modulus from the given value
>   *
> @@ -209,13 +164,14 @@ static int pow_mod(const struct rsa_public_key *key, uint32_t *inout)
>  }
>
>  static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
> -               const uint32_t sig_len, const uint8_t *hash)
> +                         const uint32_t sig_len, const uint8_t *hash,
> +                         struct checksum_algo *algo)
>  {
>         const uint8_t *padding;
>         int pad_len;
>         int ret;
>
> -       if (!key || !sig || !hash)
> +       if (!key || !sig || !hash || !algo)
>                 return -EIO;
>
>         if (sig_len != (key->len * sizeof(uint32_t))) {
> @@ -223,6 +179,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
>                 return -EINVAL;
>         }
>
> +       debug("Checksum algorithm: %s", algo->name);
> +
>         /* Sanity check for stack size */
>         if (sig_len > RSA_MAX_SIG_BITS / 8) {
>                 debug("Signature length %u exceeds maximum %d\n", sig_len,
> @@ -238,9 +196,8 @@ static int rsa_verify_key(const struct rsa_public_key *key, const uint8_t *sig,
>         if (ret)
>                 return ret;
>
> -       /* Determine padding to use depending on the signature type. */
> -       padding = padding_sha1_rsa2048;
> -       pad_len = RSA2048_BYTES - SHA1_SUM_LEN;
> +       padding = algo->rsa_padding;
> +       pad_len = RSA2048_BYTES - algo->checksum_len;
>
>         /* Check pkcs1.5 padding bytes. */
>         if (memcmp(buf, padding, pad_len)) {
> @@ -309,7 +266,7 @@ static int rsa_verify_with_keynode(struct image_sign_info *info,
>         }
>
>         debug("key length %d\n", key.len);
> -       ret = rsa_verify_key(&key, sig, sig_len, hash);
> +       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;
> @@ -323,12 +280,22 @@ int rsa_verify(struct image_sign_info *info,
>                uint8_t *sig, uint sig_len)
>  {
>         const void *blob = info->fdt_blob;
> -       uint8_t hash[SHA1_SUM_LEN];
> +       /* Reserve memory for maximum checksum-length */
> +       uint8_t hash[RSA2048_BYTES];
>         int ndepth, noffset;
>         int sig_node, node;
>         char name[100];
> -       sha1_context ctx;
> -       int ret, i;
> +       int ret;
> +
> +       /*
> +        * Verify that the checksum-length does not exceed the
> +        * rsa-signature-length
> +        */
> +       if (info->algo->checksum->checksum_len > RSA2048_BYTES) {
> +               debug("%s: invlaid checksum-algorithm %s for RSA2048\n",
> +                     __func__, info->algo->checksum->name);
> +               return -EINVAL;
> +       }
>
>         sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME);
>         if (sig_node < 0) {
> @@ -336,10 +303,8 @@ int rsa_verify(struct image_sign_info *info,
>                 return -ENOENT;
>         }
>
> -       sha1_starts(&ctx);
> -       for (i = 0; i < region_count; i++)
> -               sha1_update(&ctx, region[i].data, region[i].size);
> -       sha1_finish(&ctx, hash);
> +       /* Calculate checksum with checksum-algorithm */
> +       info->algo->checksum->calculate(region, region_count, hash);
>
>         /* See if we must use a particular key */
>         if (info->required_keynode != -1) {
> diff --git a/test/vboot/sign-configs.its b/test/vboot/sign-configs-sha1.its
> similarity index 100%
> rename from test/vboot/sign-configs.its
> rename to test/vboot/sign-configs-sha1.its
> diff --git a/test/vboot/sign-configs-sha256.its b/test/vboot/sign-configs-sha256.its
> new file mode 100644
> index 0000000..1b3432e
> --- /dev/null
> +++ b/test/vboot/sign-configs-sha256.its
> @@ -0,0 +1,45 @@
> +/dts-v1/;
> +
> +/ {
> +       description = "Chrome OS kernel image with one or more FDT blobs";
> +       #address-cells = <1>;
> +
> +       images {
> +               kernel at 1 {
> +                       data = /incbin/("test-kernel.bin");
> +                       type = "kernel_noload";
> +                       arch = "sandbox";
> +                       os = "linux";
> +                       compression = "none";
> +                       load = <0x4>;
> +                       entry = <0x8>;
> +                       kernel-version = <1>;
> +                       hash at 1 {
> +                               algo = "sha256";
> +                       };
> +               };
> +               fdt at 1 {
> +                       description = "snow";
> +                       data = /incbin/("sandbox-kernel.dtb");
> +                       type = "flat_dt";
> +                       arch = "sandbox";
> +                       compression = "none";
> +                       fdt-version = <1>;
> +                       hash at 1 {
> +                               algo = "sha256";
> +                       };
> +               };
> +       };
> +       configurations {
> +               default = "conf at 1";
> +               conf at 1 {
> +                       kernel = "kernel at 1";
> +                       fdt = "fdt at 1";
> +                       signature at 1 {
> +                               algo = "sha256,rsa2048";
> +                               key-name-hint = "dev";
> +                               sign-images = "fdt", "kernel";
> +                       };
> +               };
> +       };
> +};
> diff --git a/test/vboot/sign-images.its b/test/vboot/sign-images-sha1.its
> similarity index 100%
> rename from test/vboot/sign-images.its
> rename to test/vboot/sign-images-sha1.its
> diff --git a/test/vboot/sign-images-sha256.its b/test/vboot/sign-images-sha256.its
> new file mode 100644
> index 0000000..e6aa9fc
> --- /dev/null
> +++ b/test/vboot/sign-images-sha256.its
> @@ -0,0 +1,42 @@
> +/dts-v1/;
> +
> +/ {
> +       description = "Chrome OS kernel image with one or more FDT blobs";
> +       #address-cells = <1>;
> +
> +       images {
> +               kernel at 1 {
> +                       data = /incbin/("test-kernel.bin");
> +                       type = "kernel_noload";
> +                       arch = "sandbox";
> +                       os = "linux";
> +                       compression = "none";
> +                       load = <0x4>;
> +                       entry = <0x8>;
> +                       kernel-version = <1>;
> +                       signature at 1 {
> +                               algo = "sha256,rsa2048";
> +                               key-name-hint = "dev";
> +                       };
> +               };
> +               fdt at 1 {
> +                       description = "snow";
> +                       data = /incbin/("sandbox-kernel.dtb");
> +                       type = "flat_dt";
> +                       arch = "sandbox";
> +                       compression = "none";
> +                       fdt-version = <1>;
> +                       signature at 1 {
> +                               algo = "sha256,rsa2048";
> +                               key-name-hint = "dev";
> +                       };
> +               };
> +       };
> +       configurations {
> +               default = "conf at 1";
> +               conf at 1 {
> +                       kernel = "kernel at 1";
> +                       fdt = "fdt at 1";
> +               };
> +       };
> +};
> diff --git a/test/vboot/vboot_test.sh b/test/vboot/vboot_test.sh
> index bb2c605..27b221a 100755
> --- a/test/vboot/vboot_test.sh
> +++ b/test/vboot/vboot_test.sh
> @@ -6,6 +6,14 @@
>  #
>  # SPDX-License-Identifier:     GPL-2.0+
>
> +# Args:
> +#      $1:     sha256 or sha1 (default)
> +if [ -z "$1" ]; then
> +       sha=sha1
> +else
> +       sha=$1
> +fi

The test looks good, but can we please do both sha1 and sha256? It is
supposed to be an automated test so running it twice or with arguments
is not very friendly.

> +
>  set -e
>
>  # Run U-Boot and report the result
> @@ -70,7 +78,7 @@ head -c 5000 /dev/zero >test-kernel.bin
>
>  # Build the FIT, but don't sign anything yet
>  echo Build FIT with signed images
> -${mkimage} -D "${dtc}" -f sign-images.its test.fit >${tmp}
> +${mkimage} -D "${dtc}" -f sign-images-$sha.its test.fit >${tmp}
>
>  run_uboot "unsigned signatures:" "dev-"
>
> @@ -85,9 +93,9 @@ run_uboot "signed images" "dev+"
>  dtc -p 0x1000 sandbox-u-boot.dts -O dtb -o sandbox-u-boot.dtb
>
>  echo Build FIT with signed configuration
> -${mkimage} -D "${dtc}" -f sign-configs.its test.fit >${tmp}
> +${mkimage} -D "${dtc}" -f sign-configs-$sha.its test.fit >${tmp}
>
> -run_uboot "unsigned config" "sha1+ OK"
> +run_uboot "unsigned config" $sha"+ OK"
>
>  # Sign images with our dev keys
>  echo Sign images
> @@ -107,7 +115,7 @@ popd >/dev/null
>
>  echo
>  if ${ok}; then
> -       echo "Test passed"
> +       echo "Test $sha passed"
>  else
> -       echo "Test failed"
> +       echo "Test $sha failed"
>  fi
> --
> 1.8.3.1
>

Regards,
Simon


More information about the U-Boot mailing list