The OpenSSL Provider API support routes FIT signing-key loading through
OSSL_STORE on OpenSSL >= 3 (USE_PKCS11_PROVIDER), but only for key files:
rsa_pem_get_priv_key() fopen()s the path before OSSL_STORE_open(), so a pkcs11:
token URI fails with -ENOENT. The legacy engine path that handled tokens is
compiled out on OpenSSL >= 3, so FIT signing with a token key silently produces
an unsigned FIT (a configuration signature node with no value or
hashed-strings).

Load a pkcs11: key URI in the provider path directly through OSSL_STORE and the
pkcs11 provider: skip the fopen, append ";type=private" if absent. The PIN
travels in the URI (pin-value=); MKIMAGE_SIGN_PIN is unaffected.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Johannes Schneider <[email protected]>
---
Follow-up to Eddie Kovsky's "rsa: Add support for OpenSSL Provider API"
(https://lore.kernel.org/u-boot/[email protected]).

How we use it: our build signs production FIT images with an RSA key kept on a
PKCS#11 token, so the private key never lands on the build host or in CI
artifacts. mkimage gets the key as a "pkcs11:...;type=private" URI; the
provider path today handles file keys only, so with the engine gone on
OpenSSL >= 3 a token-backed FIT silently comes out unsigned -- this closes that
gap.

--- a/lib/rsa/rsa-sign.c
+++ b/lib/rsa/rsa-sign.c
@@ -237,6 +237,49 @@
                return -EINVAL;
 
        *evpp = NULL;
+
+#ifdef USE_PKCS11_PROVIDER
+       /* A pkcs11: token URI is not a file: load it via OSSL_STORE + the 
pkcs11 provider instead of fopen (PIN in the URI, pin-value=). */
+       if (keydir && !strncmp(keydir, "pkcs11:", 7)) {
+               char uri[1200];
+               OSSL_STORE_CTX *p11_store;
+               EVP_PKEY *p11_key = NULL;
+
+               if (strstr(keydir, "type="))
+                       snprintf(uri, sizeof(uri), "%s", keydir);
+               else
+                       snprintf(uri, sizeof(uri), "%s;type=private", keydir);
+
+               if (!OSSL_PROVIDER_try_load(NULL, "default", true))
+                       ERR(1, "OSSL_PROVIDER_try_load(default)");
+               if (!OSSL_PROVIDER_try_load(NULL, "pkcs11", true))
+                       ERR(1, "OSSL_PROVIDER_try_load(pkcs11)");
+
+               p11_store = OSSL_STORE_open(uri, NULL, NULL, NULL, NULL);
+               ERR(!p11_store, "OSSL_STORE_open(%s)", uri);
+               while (!OSSL_STORE_eof(p11_store)) {
+                       OSSL_STORE_INFO *info = OSSL_STORE_load(p11_store);
+
+                       if (!info) {
+                               if (OSSL_STORE_error(p11_store))
+                                       break;
+                               continue;
+                       }
+                       if (OSSL_STORE_INFO_get_type(info) == 
OSSL_STORE_INFO_PKEY)
+                               p11_key = OSSL_STORE_INFO_get1_PKEY(info);
+                       OSSL_STORE_INFO_free(info);
+                       if (p11_key)
+                               break;
+               }
+               OSSL_STORE_close(p11_store);
+               if (!p11_key) {
+                       fprintf(stderr, "No private key found at '%s'\n", uri);
+                       return -EPROTO;
+               }
+               *evpp = p11_key;
+               return 0;
+       }
+#endif
        if (keydir && name)
                snprintf(path, sizeof(path), "%s/%s.key", keydir, name);
        else if (keyfile)

Reply via email to