Transition from liboqs SPHINCS+ to native SLH-DSA (FIPS 205)#5
Open
Transition from liboqs SPHINCS+ to native SLH-DSA (FIPS 205)#5
Conversation
Foundation for transitioning from liboqs SPHINCS+ to native SLH-DSA
(FIPS 205) per RFC 9909.
- Add 12 SLH-DSA OIDs (6 SHAKE + 6 SHA2) to oid_sum.h, replacing
SPHINCS+ pre-standardization OIDs with NIST standardized OIDs
(2.16.840.1.101.3.4.3.{20-31})
- Add DER codec functions to wc_slhdsa.c: PrivateKeyDecode,
PublicKeyDecode, KeyToDer, PrivateKeyToDer, PublicKeyToDer
- Add SLH-DSA key type enums in asn.h (replacing SPHINCS key types)
- Add SLH-DSA cert type enums in asn_public.h
- Update SignatureCtx key union to use SlhDsaKey instead of sphincs_key
https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Add SLH-DSA SignatureScheme code points to internal.h per draft-reddy-tls-slhdsa-02 (0x0917-0x091C for SHAKE variants) - Add SLH-DSA signature algorithm enum values, SIG_SLHDSA flag, peer key storage, and min key size fields - Update types.h: MAX_ENCODED_SIG_SZ for SLH-DSA (49856 bytes) - Update settings.h: remove HAVE_SPHINCS from liboqs block, replace with WOLFSSL_HAVE_SLHDSA in asym key export/import - Update ssl.c: replace sphincs.h include with wc_slhdsa.h - Update build system: remove sphincs.c/sphincs.h from include.am https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Update src/x509.c to use native SLH-DSA (FIPS 205) instead of liboqs SPHINCS+ for X.509 public key handling. Replace all sphincs_key usage with SlhDsaKey, update OID checks to use SLH-DSA constants, and use the new SLH-DSA API. https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Remove all SPHINCS+ benchmark code (bench_sphincsKeySign, flags, CLI options) from benchmark.c/h. SLH-DSA benchmarks already exist. - Update gencertbuf.pl to reference SLH-DSA test key files instead of SPHINCS+ files. https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Remove all SPHINCS+ test key arrays from certs_test.h. SLH-DSA test keys will be generated and added in a subsequent commit. Update gencertbuf.pl to reference SLH-DSA file paths. https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Major update to wolfcrypt/src/asn.c and asn_orig.c: - Replace all SPHINCS+ OID arrays with SLH-DSA NIST OIDs per RFC 9909 (SHA2: sigAlgs 20-25, SHAKE: sigAlgs 26-31) - Replace sphincs_key with SlhDsaKey throughout - Update certificate signing to use wc_SlhDsaKey_Sign with empty context - Update certificate verification to use wc_SlhDsaKey_Verify (returns 0 on success instead of setting int* res) - Replace all SPHINCS key type, cert type, and OID constants - Update PEM header/footer strings - Update MakeAnyCert/MakeCertReq signatures - Change HAVE_SPHINCS guards to WOLFSSL_HAVE_SLHDSA https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Remove sphincs.c/sphincs.h references from all IDE project files (VS, Xcode, Espressif, INTIME-RTOS, MPLABX, Zephyr, CSharp) - Update scripts/asn1_oid_sum.pl with SLH-DSA OIDs (RFC 9909) - Update certs/include.am, cmake/functions.cmake, rpm/spec.in - Update INSTALL and doxygen docs - Update .wolfssl_known_macro_extras https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Delete wolfcrypt/src/sphincs.c and wolfssl/wolfcrypt/sphincs.h - Delete certs/sphincs/ directory with all test key DER files - Fix remaining HAVE_SPHINCS reference in asn.h pkCurveOID guard https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Remove sphincs.c link from Renesas e2studio project file - Update INSTALL to say "FIPS 205" instead of "SPHINCS+" https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Fix SignatureCtx key union member: slhDsa -> slhdsa (matching the member name defined in asn.h) - Generate SLH-DSA test key DER files for all 6 SHAKE parameter sets using wc_SlhDsaKey_MakeKey + wc_SlhDsaKey_KeyToDer https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
- Initialize haveSlhDsaSig on client side in InitSSL and InitSSL_Ctx - Initialize minSlhDsaKeySz from MIN_SLHDSAKEY_SZ - Copy SLH-DSA settings from ctx to ssl - Add SLH-DSA signature algorithms to AddSuiteHashSigAlgo for signature_algorithms extension (all 6 SHAKE variants) https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Add SLH-DSA signature scheme support per draft-reddy-tls-slhdsa-02: - EncodeSigAlg: map slhdsa_shake_*_sa_algo to wire bytes (0x09, 0x17-0x1C) - DecodeTls13SigAlg: parse SLH-DSA minor bytes within SLHDSA_SA_MAJOR - SendTls13CertificateVerify: add SLH-DSA signing path using wc_SlhDsaKey_Sign with empty context per RFC 9909 - DoTls13CertificateVerify: add SLH-DSA verification path - MatchSigAlgo: add SLH-DSA signature algorithm matching - Add WOLFSSL_HAVE_SLHDSA to all relevant conditional guards https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Add individual ADD_HASH_SIG_ALGO dispatch entries for each SLH-DSA SHAKE variant in the per-algorithm branch of AddSuiteHashSigAlgo, encoding the SA_MAJOR/SA_MINOR wire bytes. https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Comprehensive TLS 1.3 SLH-DSA support per draft-reddy-tls-slhdsa-02: tls13.c: - EncodeSigAlg/DecodeTls13SigAlg for all 6 SHAKE variants - SendTls13CertificateVerify: SLH-DSA signing with empty context - DoTls13CertificateVerify: SLH-DSA verification internal.c: - DecodeSigAlg: handle SLH-DSA minor bytes (shares 0x09 major with Dilithium) - FreeKey/AllocKey/ReuseKey: SlhDsaKey lifecycle - ProcessPeerCerts: extract SLH-DSA peer keys - ProcessPeerCertCheckKey: size validation - MatchSigAlgo: match SLH-DSA OIDs to sig algos - SetCipherListFromBytes: include SLH-DSA in haveSig - DecodePrivateKey_ex: SLH-DSA private key decoding ssl_load.c: - ProcessBufferKeySet/CertSetHave: detect SLH-DSA keys/certs - ProcessBufferTryDecodeSlhDsa: new decode function ssl.c: - Copy haveSlhDsaSig from ctx to ssl https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
Fixes a bug where wc_SlhDsaKey_PrivateKeyDecode and wc_SlhDsaKey_PublicKeyDecode only decoded DER keys whose OID matched the parameter set the key was initialized with. This made it impossible to load any variant other than SLHDSA_SHAKE128S through SSL/TLS, since ProcessBufferTryDecodeSlhDsa initialized with a fixed placeholder param. Both decode functions now iterate over the compiled-in parameter sets and try each keytype against the DER OID until one matches. On success, key->params is updated to the detected parameter set so subsequent size/import calls use the correct values. Also: - Removed the "try raw import first" shortcut from PublicKeyDecode. It didn't match the function's documented contract (DER only) and could silently accept random bytes that happened to be 2*n long. - Simplified GetKeyOID's SLH-DSA branch in asn.c from seven per-variant init/decode attempts to a single decode call plus a switch over the detected param. ~90 lines removed. - Added test_wc_slhdsa_der_roundtrip which, for every compiled-in SHAKE parameter set, generates a key, encodes to DER, decodes into a key initialized with a DIFFERENT placeholder param, checks that the decoded key's params field matches the original, signs a message with the decoded private key, and verifies with the original and with the DER-decoded public key. This test would have caught the original bug immediately. https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV
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.
Summary
This PR replaces the liboqs-based pre-standardization SPHINCS+ implementation with the native FIPS 205 SLH-DSA implementation across all higher layers (certificate/ASN.1/X.509 and TLS 1.3 handshake). All liboqs SPHINCS+ code is removed.
The transition follows two specifications:
Motivation
wolfSSL has a native FIPS 205 SLH-DSA implementation in
wolfcrypt/src/wc_slhdsa.c, but it previously lacked higher-layer integration. The liboqs-based SPHINCS+ wrapper used pre-standardization OIDs (1.3.9999.6.x) and depended on the external liboqs library. This PR switches everything to the standardized native implementation and removes the liboqs SPHINCS+ dependency entirely.A future standalone effort will remove liboqs support for ML-KEM and ML-DSA as well.
Changes
New DER codec for SLH-DSA
wc_SlhDsaKey_PrivateKeyDecode,wc_SlhDsaKey_PublicKeyDecodewc_SlhDsaKey_KeyToDer,wc_SlhDsaKey_PrivateKeyToDer,wc_SlhDsaKey_PublicKeyToDerDecodeAsymKey/SetAsymKeyDerhelpers following the Dilithium patternOIDs (RFC 9909)
Added 12 standardized NIST OIDs under
2.16.840.1.101.3.4.3:AlgorithmIdentifier parameters are absent (per RFC 9909). Context string is empty for X.509 signing and TLS CertificateVerify.
Certificate/ASN.1 layer
wolfcrypt/src/asn.cwolfcrypt/src/asn_orig.cwc_SlhDsaKey_Sign(key, NULL, 0, ...)wc_SlhDsaKey_Verify(key, NULL, 0, ...)(returns 0 on success)X.509 layer (
src/x509.c)sphincs_keyhandling withSlhDsaKeyDYNAMIC_TYPE_SLHDSATLS 1.3 handshake (
src/tls13.c,src/internal.c,src/ssl.c,src/ssl_load.c)Per draft-reddy-tls-slhdsa-02:
EncodeSigAlg/DecodeTls13SigAlgfor SLH-DSA (shares SA_MAJOR=0x09 with Dilithium, disambiguated by minor byte)SendTls13CertificateVerify/DoTls13CertificateVerifywith empty contextpeerSlhDsaKey,peerSlhDsaKeyPresent)AllocKey/FreeKey/ReuseKeyProcessPeerCertsextracts SLH-DSA peer keysProcessBufferTryDecodeSlhDsafor loading SLH-DSA private keyshaveSlhDsaSig,minSlhDsaKeySzadded to Options and CTXSIG_SLHDSAflag inSIG_ALLBuild system
HAVE_SPHINCSremoved fromHAVE_LIBOQSblock insettings.hsphincs.cremoved fromBUILD_LIBOQSsourcesCMakeLists.txt, all IDE project files (VS, VS2022, Xcode, INTIME-RTOS, MPLABX16, Espressif, Zephyr, Renesas, CSharp wrapper),configure.ac,cmake/functions.cmake,rpm/spec.inTypes and settings
MAX_ENCODED_SIG_SZconditional updated toWOLFSSL_HAVE_SLHDSAMAX_X509_HEADER_SZconditional updatedWC_ENABLE_ASYM_KEY_EXPORT/IMPORTconditionals updatedDYNAMIC_TYPE_SPHINCSremoved (replaced by existingDYNAMIC_TYPE_SLHDSA)Test infrastructure
certs/slhdsa/(all SHAKE parameter sets)certs_test.hwith SLH-DSA test keysgencertbuf.plto reference SLH-DSA DER fileswolfcrypt/benchmark/benchmark.c; SPHINCS+ benchmark code removedscripts/asn1_oid_sum.plupdated with the 12 new SLH-DSA OIDsRemoved
wolfcrypt/src/sphincs.cwolfssl/wolfcrypt/sphincs.hcerts/sphincs/directorydoc/dox_comments/,INSTALL,.wolfssl_known_macro_extrasTest plan
./configure --enable-slhdsa && make./wolfcrypt/test/testwolfcryptreportsSLH-DSA test passed!along with all other algorithmsINSTALLwhere SLH-DSA is described as the standardized name of SPHINCS+)https://claude.ai/code/session_019gqvW3ZMKGGyi6zCRNPDYV