Skip to content

Add CryptoCb support for LMS and XMSS#10

Open
Frauschi wants to merge 1 commit intomasterfrom
claude/add-cryptocb-lms-xmss-KYtLu
Open

Add CryptoCb support for LMS and XMSS#10
Frauschi wants to merge 1 commit intomasterfrom
claude/add-cryptocb-lms-xmss-KYtLu

Conversation

@Frauschi
Copy link
Copy Markdown
Owner

Summary

Groundwork for routing LMS/HSS (RFC 8554) and XMSS/XMSS^MT (RFC 8391) through the WOLF_CRYPTO_CB framework, so that the PKCS#11 provider and wolfHSM client can later host stateful hash-based keys on a device. No HSM-side or PKCS#11-provider code is in scope here — this PR adds only the wolfSSL-side dispatcher layer.

The dispatcher surface mirrors the operations PKCS#11 v3.1 and v3.2 expose for these algorithms:

wolfSSL API PKCS#11 analog CryptoCb dispatcher
wc_LmsKey_MakeKey CKM_HSS_KEY_PAIR_GEN wc_CryptoCb_LmsKeyGen
wc_LmsKey_Sign CKM_HSS (sign) wc_CryptoCb_LmsSign
wc_LmsKey_Verify CKM_HSS (verify) wc_CryptoCb_LmsVerify
wc_LmsKey_SigsLeft CKA_HSS_KEYS_REMAINING wc_CryptoCb_LmsSigsLeft
wc_XmssKey_MakeKey CKM_XMSS_KEY_PAIR_GEN / CKM_XMSSMT_KEY_PAIR_GEN wc_CryptoCb_XmssKeyGen
wc_XmssKey_Sign CKM_XMSS / CKM_XMSSMT (sign) wc_CryptoCb_XmssSign
wc_XmssKey_Verify CKM_XMSS / CKM_XMSSMT (verify) wc_CryptoCb_XmssVerify
wc_XmssKey_SigsLeft XMSS remaining-sigs attr wc_CryptoCb_XmssSigsLeft

XMSS vs XMSSMT is discriminated inside the callback via the existing XmssKey::is_xmssmt field, so the dispatcher interface stays unified. Reload / GetKid / ExportPub and the external-backend variants (ext_lms.c, ext_xmss.c, selected by --with-liblms / --with-libxmss) are intentionally out of scope.

Design choices

  • Per-algorithm dispatchers, following the Ed25519 pattern — dedicated WC_PK_TYPE_LMS_* and WC_PK_TYPE_XMSS_* enums, dedicated wc_CryptoInfo.pk union members, and dedicated wc_CryptoCb_* functions. Rejected the shared wc_HashSigType dispatcher style (Dilithium/Falcon) because LMS and XMSS have very different key structs and no void* erasure benefit.
  • Built-in backends only (wc_lms.c, wc_xmss.c). ext_lms.c / ext_xmss.c carry an inline comment noting they do not route through CryptoCb.
  • XmssKey gains a devId field under WOLF_CRYPTO_CB; wc_XmssKey_Init now stores it (previously (void)devId;). LmsKey already had the field.
  • CryptoCb dispatch runs before the software write_private_key / read_private_key / context validations so HSM-backed keys don't need dummy software callbacks. On CRYPTOCB_UNAVAILABLE the software path still revisits those checks.
  • Reload short-circuits for HSM-backed keys (state lives in the device). GetKid logs a warning because priv_raw may be uninitialised on HSM-backed keys.

Commit breakdown

  1. Add CryptoCb dispatcher infrastructure for LMS and XMSS — enums in types.h, devId field on XmssKey, wc_CryptoInfo.pk union entries, eight wc_CryptoCb_* declarations and bodies.
  2. Route LMS/XMSS sign/verify/keygen/sigs-left through CryptoCb — call sites in wc_lms.c and wc_xmss.c, plus the wc_XmssKey_Init devId-store fix.
  3. Exercise LMS/XMSS CryptoCb path in cryptocb_test — eight new myCryptoDevCb handlers and lms_test / xmss_test invoked inside cryptocb_test.
  4. Apply code-review fixes — negative-length guards in Verify, int* res on verify dispatchers, word32* sigs-left counts, safer SigsLeft fallback, flattened myCryptoDevCb else-chain, reordered CryptoCb dispatch, HSM-aware Reload/GetKid, doc and include cleanups.

Test plan

  • ./configure --enable-lms --enable-xmss --enable-cryptocb && make && ./wolfcrypt/test/testwolfcrypt — passes, LMS and XMSS tests exercise the CryptoCb round-trip.
  • ./configure --enable-lms --enable-xmss && make && ./wolfcrypt/test/testwolfcrypt — new code fully #ifdef-elided, passes.
  • ./configure --enable-cryptocb && make && ./wolfcrypt/test/testwolfcrypt — LMS/XMSS-less build, passes.
  • KAT regression: testwolfcrypt output md5 is bit-identical before and after the change under the primary config (801f0730eb597e486ec370f29a6259ce).
  • Downstream wolfHSM / PKCS#11 provider wiring (follow-up PR).

https://claude.ai/code/session_01MixzJP9kPWkS8bhfDDDBnX


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

@Frauschi Frauschi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Support for devCtx as well asl PRIVATE_KEY_ID and LABEL is missing

Comment thread wolfcrypt/src/ext_lms.c Outdated
Comment thread wolfcrypt/src/ext_xmss.c Outdated
Comment thread wolfssl/wolfcrypt/cryptocb.h Outdated
Comment thread wolfssl/wolfcrypt/cryptocb.h Outdated
Comment thread wolfssl/wolfcrypt/cryptocb.h
@Frauschi Frauschi force-pushed the claude/add-cryptocb-lms-xmss-KYtLu branch 2 times, most recently from 3f1a1b3 to 093d67a Compare April 27, 2026 19:12
Groundwork for routing LMS / HSS (RFC 8554) and XMSS / XMSS^MT
(RFC 8391, both profiled in NIST SP 800-208) through the
WOLF_CRYPTO_CB framework so that the wolfSSL PKCS#11 provider and the
wolfHSM client can later host stateful hash-based keys on a device.
No HSM-side or PKCS#11-provider code is in scope; this commit only
adds the wolfSSL-side dispatcher layer, the per-key device binding,
and the helpers a backend needs to answer the request.

Dispatcher surface (modelled on wc_CryptoCb_PqcSign* used for
Dilithium and Falcon):

  WC_PK_TYPE_PQC_STATEFUL_SIG_KEYGEN
  WC_PK_TYPE_PQC_STATEFUL_SIG_SIGN
  WC_PK_TYPE_PQC_STATEFUL_SIG_VERIFY
  WC_PK_TYPE_PQC_STATEFUL_SIG_SIGS_LEFT

A new discriminator enum wc_PqcStatefulSignatureType
(WC_PQC_STATEFUL_SIG_TYPE_LMS / _XMSS) tells the callback how to
interpret the void* key. The dispatcher functions are
wc_CryptoCb_PqcStatefulSig{KeyGen,Sign,Verify,SigsLeft} plus the
wc_CryptoCb_PqcStatefulSigGetDevId helper. XMSS vs XMSS^MT is
discriminated inside the callback via the existing
XmssKey::is_xmssmt field.

Mapping to PKCS#11 v3.1 / v3.2:

  wc_LmsKey_MakeKey   -> CKM_HSS_KEY_PAIR_GEN
  wc_LmsKey_Sign      -> CKM_HSS (sign)
  wc_LmsKey_Verify    -> CKM_HSS (verify)
  wc_LmsKey_SigsLeft  -> CKA_HSS_KEYS_REMAINING attribute
  wc_XmssKey_MakeKey  -> CKM_XMSS_KEY_PAIR_GEN / CKM_XMSSMT_KEY_PAIR_GEN
  wc_XmssKey_Sign     -> CKM_XMSS / CKM_XMSSMT (sign)
  wc_XmssKey_Verify   -> CKM_XMSS / CKM_XMSSMT (verify)
  wc_XmssKey_SigsLeft -> XMSS remaining-sigs attribute

Public API additions:

- LmsKey / XmssKey gain (under WOLF_CRYPTO_CB) int devId and
  void* devCtx, and (under WOLF_PRIVATE_KEY_ID) byte id[],
  int idLen, char label[], int labelLen, with LMS_MAX_ID_LEN,
  LMS_MAX_LABEL_LEN, XMSS_MAX_ID_LEN, XMSS_MAX_LABEL_LEN constants
  defaulting to 32 and overridable.
- wc_LmsKey_InitId / wc_LmsKey_InitLabel and the XMSS equivalents,
  gated on WOLF_PRIVATE_KEY_ID, mirror wc_InitRsaKey_Id /
  wc_InitRsaKey_Label.
- wc_LmsKey_HashMsg / wc_XmssKey_HashMsg compute the digest dictated
  by the parameter set (SHA-256 / SHA-256-192 / SHAKE256 / SHAKE256-192
  for LMS; SHA-256 / SHA-512 / SHAKE128 / SHAKE256 for XMSS) so a
  PKCS#11-style backend can produce the digest from inside the
  callback. wolfHSM-style backends ignore the helper and consume
  msg / msgSz directly.

Behaviour notes:

- The CryptoCb dispatch in wc_*Key_MakeKey / Sign runs before the
  software write/read/context callback validation so a device-backed
  key does not need dummy software callbacks. On CRYPTOCB_UNAVAILABLE
  the software validations are re-applied.
- wc_*Key_Verify rejects negative msgSz before widening to word32 for
  the dispatcher, and surfaces validity through int* res in the
  dispatcher, translating res != 1 back to SIG_VERIFY_E for the
  wolfSSL caller.
- wc_*Key_SigsLeft uses word32* sigsLeft so a key at the 2^32 PKCS#11
  limit can be expressed unambiguously; the public int-returning API
  clamps at 0x7FFFFFFF and emits WOLFSSL_MSG instead of swallowing
  device errors.
- wc_*Key_Reload short-circuits for HSM-backed keys; wc_LmsKey_GetKid
  warns that priv_raw may be uninitialised; wc_*Key_ExportPub
  preserves the source key's devId so the verify-only copy keeps
  dispatching through the same device.

Test coverage:

myCryptoDevCb gains four new handlers that bounce each operation
back into the software API by clearing devId and restoring it; both
Sign and Verify go through the dispatcher, so the produced signatures
self-verify within the harness. lms_test and xmss_test are invoked
inside cryptocb_test to exercise the full round trip.

Builds verified:

  --enable-lms --enable-xmss --enable-cryptocb (primary)
  --enable-lms --enable-xmss --enable-cryptocb CPPFLAGS=-DWOLF_PRIVATE_KEY_ID
  --enable-lms --enable-xmss
  --enable-cryptocb

A doc/LMS_XMSS_CryptoCb.md document covers the rationale, the
PKCS#11 mapping, the public API, and the design notes.
@Frauschi Frauschi force-pushed the claude/add-cryptocb-lms-xmss-KYtLu branch from 093d67a to 03833f6 Compare April 27, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant