Repository navigation
Reject key generation for id and label keys a device declines - #11866
Merged
Merged
Conversation
|
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
A configuration-specific test regression remains, and callback compatibility across ten cryptographic algorithms warrants final human validation.
1 open issue
What changed in this PR
This PR prevents wolfCrypt from silently generating software keys when a registered device declines generation for an id- or label-bound key, avoiding mismatched public and private keys.
Changes:
- Adds a shared device-routing check across ten key-generation algorithms while preserving fallback for unregistered devices.
- Adds regression tests and adjusts the TLS test callback to stop labeling declined ECDH keys.
- Documents the new
NO_VALID_DEVIDreturn condition.
| File | Description |
|---|---|
| wolfssl/wolfcrypt/cryptocb.h | Declares the device-bound key check. |
| wolfcrypt/src/wc_xmss.c | Rejects unsafe XMSS software fallback. |
| wolfcrypt/src/wc_slhdsa.c | Rejects unsafe SLH-DSA software fallback. |
| wolfcrypt/src/wc_mlkem.c | Rejects unsafe ML-KEM software fallback. |
| wolfcrypt/src/wc_mldsa.c | Rejects unsafe ML-DSA software fallback. |
| wolfcrypt/src/wc_lms.c | Rejects unsafe LMS software fallback. |
| wolfcrypt/src/rsa.c | Rejects unsafe RSA software fallback. |
| wolfcrypt/src/falcon.c | Rejects unsafe Falcon software fallback. |
| wolfcrypt/src/ed448.c | Rejects device-bound Ed448 generation. |
| wolfcrypt/src/ed25519.c | Rejects unsafe Ed25519 software fallback. |
| wolfcrypt/src/ecc.c | Rejects unsafe ECC software fallback. |
| wolfcrypt/src/cryptocb.c | Implements the device-routing lookup. |
| tests/api/test_slhdsa.h | Registers the SLH-DSA regression test. |
| tests/api/test_slhdsa.c | Tests SLH-DSA rejection and fallback. |
| tests/api/test_rsa.h | Registers the RSA regression test. |
| tests/api/test_rsa.c | Tests RSA rejection and fallback. |
| tests/api/test_mlkem.h | Registers the ML-KEM regression test. |
| tests/api/test_mlkem.c | Tests ML-KEM rejection and fallback. |
| tests/api/test_mldsa.h | Registers the ML-DSA regression test. |
| tests/api/test_mldsa.c | Tests ML-DSA rejection and fallback. |
| tests/api/test_lms_xmss.h | Registers LMS and XMSS regression tests. |
| tests/api/test_lms_xmss.c | Tests device-bound LMS and XMSS rejection. |
| tests/api/test_falcon.h | Registers the Falcon regression test. |
| tests/api/test_falcon.c | Tests Falcon rejection and fallback. |
| tests/api/test_ed448.h | Registers the Ed448 regression test. |
| tests/api/test_ed448.c | Tests Ed448 rejection and fallback. |
| tests/api/test_ed25519.h | Registers the Ed25519 regression test. |
| tests/api/test_ed25519.c | Tests Ed25519 rejection and fallback. |
| tests/api/test_ecc.h | Registers the ECC regression test. |
| tests/api/test_ecc.c | Tests ECC rejection, routing, and callback reentry. |
| tests/api.c | Stops labeling declined ECDH keys. |
| doc/dox_comments/header_files/wc_xmss.h | Documents XMSS device rejection. |
| doc/dox_comments/header_files/wc_slhdsa.h | Documents SLH-DSA device rejection. |
| doc/dox_comments/header_files/wc_mlkem.h | Documents ML-KEM device rejection. |
| doc/dox_comments/header_files/wc_mldsa.h | Documents ML-DSA device rejection. |
| doc/dox_comments/header_files/wc_lms.h | Documents LMS device rejection. |
| doc/dox_comments/header_files/rsa.h | Documents RSA device rejection. |
| doc/dox_comments/header_files/falcon.h | Documents Falcon device rejection. |
| doc/dox_comments/header_files/ed448.h | Documents Ed448 device rejection. |
| doc/dox_comments/header_files/ed25519.h | Documents Ed25519 device rejection. |
| doc/dox_comments/header_files/ecc.h | Documents ECC device rejection. |
Review effort: Balanced
Frauschi
force-pushed
the
keygen-id-key-fallback
branch
2 times, most recently
from
October 22, 2026 18:44
ea0a251 to
016ac4a
Compare
Member
Author
|
Jenkins retest this please |
padelsbach
reviewed
Oct 27, 2026
padelsbach
reviewed
Oct 27, 2026
Frauschi
force-pushed
the
keygen-id-key-fallback
branch
from
October 27, 2026 16:43
016ac4a to
c63d25b
Compare
Contributor
A key initialized with an id or label names a key held by a crypto callback device. When that device returned CRYPTOCB_UNAVAILABLE for key generation, the make-key functions fell back to software and returned success. The key then held a software key pair while its id or label still named the device key, so the next private-key operation went to the device and used a different key from the one in the key object. A signature made that way does not verify against the key's own public key. ECC, RSA, Ed25519, Ed448, ML-DSA, ML-KEM, SLH-DSA, Falcon, LMS and XMSS key generation now return NO_VALID_DEVID when the key has an id or label and its devId names a registered device that did not generate it. WC_CRYPTOCB_IS_DEV_KEY() in cryptocb.h holds that test. It resolves the device through the WOLF_CRYPTO_CB_FIND callback, as dispatch does, so an id key with INVALID_DEVID that the find callback routes to a device is covered too. The rule only applies to a registered device. When the devId reaches no device, later operations also run in software with the same key, so the software fallback stays: generating a key under an id and then storing it with wc_Pkcs11StoreKey keeps working. A device callback that generates the key by clearing devId and calling make-key again on the same key, as wolfcrypt/test/test.c and tests/swdev do, also keeps working, since the inner call sees no registered device. The id, label and devId are read before the device is called, so a callback that writes a label into a key it declines does not trip the check on that call. The test_wc_CryptoCb TLS callback did this to mark ephemeral ECDH keys, and under WOLFSSL_ASYNC_CRYPT_SW the resumed key generation then saw the label and failed. It now recognizes those keys by their software private key instead, since its TLS keys are loaded public-only. ECC id and label keys on a registered device always fail here when HAVE_ECC_DHE is not defined, since its keygen callback is gated on it. RSA keeps its hardware keygen paths unchanged. Only RNG-driven key generation is affected. wc_MlDsaKey_MakeKeyFromSeed, wc_MlKemKey_MakeKeyWithRandom, wc_SlhDsaKey_MakeKeyWithRandom and private-key import take the key material from the caller and are unchanged. Each algorithm gains an API test: an id key and a label key on a registered device that declines keygen get NO_VALID_DEVID, and where software key generation exists, an id key on an unregistered devId and a plain key on the declining device still fall back to software. The ECC test also covers a device that generates the key by calling wc_ecc_make_key_ex on the caller's key, and a find callback that routes an INVALID_DEVID id key to a declining device.
A PKCS#11 token without a key generation mechanism declines keygen: wc_Pkcs11 returns NOT_COMPILED_IN, which the crypto callback layer maps to CRYPTOCB_UNAVAILABLE. The software key used to be stored on the token afterwards with wc_Pkcs11StoreKey, and rejecting id and label keys broke that flow. Defining WOLF_CRYPTO_CB_KEYGEN_SW_FALLBACK now restores the software fallback for them. Without it, the flow still works by initializing the id key with INVALID_DEVID, generating it and then storing it, since wc_Pkcs11StoreKey takes the token directly. That does not apply when a WOLF_CRYPTO_CB_FIND callback routes INVALID_DEVID to the token, because the key then belongs to the device. The check no longer looks up the device before every keygen on an id or label key. Whether the key has an id or label, and its devId, are still read before the device is called, but wc_CryptoCb_HasPkDevice() only runs once the device has declined, so a key the device generates costs no extra lookup. Reading devId up front keeps the check when a callback clears key->devId and then declines. The cryptocb dispatchers cannot make this check themselves: they get a void* key for the PQC types, and CRYPTOCB_UNAVAILABLE from them means both no device and a declining device. WC_CRYPTOCB_KEYGEN_ID_CHECK in cryptocb.h gates the check, its tests and wc_CryptoCb_HasPkDevice(). The opt-out is listed with the other crypto callback build options in cryptocb.c, and the NO_VALID_DEVID doxygen entries now also name a device picked by a WOLF_CRYPTO_CB_FIND callback. Under the opt-out the ECC test checks that id and label keys are generated in software again, and a new keygen-sw-fallback entry in the cryptocb-only workflow builds that configuration. Test changes: the ECC test adds a callback that clears devId before declining. The RSA and SLH-DSA tests add a key without an id on the declining device, which the other algorithms already covered. The RSA test uses TEST_RSA_BITS instead of a 2048-bit software key, and the SLH-DSA test uses the file's default parameter set, so it also runs in SHA-2-only and 192/256-only builds. The RSA test guard drops WOLFSSL_CRYPTOCELL, which master removed, and now runs in the WOLFSSL_SE050_NO_RSA and WOLFSSL_SE050_ONLY_KEY_ID builds that keep the software keygen path.
Frauschi
force-pushed
the
keygen-id-key-fallback
branch
from
October 28, 2026 09:40
c63d25b to
85284bb
Compare
padelsbach
approved these changes
Oct 28, 2026
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.

