Replace global RSA methods with per-context callbacks - #675
Open
mtrojnar wants to merge 3 commits into
Open
Conversation
mtrojnar
force-pushed
the
fix-rsa-method-scope-672
branch
3 times, most recently
from
August 12, 2026 19:01
f520426 to
9ab98f8
Compare
mtrojnar
force-pushed
the
fix-rsa-method-scope-672
branch
2 times, most recently
from
August 13, 2026 07:39
71408f4 to
76c05a2
Compare
Open
3 tasks
mtrojnar
force-pushed
the
fix-rsa-method-scope-672
branch
from
August 17, 2026 18:26
23b5e86 to
ed5c1fa
Compare
mtrojnar
force-pushed
the
fix-rsa-method-scope-672
branch
2 times, most recently
from
August 18, 2026 11:26
2a66cfd to
ba0efd5
Compare
Stop registering libp11's RSA EVP_PKEY_METHOD process-wide when a private key is created. Global registration changes method selection for unrelated software and provider-backed RSA keys. Add a per-context callback for returned private EVP_PKEY objects and preserve it when UTIL_CTX recreates its libp11 context. Have the ENGINE use this hook to attach its method dispatch only to keys loaded by that ENGINE, keeping ENGINE integration out of the public libp11 implementation.
Register a callback on each provider utility context so private-key loading prepares P11_KEYDATA when libp11 creates the carrier EVP_PKEY. Transfer the reference through a provider-owned ex_data index instead of assuming that process-local indexes are shared between separate libp11 copies. Detach the keydata before releasing the carrier key to break the temporary reference cycle. Ex-data duplication, cleanup, and provider teardown retain well-defined ownership throughout the handoff to STORE.
Verify that loading a PKCS#11 key through the public libp11 API leaves existing and subsequently generated provider-backed software RSA keys unchanged. Exercise ENGINE signing without passing an ENGINE to EVP_PKEY_CTX_new(), so success depends on the key-loading callback. Run it against both raw-RSA-only and native-PSS-only SoftHSM configurations with explicit digest, MGF1, and salt-length parameters. Restrict the provider test to native RSA-PSS with raw RSA disabled and use the same explicit PSS parameters. A successful signature therefore proves the provider path works with a PSS-only device.
mtrojnar
force-pushed
the
fix-rsa-method-scope-672
branch
from
August 18, 2026 13:08
ba0efd5 to
83855fb
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request Type
Related Issue
Fixes #672
Current Behavior
On OpenSSL 3.x,
PKCS11_get_private_key()registers libp11's custom RSAEVP_PKEY_METHODprocess-wide withEVP_PKEY_meth_add0().That registration changes method selection for unrelated software RSA keys.
Provider-backed keys created before the PKCS#11 key can subsequently fail in
operations such as
X509_sign()with:Software RSA keys created afterward can also silently fall back to legacy
implementations instead of remaining backed by the default provider.
The registration also crosses an architecture boundary: the libp11 library
initializes deprecated OpenSSL method integration that belongs to the ENGINE
component.
New Behavior
PKCS11_get_private_key()no longer registers an RSAEVP_PKEY_METHODglobally. Loading a PKCS#11 key therefore does not alter method selection for
unrelated keys.
A new per-context callback API lets integrations customize each returned key:
The callback receives borrowed
PKCS11_KEYandEVP_PKEYobjects and maycustomize the returned key in place. The callback must not free either
object; an error aborts key retrieval and libp11 releases the
EVP_PKEY.The OpenSSL integrations use this callback independently:
PKCS11_pkey_methsdispatch only to keys loaded bythat ENGINE. This preserves native RSA-PSS and software-PSS-over-raw-RSA
behavior without changing process-wide method selection.
P11_KEYDATAin its callback and transfers it to STOREthrough a provider-owned
EVP_PKEYex-data slot. Duplication and cleanupcallbacks retain explicit ownership, and STORE detaches the slot before
releasing the temporary carrier key.
The provider-owned slot avoids assuming that process-local ex-data indexes
are shared between the external libp11 library and the provider's embedded
libp11 copy. Provider operations continue through provider dispatch and do
not depend on ENGINE support.
Scope of Changes
PKCS11_CTX_set_pkey_callback()and thePKCS11_PKEY_CALLBACK_GET_PRIVATE_KEYevent.UTIL_CTXcreates or reloads itsinternal libp11 context.
EVP_PKEY_METHODregistration and its global statefrom the libp11 library.
eng_*code.reference-counted ex-data handoff to KEYMGMT.
callback-selected ENGINE dispatch, raw-RSA-only ENGINE signing, and
native-PSS-only signing through both ENGINE and provider dispatch.
This adds a public libp11 API symbol and callback type. No existing public
symbol or function signature is removed.
Testing
Built with OpenSSL 3.6.3 using strict configuration and ran:
Result: 51 total, 46 passed, 5 skipped due to unavailable ML-DSA/ML-KEM
features, 0 failed.
The provider RSA-PSS test restricts SoftHSM2 to
CKM_RSA_PKCS_PSS, verifiesthat
CKM_RSA_X_509is unavailable, and signs with explicit SHA-256, MGF1,and digest-length salt parameters. Its success therefore covers the target
PSS-only-device behavior directly.
The ENGINE scenario also sets the MGF1 digest and digest-length salt
explicitly, and runs against both raw-RSA-only and native-PSS-only SoftHSM2
configurations.
A clean strict build with
CPPFLAGS=-DOPENSSL_NO_ENGINEalso succeeded.Focused tests in that configuration produced 3 provider passes
(RSA-PSS, RSA-OAEP, and EC signing) and 1 expected ENGINE-dependent skip.
Additional Notes
ENGINE-specific APIs remain confined to
eng_*sources. The provider doesnot route operations through ENGINE, preserving the provider-only OpenSSL 4
architecture.
The provider callback implements key construction and ownership handoff.
Provider signature and asymmetric-cipher mechanism selection remain in the
existing provider operation implementation; this change does not add a
software-PSS-over-
CKM_RSA_X_509provider fallback.License Declaration