diff options
Diffstat (limited to 'lib/rsa')
-rw-r--r-- | lib/rsa/Makefile | 2 | ||||
-rw-r--r-- | lib/rsa/rsa-checksum.c | 51 | ||||
-rw-r--r-- | lib/rsa/rsa-sign.c | 258 |
3 files changed, 90 insertions, 221 deletions
diff --git a/lib/rsa/Makefile b/lib/rsa/Makefile index 8b75d41f04b..c9ac72c1e26 100644 --- a/lib/rsa/Makefile +++ b/lib/rsa/Makefile @@ -5,6 +5,6 @@ # (C) Copyright 2000-2007 # Wolfgang Denk, DENX Software Engineering, wd@denx.de. -obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY) += rsa-verify.o rsa-checksum.o +obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY) += rsa-verify.o obj-$(CONFIG_$(SPL_TPL_)RSA_VERIFY_WITH_PKEY) += rsa-keyprop.o obj-$(CONFIG_RSA_SOFTWARE_EXP) += rsa-mod-exp.o diff --git a/lib/rsa/rsa-checksum.c b/lib/rsa/rsa-checksum.c deleted file mode 100644 index e60debb7df3..00000000000 --- a/lib/rsa/rsa-checksum.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0+ -/* - * Copyright (c) 2013, Andreas Oetken. - */ - -#ifndef USE_HOSTCC -#include <common.h> -#include <fdtdec.h> -#include <asm/byteorder.h> -#include <linux/errno.h> -#include <asm/unaligned.h> -#include <hash.h> -#else -#include "fdt_host.h" -#endif -#include <u-boot/rsa.h> - -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; - - ret = algo->hash_init(algo, &ctx); - if (ret) - return ret; - - for (i = 0; i < region_count - 1; i++) { - ret = algo->hash_update(algo, ctx, region[i].data, - region[i].size, 0); - if (ret) - return ret; - } - - ret = algo->hash_update(algo, ctx, region[i].data, region[i].size, 1); - if (ret) - return ret; - ret = algo->hash_finish(algo, ctx, checksum, algo->digest_size); - if (ret) - return ret; - - return 0; -} diff --git a/lib/rsa/rsa-sign.c b/lib/rsa/rsa-sign.c index 1f0d81bd7a3..5a1583b8f75 100644 --- a/lib/rsa/rsa-sign.c +++ b/lib/rsa/rsa-sign.c @@ -9,7 +9,9 @@ #include <string.h> #include <image.h> #include <time.h> +#include <u-boot/fdt-libcrypto.h> #include <openssl/bn.h> +#include <openssl/ec.h> #include <openssl/rsa.h> #include <openssl/pem.h> #include <openssl/err.h> @@ -51,19 +53,21 @@ static int rsa_err(const char *msg) * * @keydir: Directory containins the key * @name Name of key file (will have a .crt extension) - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ -static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap) +static int rsa_pem_get_pub_key(const char *keydir, const char *name, EVP_PKEY **evpp) { char path[1024]; - EVP_PKEY *key; + EVP_PKEY *key = NULL; X509 *cert; - RSA *rsa; FILE *f; int ret; - *rsap = NULL; + if (!evpp) + return -EINVAL; + + *evpp = NULL; snprintf(path, sizeof(path), "%s/%s.crt", keydir, name); f = fopen(path, "r"); if (!f) { @@ -88,22 +92,12 @@ static int rsa_pem_get_pub_key(const char *keydir, const char *name, RSA **rsap) goto err_pubkey; } - /* Convert to a RSA_style key. */ - rsa = EVP_PKEY_get1_RSA(key); - if (!rsa) { - rsa_err("Couldn't convert to a RSA style key"); - ret = -EINVAL; - goto err_rsa; - } fclose(f); - EVP_PKEY_free(key); + *evpp = key; X509_free(cert); - *rsap = rsa; return 0; -err_rsa: - EVP_PKEY_free(key); err_pubkey: X509_free(cert); err_cert: @@ -117,19 +111,20 @@ err_cert: * @keydir: Key prefix * @name Name of key * @engine Engine to use - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_engine_get_pub_key(const char *keydir, const char *name, - ENGINE *engine, RSA **rsap) + ENGINE *engine, EVP_PKEY **evpp) { const char *engine_id; char key_id[1024]; - EVP_PKEY *key; - RSA *rsa; - int ret; + EVP_PKEY *key = NULL; + + if (!evpp) + return -EINVAL; - *rsap = NULL; + *evpp = NULL; engine_id = ENGINE_get_id(engine); @@ -165,22 +160,9 @@ static int rsa_engine_get_pub_key(const char *keydir, const char *name, if (!key) return rsa_err("Failure loading public key from engine"); - /* Convert to a RSA_style key. */ - rsa = EVP_PKEY_get1_RSA(key); - if (!rsa) { - rsa_err("Couldn't convert to a RSA style key"); - ret = -EINVAL; - goto err_rsa; - } - - EVP_PKEY_free(key); - *rsap = rsa; + *evpp = key; return 0; - -err_rsa: - EVP_PKEY_free(key); - return ret; } /** @@ -189,15 +171,15 @@ err_rsa: * @keydir: Directory containing the key (PEM file) or key prefix (engine) * @name Name of key file (will have a .crt extension) * @engine Engine to use - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_get_pub_key(const char *keydir, const char *name, - ENGINE *engine, RSA **rsap) + ENGINE *engine, EVP_PKEY **evpp) { if (engine) - return rsa_engine_get_pub_key(keydir, name, engine, rsap); - return rsa_pem_get_pub_key(keydir, name, rsap); + return rsa_engine_get_pub_key(keydir, name, engine, evpp); + return rsa_pem_get_pub_key(keydir, name, evpp); } /** @@ -205,18 +187,26 @@ static int rsa_get_pub_key(const char *keydir, const char *name, * * @keydir: Directory containing the key * @name Name of key file (will have a .key extension) - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_pem_get_priv_key(const char *keydir, const char *name, - RSA **rsap) + const char *keyfile, EVP_PKEY **evpp) { - char path[1024]; - RSA *rsa; - FILE *f; + char path[1024] = {0}; + FILE *f = NULL; + + if (!evpp) + return -EINVAL; + + *evpp = NULL; + if (keydir && name) + snprintf(path, sizeof(path), "%s/%s.key", keydir, name); + else if (keyfile) + snprintf(path, sizeof(path), "%s", keyfile); + else + return -EINVAL; - *rsap = NULL; - snprintf(path, sizeof(path), "%s/%s.key", keydir, name); f = fopen(path, "r"); if (!f) { fprintf(stderr, "Couldn't open RSA private key: '%s': %s\n", @@ -224,14 +214,12 @@ static int rsa_pem_get_priv_key(const char *keydir, const char *name, return -ENOENT; } - rsa = PEM_read_RSAPrivateKey(f, 0, NULL, path); - if (!rsa) { + if (!PEM_read_PrivateKey(f, evpp, NULL, path)) { rsa_err("Failure reading private key"); fclose(f); return -EPROTO; } fclose(f); - *rsap = rsa; return 0; } @@ -242,23 +230,27 @@ static int rsa_pem_get_priv_key(const char *keydir, const char *name, * @keydir: Key prefix * @name Name of key * @engine Engine to use - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_engine_get_priv_key(const char *keydir, const char *name, - ENGINE *engine, RSA **rsap) + const char *keyfile, + ENGINE *engine, EVP_PKEY **evpp) { const char *engine_id; char key_id[1024]; - EVP_PKEY *key; - RSA *rsa; - int ret; + EVP_PKEY *key = NULL; - *rsap = NULL; + if (!evpp) + return -EINVAL; engine_id = ENGINE_get_id(engine); if (engine_id && !strcmp(engine_id, "pkcs11")) { + if (!keydir && !name) { + fprintf(stderr, "Please use 'keydir' with PKCS11\n"); + return -EINVAL; + } if (keydir) if (strstr(keydir, "object=")) snprintf(key_id, sizeof(key_id), @@ -273,14 +265,19 @@ static int rsa_engine_get_priv_key(const char *keydir, const char *name, "pkcs11:object=%s;type=private", name); } else if (engine_id) { - if (keydir) + if (keydir && name) snprintf(key_id, sizeof(key_id), "%s%s", keydir, name); - else + else if (keydir) snprintf(key_id, sizeof(key_id), "%s", name); + else if (keyfile) + snprintf(key_id, sizeof(key_id), "%s", keyfile); + else + return -EINVAL; + } else { fprintf(stderr, "Engine not supported\n"); return -ENOTSUP; @@ -290,22 +287,9 @@ static int rsa_engine_get_priv_key(const char *keydir, const char *name, if (!key) return rsa_err("Failure loading private key from engine"); - /* Convert to a RSA_style key. */ - rsa = EVP_PKEY_get1_RSA(key); - if (!rsa) { - rsa_err("Couldn't convert to a RSA style key"); - ret = -EINVAL; - goto err_rsa; - } - - EVP_PKEY_free(key); - *rsap = rsa; + *evpp = key; return 0; - -err_rsa: - EVP_PKEY_free(key); - return ret; } /** @@ -314,15 +298,16 @@ err_rsa: * @keydir: Directory containing the key (PEM file) or key prefix (engine) * @name Name of key * @engine Engine to use for signing - * @rsap Returns RSA object, or NULL on failure - * @return 0 if ok, -ve on error (in which case *rsap will be set to NULL) + * @evpp Returns EVP_PKEY object, or NULL on failure + * @return 0 if ok, -ve on error (in which case *evpp will be set to NULL) */ static int rsa_get_priv_key(const char *keydir, const char *name, - ENGINE *engine, RSA **rsap) + const char *keyfile, ENGINE *engine, EVP_PKEY **evpp) { if (engine) - return rsa_engine_get_priv_key(keydir, name, engine, rsap); - return rsa_pem_get_priv_key(keydir, name, rsap); + return rsa_engine_get_priv_key(keydir, name, keyfile, engine, + evpp); + return rsa_pem_get_priv_key(keydir, name, keyfile, evpp); } static int rsa_init(void) @@ -416,12 +401,11 @@ static void rsa_engine_remove(ENGINE *e) } } -static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo, +static int rsa_sign_with_key(EVP_PKEY *pkey, struct padding_algo *padding_algo, struct checksum_algo *checksum_algo, const struct image_region region[], int region_count, uint8_t **sigp, uint *sig_size) { - EVP_PKEY *key; EVP_PKEY_CTX *ckey; EVP_MD_CTX *context; int ret = 0; @@ -429,16 +413,7 @@ static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo, uint8_t *sig; int i; - key = EVP_PKEY_new(); - if (!key) - return rsa_err("EVP_PKEY object creation failed"); - - if (!EVP_PKEY_set1_RSA(key, rsa)) { - ret = rsa_err("EVP key setup failed"); - goto err_set; - } - - size = EVP_PKEY_size(key); + size = EVP_PKEY_size(pkey); sig = malloc(size); if (!sig) { fprintf(stderr, "Out of memory for signature (%zu bytes)\n", @@ -454,7 +429,7 @@ static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo, } EVP_MD_CTX_init(context); - ckey = EVP_PKEY_CTX_new(key, NULL); + ckey = EVP_PKEY_CTX_new(pkey, NULL); if (!ckey) { ret = rsa_err("EVP key context creation failed"); goto err_create; @@ -462,7 +437,7 @@ static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo, if (EVP_DigestSignInit(context, &ckey, checksum_algo->calculate_sign(), - NULL, key) <= 0) { + NULL, pkey) <= 0) { ret = rsa_err("Signer setup failed"); goto err_sign; } @@ -497,7 +472,6 @@ static int rsa_sign_with_key(RSA *rsa, struct padding_algo *padding_algo, EVP_MD_CTX_reset(context); #endif EVP_MD_CTX_destroy(context); - EVP_PKEY_free(key); debug("Got signature: %d bytes, expected %zu\n", *sig_size, size); *sigp = sig; @@ -510,8 +484,6 @@ err_sign: err_create: free(sig); err_alloc: -err_set: - EVP_PKEY_free(key); return ret; } @@ -519,7 +491,7 @@ int rsa_sign(struct image_sign_info *info, const struct image_region region[], int region_count, uint8_t **sigp, uint *sig_len) { - RSA *rsa; + EVP_PKEY *pkey = NULL; ENGINE *e = NULL; int ret; @@ -533,15 +505,16 @@ int rsa_sign(struct image_sign_info *info, goto err_engine; } - ret = rsa_get_priv_key(info->keydir, info->keyname, e, &rsa); + ret = rsa_get_priv_key(info->keydir, info->keyname, info->keyfile, + e, &pkey); if (ret) goto err_priv; - ret = rsa_sign_with_key(rsa, info->padding, info->checksum, region, + ret = rsa_sign_with_key(pkey, info->padding, info->checksum, region, region_count, sigp, sig_len); if (ret) goto err_sign; - RSA_free(rsa); + EVP_PKEY_free(pkey); if (info->engine_id) rsa_engine_remove(e); rsa_remove(); @@ -549,7 +522,7 @@ int rsa_sign(struct image_sign_info *info, return ret; err_sign: - RSA_free(rsa); + EVP_PKEY_free(pkey); err_priv: if (info->engine_id) rsa_engine_remove(e); @@ -680,70 +653,6 @@ int rsa_get_params(RSA *key, uint64_t *exponent, uint32_t *n0_invp, return ret; } -static int fdt_add_bignum(void *blob, int noffset, const char *prop_name, - BIGNUM *num, int num_bits) -{ - int nwords = num_bits / 32; - int size; - uint32_t *buf, *ptr; - BIGNUM *tmp, *big2, *big32, *big2_32; - BN_CTX *ctx; - int ret; - - tmp = BN_new(); - big2 = BN_new(); - big32 = BN_new(); - big2_32 = BN_new(); - - /* - * Note: This code assumes that all of the above succeed, or all fail. - * In practice memory allocations generally do not fail (unless the - * process is killed), so it does not seem worth handling each of these - * as a separate case. Technicaly this could leak memory on failure, - * but a) it won't happen in practice, and b) it doesn't matter as we - * will immediately exit with a failure code. - */ - if (!tmp || !big2 || !big32 || !big2_32) { - fprintf(stderr, "Out of memory (bignum)\n"); - return -ENOMEM; - } - ctx = BN_CTX_new(); - if (!ctx) { - fprintf(stderr, "Out of memory (bignum context)\n"); - return -ENOMEM; - } - BN_set_word(big2, 2L); - BN_set_word(big32, 32L); - BN_exp(big2_32, big2, big32, ctx); /* B = 2^32 */ - - size = nwords * sizeof(uint32_t); - buf = malloc(size); - if (!buf) { - fprintf(stderr, "Out of memory (%d bytes)\n", size); - return -ENOMEM; - } - - /* Write out modulus as big endian array of integers */ - for (ptr = buf + nwords - 1; ptr >= buf; ptr--) { - BN_mod(tmp, num, big2_32, ctx); /* n = N mod B */ - *ptr = cpu_to_fdt32(BN_get_word(tmp)); - BN_rshift(num, num, 32); /* N = N/B */ - } - - /* - * We try signing with successively increasing size values, so this - * might fail several times - */ - ret = fdt_setprop(blob, noffset, prop_name, buf, size); - free(buf); - BN_free(tmp); - BN_free(big2); - BN_free(big32); - BN_free(big2_32); - - return ret ? -FDT_ERR_NOSPACE : 0; -} - int rsa_add_verify_data(struct image_sign_info *info, void *keydest) { BIGNUM *modulus, *r_squared; @@ -754,6 +663,7 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) int ret; int bits; RSA *rsa; + EVP_PKEY *pkey = NULL; ENGINE *e = NULL; debug("%s: Getting verification data\n", __func__); @@ -762,9 +672,15 @@ int rsa_add_verify_data(struct image_sign_info *info, void *keydest) if (ret) return ret; } - ret = rsa_get_pub_key(info->keydir, info->keyname, e, &rsa); + ret = rsa_get_pub_key(info->keydir, info->keyname, e, &pkey); if (ret) goto err_get_pub_key; +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) + rsa = EVP_PKEY_get1_RSA(pkey); +#else + rsa = EVP_PKEY_get0_RSA(pkey); +#endif ret = rsa_get_params(rsa, &exponent, &n0_inv, &modulus, &r_squared); if (ret) goto err_get_params; @@ -834,7 +750,11 @@ done: if (ret) ret = ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EIO; err_get_params: +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x02070000fL) RSA_free(rsa); +#endif + EVP_PKEY_free(pkey); err_get_pub_key: if (info->engine_id) rsa_engine_remove(e); |