Skip to content

Replace liboqs SPHINCS+ with SLH-DSA in certificate layer#10261

Open
Frauschi wants to merge 1 commit intowolfSSL:masterfrom
Frauschi:slh-dsa
Open

Replace liboqs SPHINCS+ with SLH-DSA in certificate layer#10261
Frauschi wants to merge 1 commit intowolfSSL:masterfrom
Frauschi:slh-dsa

Conversation

@Frauschi
Copy link
Copy Markdown
Contributor

Replace the liboqs-based pre-standardization SPHINCS+ implementation with the native FIPS 205 SLH-DSA implementation across the certificate/ASN.1/X.509 layers. All liboqs SPHINCS+ code is removed.

This enables SLH-DSA for certificate chain authentication (CA certificates signed with SLH-DSA, certificate verification). TLS 1.3 entity authentication via CertificateVerify with SLH-DSA will be added in a follow-up PR.

Follows RFC 9909 (X.509 Algorithm Identifiers for SLH-DSA).

Changes:

  • New DER codec for SLH-DSA (PrivateKeyDecode, PublicKeyDecode, KeyToDer, PrivateKeyToDer, PublicKeyToDer) with RFC 9909 compliant encoding (bare OCTET STRING, 4*n bytes = SK.seed || SK.prf || PK.seed || PK.root, no nested wrapper) and OID auto-detection across all six SHAKE parameter sets.
  • 12 standardized NIST OIDs (6 SHA2 + 6 SHAKE) per RFC 9909. OID collision mechanism cleaned up since NIST OIDs don't collide.
  • Complete ASN.1 layer replacement (~500 lines in asn.c) and X.509 public-key handling in x509.c.
  • SHA2-SLH-DSA OIDs are recognized but the native backend is SHAKE-only; Private/PublicKeyDecode and ConfirmSignature return NOT_COMPILED_IN for SHA2 variants so callers get an informative error instead of a generic parse failure.
  • wc_GetKeyOID selects its placeholder parameter from whatever SHAKE variant is compiled in, so auto-detect works when specific variants (e.g. SHAKE128F) are disabled.
  • wc_SlhDsaKey_PublicKeyDecode saves and restores key->params and *inOutIdx on ImportPublic failure, matching PrivateKeyDecode.
  • DER round-trip and on-disk decode tests (bench_slhdsa_shake*_key.der fixtures regenerated with wolfSSL's own encoder, guaranteed RFC 9909 compliant) guard against future encoding drift.
  • SLH-DSA test cert chain generated with OpenSSL 3.5.
  • DYNAMIC_TYPE_SPHINCS = 98 kept as RESERVED with a tombstone comment for ABI stability; new code should use DYNAMIC_TYPE_SLHDSA (107).
  • All build system / IDE project files updated; SPHINCS+ sources, headers, and test data removed.

If #9843 is merged ahead of this (probably the case), then this PR will be updated to properly incorporate the SHA2-based SLH-DSA variants.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 20, 2026

MemBrowse Memory Report

gcc-arm-cortex-m4

  • FLASH: .rodata.CSWTCH.742 +6 B (+0.0%, 195,345 B / 262,144 B, total: 75% used)

gcc-arm-cortex-m4-baremetal

  • FLASH: .rodata.CSWTCH.670 +6 B (+0.0%, 63,545 B / 262,144 B, total: 24% used)

gcc-arm-cortex-m4-min-ecc

  • FLASH: .rodata.CSWTCH.671 +6 B (+0.0%, 59,131 B / 262,144 B, total: 23% used)

gcc-arm-cortex-m4-tls12

  • FLASH: .rodata.CSWTCH.724 +6 B (+0.0%, 119,488 B / 262,144 B, total: 46% used)

@Frauschi Frauschi force-pushed the slh-dsa branch 2 times, most recently from 844d158 to ff56841 Compare April 20, 2026 15:05
Replace the liboqs-based pre-standardization SPHINCS+ implementation
with the native FIPS 205 SLH-DSA implementation across the
certificate/ASN.1/X.509 layers. All liboqs SPHINCS+ code is removed.

This enables SLH-DSA for certificate chain authentication (CA
certificates signed with SLH-DSA, certificate verification). TLS 1.3
entity authentication via CertificateVerify with SLH-DSA will be added
in a follow-up PR.

Follows RFC 9909 (X.509 Algorithm Identifiers for SLH-DSA).

Changes:
- New DER codec for SLH-DSA (PrivateKeyDecode, PublicKeyDecode,
  KeyToDer, PrivateKeyToDer, PublicKeyToDer) with RFC 9909 compliant
  encoding (bare OCTET STRING, 4*n bytes = SK.seed || SK.prf ||
  PK.seed || PK.root, no nested wrapper) and OID auto-detection across
  all six SHAKE parameter sets.
- 12 standardized NIST OIDs (6 SHA2 + 6 SHAKE) per RFC 9909. OID
  collision mechanism cleaned up since NIST OIDs don't collide.
- Complete ASN.1 layer replacement (~500 lines in asn.c) and X.509
  public-key handling in x509.c.
- SHA2-SLH-DSA OIDs are recognized but the native backend is
  SHAKE-only; Private/PublicKeyDecode and ConfirmSignature return
  NOT_COMPILED_IN for SHA2 variants so callers get an informative
  error instead of a generic parse failure.
- wc_GetKeyOID selects its placeholder parameter from whatever SHAKE
  variant is compiled in, so auto-detect works when specific variants
  (e.g. SHAKE128F) are disabled.
- wc_SlhDsaKey_PublicKeyDecode saves and restores key->params and
  *inOutIdx on ImportPublic failure, matching PrivateKeyDecode.
- DER round-trip and on-disk decode tests (bench_slhdsa_shake*_key.der
  fixtures regenerated with wolfSSL's own encoder, guaranteed
  RFC 9909 compliant) guard against future encoding drift.
- SLH-DSA test cert chain generated with OpenSSL 3.5.
- DYNAMIC_TYPE_SPHINCS = 98 kept as RESERVED with a tombstone comment
  for ABI stability; new code should use DYNAMIC_TYPE_SLHDSA (107).
- All build system / IDE project files updated; SPHINCS+ sources,
  headers, and test data removed.
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