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)
