Merge patch series "Add preload_check_sign tool"
authorTom Rini <trini@konsulko.com>
Fri, 21 Feb 2025 14:34:34 +0000 (08:34 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 21 Feb 2025 17:37:27 +0000 (11:37 -0600)
Paul HENRYS <paul.henrys_ext@softathome.com> says:

This serie of patches adds a new tool to authenticate files signed
with a preload header.
This tool is also used in the tests to actually verify the
authenticity of the file signed with such a preload header.

Link: https://lore.kernel.org/r/20250212093126.3722186-1-paul.henrys_ext@softathome.com
1  2 
tools/binman/ftest.py
tools/image-host.c

Simple merge
@@@ -1397,3 -1393,139 +1402,139 @@@ int fit_check_sign(const void *fit, con
        return ret;
  }
  #endif
 -      for (i=0 ; i < region_count ; ++i) {
+ #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