rsa: Add rsa_verify_openssl() to use openssl for host builds

rsa_verify_openssl() is used in lib/rsa/rsa-verify.c to authenticate data
when building host tools.

Signed-off-by: Paul HENRYS <paul.henrys_ext@softathome.com>
This commit is contained in:
Paul HENRYS 2025-02-24 22:20:50 +01:00 committed by Tom Rini
parent dbb9e136b8
commit 942c8c8e66
3 changed files with 164 additions and 0 deletions

View File

@ -1688,6 +1688,24 @@ struct sig_header_s {
*/
int image_pre_load(ulong addr);
#if defined(USE_HOSTCC)
/**
* rsa_verify_openssl() - Verify a signature against some data with openssl API
*
* Verify a RSA PKCS1.5/PSS signature against an expected hash.
*
* @info: Specifies the key and algorithms
* @region: Pointer to the input data
* @region_count: Number of region
* @sig: Signature
* @sig_len: Number of bytes in the signature
* Return: 0 if verified, -ve on error
*/
int rsa_verify_openssl(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len);
#endif
/**
* fit_image_verify_required_sigs() - Verify signatures marked as 'required'
*

View File

@ -565,6 +565,11 @@ int rsa_verify(struct image_sign_info *info,
uint8_t hash[info->crypto->key_len];
int ret;
#ifdef USE_HOSTCC
if (!info->fdt_blob)
return rsa_verify_openssl(info, region, region_count, sig, sig_len);
#endif
/*
* Verify that the checksum-length does not exceed the
* rsa-signature-length

View File

@ -19,6 +19,11 @@
#include <openssl/evp.h>
#endif
#if CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)
#include <openssl/rsa.h>
#include <openssl/err.h>
#endif
/**
* fit_set_hash_value - set hash value in requested has node
* @fit: pointer to the FIT format image header
@ -1401,3 +1406,139 @@ int fit_check_sign(const void *fit, const void *key,
return ret;
}
#endif
#if CONFIG_IS_ENABLED(IMAGE_PRE_LOAD)
/**
* rsa_verify_openssl() - Verify a signature against some data with openssl API
*
* Verify a RSA PKCS1.5/PSS signature against an expected hash.
*
* @info: Specifies the key and algorithms
* @region: Pointer to the input data
* @region_count: Number of region
* @sig: Signature
* @sig_len: Number of bytes in the signature
* Return: 0 if verified, -ve on error
*/
int rsa_verify_openssl(struct image_sign_info *info,
const struct image_region region[], int region_count,
uint8_t *sig, uint sig_len)
{
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ckey = NULL;
EVP_MD_CTX *ctx = NULL;
int pad;
int size;
int i;
int ret = 0;
if (!info) {
fprintf(stderr, "No info provided\n");
ret = -EINVAL;
goto out;
}
if (!info->key) {
fprintf(stderr, "No key provided\n");
ret = -EINVAL;
goto out;
}
if (!info->checksum) {
fprintf(stderr, "No checksum information\n");
ret = -EINVAL;
goto out;
}
if (!info->padding) {
fprintf(stderr, "No padding information\n");
ret = -EINVAL;
goto out;
}
if (region_count < 1) {
fprintf(stderr, "Invalid value for region_count: %d\n", region_count);
ret = -EINVAL;
goto out;
}
pkey = (EVP_PKEY *)info->key;
ckey = EVP_PKEY_CTX_new(pkey, NULL);
if (!ckey) {
ret = -ENOMEM;
fprintf(stderr, "EVK key context setup failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
size = EVP_PKEY_size(pkey);
if (size > sig_len) {
fprintf(stderr, "Invalid signature size (%d bytes)\n",
size);
ret = -EINVAL;
goto out;
}
ctx = EVP_MD_CTX_new();
if (!ctx) {
ret = -ENOMEM;
fprintf(stderr, "EVP context creation failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
EVP_MD_CTX_init(ctx);
if (EVP_DigestVerifyInit(ctx, &ckey,
EVP_get_digestbyname(info->checksum->name),
NULL, pkey) <= 0) {
ret = -EINVAL;
fprintf(stderr, "Verifier setup failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
if (!strcmp(info->padding->name, "pkcs-1.5")) {
pad = RSA_PKCS1_PADDING;
} else if (!strcmp(info->padding->name, "pss")) {
pad = RSA_PKCS1_PSS_PADDING;
} else {
ret = -ENOMSG;
fprintf(stderr, "Unsupported padding: %s\n",
info->padding->name);
goto out;
}
if (EVP_PKEY_CTX_set_rsa_padding(ckey, pad) <= 0) {
ret = -EINVAL;
fprintf(stderr, "padding setup has failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
for (i=0 ; i < region_count ; ++i) {
if (EVP_DigestVerifyUpdate(ctx, region[i].data,
region[i].size) <= 0) {
ret = -EINVAL;
fprintf(stderr, "Hashing data failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
}
if (EVP_DigestVerifyFinal(ctx, sig, sig_len) <= 0) {
ret = -EINVAL;
fprintf(stderr, "Verifying digest failed: %s\n",
ERR_error_string(ERR_get_error(), NULL));
goto out;
}
out:
if (ctx)
EVP_MD_CTX_free(ctx);
if (ret)
fprintf(stderr, "Failed to verify signature\n");
return ret;
}
#endif