]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
lib: crypto: add public_key_verify_signature()
authorAKASHI Takahiro <takahiro.akashi@linaro.org>
Tue, 21 Jul 2020 10:35:17 +0000 (19:35 +0900)
committerHeinrich Schuchardt <xypron.glpk@gmx.de>
Wed, 22 Jul 2020 10:33:55 +0000 (12:33 +0200)
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>
include/crypto/public_key.h
lib/crypto/public_key.c

index 436a1ee1ee647fe08adaf6b18e6de252593f3159..3ba90fcc3483171fa47faace1ebe639161dbd50c 100644 (file)
@@ -82,9 +82,9 @@ extern int decrypt_blob(struct kernel_pkey_params *, const void *, void *);
 extern int create_signature(struct kernel_pkey_params *, const void *, void *);
 extern int verify_signature(const struct key *,
                            const struct public_key_signature *);
+#endif /* __UBOOT__ */
 
 int public_key_verify_signature(const struct public_key *pkey,
                                const struct public_key_signature *sig);
-#endif /* !__UBOOT__ */
 
 #endif /* _LINUX_PUBLIC_KEY_H */
index e12ebbb3d0c533a169a66aacbfb2b70d23cc4cf2..a8f7fbed458a70f626f11825003a0b2703b57abf 100644 (file)
 #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.