This function, and hence rsa_verify(), will perform RSA verification with two essential parameters for a RSA public key in contract of rsa_verify_with_keynode(), which requires additional three parameters stored in FIT image.
It will be used in implementing UEFI secure boot, i.e. image authentication and variable authentication. Signed-off-by: AKASHI Takahiro <takahiro.aka...@linaro.org> --- lib/rsa/rsa-verify.c | 129 +++++++++++++++++++++++++++++++++---------- 1 file changed, 99 insertions(+), 30 deletions(-) diff --git a/lib/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c index 1df42f28c64a..43271a10bb84 100644 --- a/lib/rsa/rsa-verify.c +++ b/lib/rsa/rsa-verify.c @@ -17,9 +17,14 @@ #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__ /* for host tools */ +#undef CONFIG_RSA_VERIFY_WITH_PKEY +#endif + /* Default public exponent for backward compatibility */ #define RSA_DEFAULT_PUBEXP 65537 @@ -344,6 +349,50 @@ static int rsa_verify_key(struct image_sign_info *info, } #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 */ + prop = rsa_gen_key_prop(info->key, info->keylen); + if (!prop) { + debug("Generating necessary parameter for decoding failed\n"); + return -EACCES; + } + + 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. @@ -397,18 +446,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 @@ -421,12 +474,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); @@ -435,30 +482,52 @@ 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 (!ret) - return ret; - } + 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); - /* 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); + info->required_keynode); if (!ret) - break; + 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; + } } } -- 2.21.0 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot