Add verify-only LMS and XMSS support#206
Conversation
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #206
Scan targets checked: wolfpkcs11-bugs, wolfpkcs11-src
Findings: 2
2 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
c878805 to
0c06695
Compare
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #206
Scan targets checked: wolfpkcs11-bugs, wolfpkcs11-src
Findings: 3
3 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
0c06695 to
f208ae8
Compare
|
The failing CMake Build Test will be resolved once wolfSSL/wolfssl#10929 lands. |
wolfSSL-Fenrir-bot
left a comment
There was a problem hiding this comment.
Fenrir Automated Review — PR #206
Scan targets checked: wolfpkcs11-bugs, wolfpkcs11-src
Findings: 1
1 finding(s) posted as inline comments (see file-level comments below)
This review was generated automatically by Fenrir. Findings are non-blocking.
f208ae8 to
90e55a0
Compare
Add PKCS#11 verify-only support for the stateful hash-based signature schemes LMS/HSS (RFC 8554) and XMSS/XMSS^MT (RFC 8391), backed by wolfSSL and gated behind the --enable-lms and --enable-xmss build options. Interface: - Key types CKK_HSS, CKK_XMSS, CKK_XMSSMT and mechanisms CKM_HSS, CKM_XMSS, CKM_XMSSMT, using the OASIS PKCS#11 v3.3 standard constant values (not vendor-defined). - Public keys are imported as ordinary token or session objects from the raw RFC 8554 / RFC 8391 public key in CKA_VALUE. wolfSSL derives the parameter set from the key bytes; supplied CKA_HSS_* parameter attributes and the XMSS CKA_PARAMETER_SET OID are validated against the key, and a mismatch is rejected with CKR_ATTRIBUTE_VALUE_INVALID. - HSS parameter attributes (CKA_HSS_LEVELS, CKA_HSS_LMS_TYPE(S), CKA_HSS_LMOTS_TYPE(S)) and the XMSS CKA_PARAMETER_SET are exposed on read. CKA_HSS_KEYS_REMAINING is a private-key state property and is reported as unavailable in a verify-only build. - C_Verify checks the mechanism against the key type, and reports a wrong-length signature or an empty message (for XMSS) as an invalid signature rather than a function failure. Constraints (verify-only): - Key generation (CKM_*_KEY_PAIR_GEN) and private-key import are rejected. Copying any HBS key is prohibited so that future sign-capable builds can never duplicate one-time-signature state. Persistence: - Public keys are stored and reloaded from disk via the new store types WOLFPKCS11_STORE_HSSKEY_PUB (0x11) and WOLFPKCS11_STORE_XMSSKEY_PUB (0x13), with 0x10 and 0x12 reserved for future private keys. Tests: - Known-answer verification, parameter-set validation, token-object persistence across a library reload, and negative cases covering private-key import, wrong mechanism/key-type pairings, and malformed, wrong-length, and structurally invalid public keys.
90e55a0 to
c496034
Compare
|
the edit: is a separate issue: #206 (comment) edit2: it passes now with that PR merged. |
philljj
left a comment
There was a problem hiding this comment.
First pass. So far looks good, just some suggestions and comments.
| #define WOLFPKCS11_STORE_MLDSAKEY_PUB 0x0D | ||
| #define WOLFPKCS11_STORE_MLKEMKEY_PRIV 0x0E | ||
| #define WOLFPKCS11_STORE_MLKEMKEY_PUB 0x0F | ||
| /* Stateful hash-based signature keys. The private-key storage types (0x10 for |
There was a problem hiding this comment.
I say just put them in now so nothing accidentally takes these slots:
/* reserved
#define WOLFPKCS11_STORE_HSSKEY_PRIV 0x10
*/
#define WOLFPKCS11_STORE_HSSKEY_PUB 0x11
/* reserved
#define WOLFPKCS11_STORE_XMSSKEY_PRIV 0x12
*/
#define WOLFPKCS11_STORE_XMSSKEY_PUB 0x13
or just put them in for real:
/* note: HSSKEY_PRIV and XMSS_PRIV not implemented yet. */
#define WOLFPKCS11_STORE_HSSKEY_PRIV 0x10
#define WOLFPKCS11_STORE_HSSKEY_PUB 0x11
#define WOLFPKCS11_STORE_XMSSKEY_PRIV 0x12
#define WOLFPKCS11_STORE_XMSSKEY_PUB 0x13
| #define WP11_INIT_MLDSA_VERIFY 0x0081 | ||
| /* Stateful hash-based signature verify operations. Sign flags (0x0090, | ||
| * 0x00A0) are reserved for the sign-capable builds. XMSS and XMSS^MT share | ||
| * one verify flag; the mechanism→key-type check distinguishes them. */ |
There was a problem hiding this comment.
Same as other spot. Just reserve them now in comment or in code for real:
#define WP11_INIT_HSS_SIGN 0x0090
#define WP11_INIT_HSS_VERIFY 0x0091
#define WP11_INIT_XMSS_SIGN 0x00A0
#define WP11_INIT_XMSS_VERIFY 0x00A1
| * rather than reaching the SetAttributeValue key-type switch and | ||
| * returning the less appropriate CKR_OBJECT_HANDLE_INVALID. The guards | ||
| * mirror that switch. CKK_GENERIC_SECRET is always available. */ | ||
| if (objType != CKK_GENERIC_SECRET |
There was a problem hiding this comment.
would a switch statement be easier to maintain here? Or maybe it won't buy much simplification because of all the #ifndef thing guards.
| run: | | ||
| ./configure --enable-cryptocb --enable-aescfb --enable-rsapss --enable-keygen --enable-pwdbased --enable-scrypt --enable-md5 \ | ||
| --enable-mldsa C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" | ||
| --enable-mldsa --enable-lms --enable-xmss C_EXTRA_FLAGS="-DWOLFSSL_PUBLIC_MP -DWC_RSA_DIRECT -DHAVE_AES_ECB -DHAVE_AES_KEYWRAP" |
There was a problem hiding this comment.
Should these workflows be testing --enable-lms=verify-only --enable-xmss=verify-only for now?
It wouldn't surprise me if long term verify-only is the use case vast majority of XMSS/LMS users are interested in.
LMS/XMSS verify-only has very attractive features (it can be incredibly lean, has no math library dependency, etc). In other words, consider verify-only LMS/XMSS an option to support and test rather than a feature deficiency.
Signing would require integration with a hardware HSM.
There was a problem hiding this comment.
Pull request overview
Adds verify-only PKCS#11 v3.3 support for stateful hash-based signatures (HSS/LMS and XMSS/XMSS^MT) in wolfPKCS11, integrating wolfSSL’s LMS/XMSS APIs behind new build-time feature flags and extending the object store + tests/CI accordingly.
Changes:
- Introduces new PKCS#11 v3.3 key types/mechanisms/attributes for HSS and XMSS, plus verify-only mechanism wiring (
C_VerifyInit/C_Verify). - Implements raw public-key import, parameter-set handling, attribute read-back, and on-disk persistence for HSS/XMSS public keys.
- Adds comprehensive KAT + persistence tests and expands autotools/CMake/CI configurations for LMS/XMSS builds.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfpkcs11/store.h | Adds new store type IDs for HSS/XMSS public keys. |
| wolfpkcs11/pkcs11.h | Defines PKCS#11 v3.3 HSS/XMSS constants and related typedefs/macros. |
| wolfpkcs11/internal.h | Adds wolfSSL LMS/XMSS includes, build guards, and internal APIs for import/verify. |
| tests/pkcs11v3test.c | Adds KAT tests + negative/attribute/guard coverage for HSS/XMSS verify-only behavior. |
| tests/include.am | Wires new persistence test + distributes hbs_kat.h. |
| tests/hbs_persistence_test.c | New test to ensure token public keys persist and still verify after reload. |
| tests/hbs_kat.h | Adds shared KAT vectors for HSS/XMSS/XMSSMT. |
| src/slot.c | Exposes new mechanisms and mechanism-info flags (verify-only). |
| src/internal.c | Implements HSS/XMSS key import, verify, attribute getters, and store encode/decode paths. |
| src/crypto.c | Integrates new key types into Create/SetAttributeValue and verify dispatch. |
| configure.ac | Adds --enable-lms / --enable-xmss configure flags and associated gating. |
| CMakeLists.txt | Adds CMake options for LMS/XMSS, plus conditional test enablement. |
| cmake/options.h.in | Exposes WOLFPKCS11_LMS / WOLFPKCS11_XMSS in generated options header. |
| .github/workflows/unit-test.yml | Adds new CI job matrices for LMS/XMSS builds. |
| .github/workflows/cmake.yml | Enables XMSS/LMS in wolfSSL build and LMS/XMSS in wolfPKCS11 CMake CI config. |
| .github/workflows/build-workflow.yml | Builds wolfSSL with LMS/XMSS enabled for workflow reuse. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| dlib = dlopen(WOLFPKCS11_DLL_FILENAME, RTLD_NOW | RTLD_LOCAL); | ||
| if (dlib == NULL) { | ||
| fprintf(stderr, "dlopen error: %s\n", dlerror()); | ||
| return -1; | ||
| } |
| func = (CK_C_GetFunctionList)dlsym(dlib, "C_GetFunctionList"); | ||
| if (func == NULL) { | ||
| fprintf(stderr, "Failed to get function list function\n"); | ||
| dlclose(dlib); | ||
| return -1; | ||
| } |
| #ifdef WOLFPKCS11_LMS | ||
| case CKA_HSS_LEVELS: | ||
| case CKA_HSS_LMS_TYPE: | ||
| case CKA_HSS_LMOTS_TYPE: | ||
| case CKA_HSS_LMS_TYPES: | ||
| case CKA_HSS_LMOTS_TYPES: | ||
| case CKA_HSS_KEYS_REMAINING: | ||
| /* HSS parameter attributes are key-derived and read-only. The | ||
| * WP11_Object_SetHssKey template pass validates the scalar forms | ||
| * against the public key and rejects a value-less or mismatched set | ||
| * (CKR_ATTRIBUTE_VALUE_INVALID) before this runs; the array and | ||
| * keys-remaining forms are values served by HssObject_GetAttr. | ||
| * Accept them all as a no-op on an HSS object so recreating one from | ||
| * its own attributes is not rejected. */ | ||
| if (object->type != CKK_HSS) | ||
| ret = BAD_FUNC_ARG; | ||
| break; | ||
| #endif |
Summary
Adds PKCS#11 verify-only support for the two NIST-approved stateful hash-based signature (SHBS) families:
Signature verification and raw public-key import are implemented on top of wolfSSL's
wc_LmsKey_*/wc_XmssKey_*APIs, using the standard OASIS PKCS#11 v3.3 mechanism, key-type, and attribute constants. Everything is gated behind the new--enable-lmsand--enable-xmssbuild options and is off by default.This is step 1 (verify only). Signing, key generation, and private-key import are deliberately out of scope and are rejected at runtime; the object model and store layout are laid out so a future sign-capable step can add private keys without an interface break.
What's included
Interface (standard PKCS#11 v3.3)
CKK_HSS(0x46),CKK_XMSS(0x47),CKK_XMSSMT(0x48)CKM_HSS(0x4033),CKM_XMSS(0x4036),CKM_XMSSMT(0x4037)CKA_HSS_LEVELS,CKA_HSS_LMS_TYPE(S),CKA_HSS_LMOTS_TYPE(S),CKA_HSS_KEYS_REMAINING,CKA_PARAMETER_SET(XMSS)All values match the OASIS PKCS#11 v3.3 working headers exactly (not vendor-defined).
Behaviour
CKA_VALUE. wolfSSL derives the parameter set from the key bytes.CKA_HSS_*parameter attributes and the XMSSCKA_PARAMETER_SETOID are validated against the imported key; a mismatch, a malformed key, or a wrong-length key is rejected withCKR_ATTRIBUTE_VALUE_INVALID.CKA_PARAMETER_SETare exposed on read.CKA_HSS_KEYS_REMAININGis a private-key state property and is reported as unavailable in a verify-only build.C_Verify— validates the mechanism against the key type (CKR_KEY_TYPE_INCONSISTENTon a mismatch) and reports a wrong-length signature (both schemes) or an empty message (XMSS only, a wolfSSL backend limitation) as an invalid signature rather than a function failure.WOLFPKCS11_STORE_HSSKEY_PUB(0x11) andWOLFPKCS11_STORE_XMSSKEY_PUB(0x13), with0x10/0x12reserved for future private keys.Verify-only constraints
CKM_*_KEY_PAIR_GEN) and private-key import are rejected.Build
Testing
New coverage in
tests/pkcs11v3test.cand a dedicatedtests/hbs_persistence_test.c:CKA_HSS_*/CKA_PARAMETER_SET).CKA_HSS_KEYS_REMAINING.All tests pass; the key-lifecycle paths (import, atomic re-import, free) were additionally checked clean under AddressSanitizer, including a
--disable-rsa --enable-lmsbuild.Notes and limitations
CKA_HSS_LMS_TYPES/CKA_HSS_LMOTS_TYPES) report the single top-level type for every level. Heterogeneous HSS keys are not expressible today.CKA_PARAMETER_SET.CKL_LMS_*/CKL_LMOTS_*convenience macros are wolfPKCS11-local (the spec header defines none); their values are the RFC 8554 registry codes.