diff options
author | Tom Rini <trini@konsulko.com> | 2020-03-12 12:45:27 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2020-03-12 12:45:27 -0400 |
commit | e24f0a39d0daa2d8c597650aeb3f559d44a195ae (patch) | |
tree | 650803dabb55a0669b19e6a7069273f703d78b84 /lib/rsa/rsa-verify.c | |
parent | 36bdcf7f3b17ec6d8cec782e7f1d5b0b8014300a (diff) | |
parent | 2201fe70d878074a9176f352693c582d7464a8d1 (diff) |
Merge branch '2020-03-12-rsa-improvements' into next
(Description from AKASHI Takahiro)
extend rsa_verify() for UEFI secure boot:
The current rsa_verify() requires five parameters for a RSA public key
for efficiency while RSA, in theory, requires only two. In addition,
those parameters are expected to come from FIT image.
So this function won't fit very well when we want to use it for the
purpose of implementing UEFI secure boot, in particular, image
authentication as well as variable authentication, where the essential
two parameters are set to be retrieved from one of X509 certificates in
signature database.
So, in this patch, additional three parameters will be calculated on the
fly when rsa_verify() is called without fdt which should contain
parameters above.
This calculation heavily relies on "big-number (or multi-precision)
library." Therefore some routines from BearSSL under MIT license are
imported in this implementation.
Diffstat (limited to 'lib/rsa/rsa-verify.c')
-rw-r--r-- | lib/rsa/rsa-verify.c | 137 |
1 files changed, 108 insertions, 29 deletions
diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 326a5e4ea9..80e817314b 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -18,9 +18,22 @@ #include "mkimage.h" #include <fdt_support.h> #endif +#include <linux/kconfig.h> #include <u-boot/rsa-mod-exp.h> #include <u-boot/rsa.h> +#ifndef __UBOOT__ +/* + * NOTE: + * Since host tools, like mkimage, make use of openssl library for + * RSA encryption, rsa_verify_with_pkey()/rsa_gen_key_prop() are + * of no use and should not be compiled in. + * So just turn off CONFIG_RSA_VERIFY_WITH_PKEY. + */ + +#undef CONFIG_RSA_VERIFY_WITH_PKEY +#endif + /* Default public exponent for backward compatibility */ #define RSA_DEFAULT_PUBEXP 65537 @@ -271,6 +284,7 @@ out: } #endif +#if CONFIG_IS_ENABLED(FIT_SIGNATURE) || IS_ENABLED(CONFIG_RSA_VERIFY_WITH_PKEY) /** * rsa_verify_key() - Verify a signature against some data using RSA Key * @@ -342,7 +356,52 @@ static int rsa_verify_key(struct image_sign_info *info, return 0; } +#endif +#ifdef CONFIG_RSA_VERIFY_WITH_PKEY +/** + * rsa_verify_with_pkey() - Verify a signature against some data using + * only modulus and exponent as RSA key properties. + * @info: Specifies key information + * @hash: Pointer to the expected hash + * @sig: Signature + * @sig_len: Number of bytes in signature + * + * Parse a RSA public key blob in DER format pointed to in @info and fill + * a key_prop structure with properties of the key. Then verify a RSA PKCS1.5 + * signature against an expected hash using the calculated properties. + * + * Return 0 if verified, -ve on error + */ +static int rsa_verify_with_pkey(struct image_sign_info *info, + const void *hash, uint8_t *sig, uint sig_len) +{ + struct key_prop *prop; + int ret; + + /* Public key is self-described to fill key_prop */ + ret = rsa_gen_key_prop(info->key, info->keylen, &prop); + if (ret) { + debug("Generating necessary parameter for decoding failed\n"); + return ret; + } + + ret = rsa_verify_key(info, prop, sig, sig_len, hash, + info->crypto->key_len); + + rsa_free_key_prop(prop); + + return ret; +} +#else +static int rsa_verify_with_pkey(struct image_sign_info *info, + const void *hash, uint8_t *sig, uint sig_len) +{ + return -EACCES; +} +#endif + +#if CONFIG_IS_ENABLED(FIT_SIGNATURE) /** * rsa_verify_with_keynode() - Verify a signature against some data using * information in node with prperties of RSA Key like modulus, exponent etc. @@ -396,18 +455,22 @@ static int rsa_verify_with_keynode(struct image_sign_info *info, return ret; } +#else +static int rsa_verify_with_keynode(struct image_sign_info *info, + const void *hash, uint8_t *sig, + uint sig_len, int node) +{ + return -EACCES; +} +#endif int rsa_verify(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t *sig, uint sig_len) { - const void *blob = info->fdt_blob; /* Reserve memory for maximum checksum-length */ uint8_t hash[info->crypto->key_len]; - int ndepth, noffset; - int sig_node, node; - char name[100]; - int ret; + int ret = -EACCES; /* * Verify that the checksum-length does not exceed the @@ -420,12 +483,6 @@ int rsa_verify(struct image_sign_info *info, return -EINVAL; } - sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); - if (sig_node < 0) { - debug("%s: No signature node found\n", __func__); - return -ENOENT; - } - /* Calculate checksum with checksum-algorithm */ ret = info->checksum->calculate(info->checksum->name, region, region_count, hash); @@ -434,29 +491,51 @@ int rsa_verify(struct image_sign_info *info, return -EINVAL; } - /* See if we must use a particular key */ - if (info->required_keynode != -1) { - ret = rsa_verify_with_keynode(info, hash, sig, sig_len, - info->required_keynode); + if (IS_ENABLED(CONFIG_RSA_VERIFY_WITH_PKEY) && !info->fdt_blob) { + /* don't rely on fdt properties */ + ret = rsa_verify_with_pkey(info, hash, sig, sig_len); + return ret; } - /* Look for a key that matches our hint */ - snprintf(name, sizeof(name), "key-%s", info->keyname); - node = fdt_subnode_offset(blob, sig_node, name); - ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node); - if (!ret) - return ret; + if (CONFIG_IS_ENABLED(FIT_SIGNATURE)) { + const void *blob = info->fdt_blob; + int ndepth, noffset; + int sig_node, node; + char name[100]; + + sig_node = fdt_subnode_offset(blob, 0, FIT_SIG_NODENAME); + if (sig_node < 0) { + debug("%s: No signature node found\n", __func__); + return -ENOENT; + } - /* No luck, so try each of the keys in turn */ - for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, &ndepth); - (noffset >= 0) && (ndepth > 0); - noffset = fdt_next_node(info->fit, noffset, &ndepth)) { - if (ndepth == 1 && noffset != node) { + /* See if we must use a particular key */ + if (info->required_keynode != -1) { ret = rsa_verify_with_keynode(info, hash, sig, sig_len, - noffset); - if (!ret) - break; + info->required_keynode); + return ret; + } + + /* Look for a key that matches our hint */ + snprintf(name, sizeof(name), "key-%s", info->keyname); + node = fdt_subnode_offset(blob, sig_node, name); + ret = rsa_verify_with_keynode(info, hash, sig, sig_len, node); + if (!ret) + return ret; + + /* No luck, so try each of the keys in turn */ + for (ndepth = 0, noffset = fdt_next_node(info->fit, sig_node, + &ndepth); + (noffset >= 0) && (ndepth > 0); + noffset = fdt_next_node(info->fit, noffset, &ndepth)) { + if (ndepth == 1 && noffset != node) { + ret = rsa_verify_with_keynode(info, hash, + sig, sig_len, + noffset); + if (!ret) + break; + } } } |