Description
A key initialized with an id or label names a key held by a crypto callback device. If that device returned
CRYPTOCB_UNAVAILABLEfor key generation, make_key silently generated a software key pair instead. The id or label still pointed at the device key, so later private-key operations used a different key, and signatures did not verify against the key's own public key.NO_VALID_DEVIDwhen the key has an id or label and its devId reaches a registered device that did not generate it. The check isWC_CRYPTOCB_IS_DEV_KEY()incryptocb.h, which finds the device the same way dispatch does (through theWOLF_CRYPTO_CB_FINDcallback if set, by devId otherwise).wc_Pkcs11StoreKeyworking, as well as callbacks that generate by clearing devId and calling make_key again (wolfcrypt/test/test.c,tests/swdev).HAVE_ECC_DHE.test_wc_CryptoCbTLS callback no longer labels the ECDH keys it declines, which broke resumed keygen underWOLFSSL_ASYNC_CRYPT_SW.Testing
test_*_make_key_id_devper algorithm: id and label keys on a declining device getNO_VALID_DEVID. Unregistered devIds and plain keys still fall back to software. ECC also covers a device that calls make_key again on the caller's key, and a find callback routing anINVALID_DEVIDid key to the declining device. All 10 tests fail without the fix.testwolfcryptandunit.test --apipass with--enable-cryptocbin these variants: plain,WOLF_CRYPTO_CB_FIND,--enable-swdev,--enable-pkcs11(without ML-DSA, which does not build with PKCS#11 on macOS clang on master),WOLFSSL_ASYNC_CRYPT_SW, and swdev withWOLF_CRYPTO_CB_ONLY_ECC/_RSA.NO_ECC_DHE(crypto-only, since TLS needs ECDHE on master):testwolfcryptpasses, and a small test program confirms the ECC rejection and fallback.