diff options
author | AKASHI Takahiro | 2020-07-21 19:35:17 +0900 |
---|---|---|
committer | Heinrich Schuchardt | 2020-07-22 12:33:55 +0200 |
commit | b2a1049b5c364961726add2796b6028b27008ca4 (patch) | |
tree | be22e76abf40da55393404994009dcf1350cda63 /lib/crypto | |
parent | a58dfd29698c65a22e3956e7aae96c7ce7fdddd3 (diff) |
lib: crypto: add public_key_verify_signature()
This function will be called from x509_check_for_self_signed() and
pkcs7_verify_one(), which will be imported from linux in a later patch.
While it does exist in linux code and has a similar functionality of
rsa_verify(), it calls further linux-specific interfaces inside.
That could lead to more files being imported from linux.
So simply re-implement it here instead of re-using the code.
Signed-off-by: AKASHI Takahiro <takahiro.akashi@linaro.org>
Diffstat (limited to 'lib/crypto')
-rw-r--r-- | lib/crypto/public_key.c | 70 |
1 files changed, 69 insertions, 1 deletions
diff --git a/lib/crypto/public_key.c b/lib/crypto/public_key.c index e12ebbb3d0c..a8f7fbed458 100644 --- a/lib/crypto/public_key.c +++ b/lib/crypto/public_key.c @@ -25,7 +25,10 @@ #include <keys/asymmetric-subtype.h> #endif #include <crypto/public_key.h> -#ifndef __UBOOT__ +#ifdef __UBOOT__ +#include <image.h> +#include <u-boot/rsa.h> +#else #include <crypto/akcipher.h> #endif @@ -80,6 +83,71 @@ void public_key_signature_free(struct public_key_signature *sig) } EXPORT_SYMBOL_GPL(public_key_signature_free); +/** + * public_key_verify_signature - Verify a signature using a public key. + * + * @pkey: Public key + * @sig: Signature + * + * Verify a signature, @sig, using a RSA public key, @pkey. + * + * Return: 0 - verified, non-zero error code - otherwise + */ +int public_key_verify_signature(const struct public_key *pkey, + const struct public_key_signature *sig) +{ + struct image_sign_info info; + struct image_region region; + int ret; + + pr_devel("==>%s()\n", __func__); + + if (!pkey || !sig) + return -EINVAL; + + if (pkey->key_is_private) + return -EINVAL; + + memset(&info, '\0', sizeof(info)); + info.padding = image_get_padding_algo("pkcs-1.5"); + /* + * Note: image_get_[checksum|crypto]_algo takes a string + * argument like "<checksum>,<crypto>" + * TODO: support other hash algorithms + */ + if (strcmp(sig->pkey_algo, "rsa") || (sig->s_size * 8) != 2048) { + pr_warn("Encryption is not RSA2048: %s%d\n", + sig->pkey_algo, sig->s_size * 8); + return -ENOPKG; + } + if (!strcmp(sig->hash_algo, "sha1")) { + info.checksum = image_get_checksum_algo("sha1,rsa2048"); + info.name = "sha1,rsa2048"; + } else if (!strcmp(sig->hash_algo, "sha256")) { + info.checksum = image_get_checksum_algo("sha256,rsa2048"); + info.name = "sha256,rsa2048"; + } else { + pr_warn("unknown msg digest algo: %s\n", sig->hash_algo); + return -ENOPKG; + } + info.crypto = image_get_crypto_algo(info.name); + if (IS_ERR(info.checksum) || IS_ERR(info.crypto)) + return -ENOPKG; + + info.key = pkey->key; + info.keylen = pkey->keylen; + + region.data = sig->digest; + region.size = sig->digest_size; + + if (rsa_verify_with_pkey(&info, sig->digest, sig->s, sig->s_size)) + ret = -EKEYREJECTED; + else + ret = 0; + + pr_devel("<==%s() = %d\n", __func__, ret); + return ret; +} #else /* * Destroy a public key algorithm key. |