Skip to content

Add post-quantum (ML-DSA, SLH-DSA) signing support for CRLs#23

Open
Frauschi wants to merge 2 commits into
masterfrom
claude/pqc-crls-wolfssl-fffsv7
Open

Add post-quantum (ML-DSA, SLH-DSA) signing support for CRLs#23
Frauschi wants to merge 2 commits into
masterfrom
claude/pqc-crls-wolfssl-fffsv7

Conversation

@Frauschi

Copy link
Copy Markdown
Owner

Summary

CRL signature verification already supported post-quantum algorithms (the CRL path reuses the shared ConfirmSignature() engine, which dispatches to ML-DSA/SLH-DSA/Falcon). CRL generation did not: wc_SignCRL_ex rejected anything other than RSA/ECC keys and sized its signature buffer with MAX_ENCODED_CLASSIC_SIG_SZ, far too small for PQC signatures.

This PR closes that gap so wolfSSL can sign CRLs with ML-DSA (FIPS 204) and SLH-DSA (FIPS 205) keys.

Changes

  • wc_SignCRL_ex (wolfcrypt/src/asn.c) now accepts wc_MlDsaKey* and SlhDsaKey* signing keys and sizes the signature buffer from the key via GetSignatureBufferSz() — the same PQC-aware sizing the certificate-generation path uses. MakeSignature(), AddSignature() and CheckSigTypeForKey() already handle PQC keys, so they are reused unchanged. The new key pointers are appended after the existing parameters so the RSA/ECC parameter order is preserved.
  • Prototype (wolfssl/wolfcrypt/asn_public.h) and the existing RSA/ECC caller (src/crl.c) updated to match.
  • Tests (tests/api.c): test_wc_SignCRL_mldsa and test_wc_SignCRL_slhdsa — build + sign + verify a CRL through the certificate manager against the issuing PQC CA, plus negative cases for a tampered signature (asserts ASN_CRL_CONFIRM_E) and a sigType/key family mismatch (asserts ALGO_ID_E). Coverage: ML-DSA-44/65/87 and SLH-DSA SHAKE-128s (SHA2-128s when built). Test vectors reuse the existing certs/mldsa/ and certs/slhdsa/ CA cert/key material.

Scope note

wolfSSL's OpenSSL-compat EVP_PKEY layer has no PQC private-key support (wolfSSL_d2i_PrivateKey has no ML-DSA case and WOLFSSL_EVP_PKEY has no PQC member), so PQC CRL signing is exposed through the wolfcrypt-level wc_SignCRL_ex API rather than the wolfSSL_X509_CRL_sign EVP wrapper. Wiring the EVP layer for PQC is a separate, larger change and is intentionally out of scope here.

Testing

  • New tests pass; full API suite reports 0 failed.
  • Build-matrix sanity: CRL-gen without PQC and PQC without CRL both compile cleanly (guards verified).
  • Interop: a wolfSSL-signed ML-DSA-44 CRL was verified with OpenSSL 3.5 (openssl crl -verifyverify OK), confirming the emitted DER is standards-conformant.

https://claude.ai/code/session_01AQerZ4diyqFynLJocio4CF


Generated by Claude Code

claude added 2 commits June 12, 2026 21:26
CRL signature *verification* already supported post-quantum algorithms via
the shared ConfirmSignature() path, but CRL *generation* did not: wc_SignCRL_ex
rejected anything other than RSA/ECC keys and sized its signature buffer with
MAX_ENCODED_CLASSIC_SIG_SZ, far too small for ML-DSA/SLH-DSA signatures.

Extend wc_SignCRL_ex() to accept wc_MlDsaKey* and SlhDsaKey* signing keys and
size the signature buffer from the key via GetSignatureBufferSz() (the same
PQC-aware sizing the certificate-generation path uses). MakeSignature(),
AddSignature() and CheckSigTypeForKey() already handle PQC keys, so they are
reused unchanged. The existing RSA/ECC caller (wolfSSL_X509_CRL_sign) passes
NULL for the new key parameters.

Note: the OpenSSL-compat EVP_PKEY layer has no PQC private-key support
(wolfSSL_d2i_PrivateKey has no ML-DSA case and WOLFSSL_EVP_PKEY has no PQC
member), so PQC CRL signing is exposed through the wolfcrypt-level
wc_SignCRL_ex API rather than the EVP wrapper.

Add round-trip tests (build + sign + verify via the certificate manager, plus
a tampered-signature negative case) covering ML-DSA-44/65/87 and SLH-DSA
SHAKE-128s (SHA2-128s when built). A wolfSSL-signed ML-DSA-44 CRL was also
verified with OpenSSL 3.5 (verify OK) to confirm DER interoperability.
- wc_SignCRL_ex: move the new ML-DSA/SLH-DSA key pointers to the end of the
  parameter list (after rng) so the original RSA/ECC parameter order is
  preserved instead of being split by the inserted PQC params. Update the
  prototype and all callers accordingly.
- wc_SignCRL_ex: brace the single-statement key-count ifs to match file style.
- Tests: size the CRL output buffer from the signing key's actual signature
  length (wc_MlDsaKey_GetSigLen / wc_SlhDsaKey_SigSize) plus wrapper headroom
  instead of a fixed 32768 magic number, so it scales to any parameter set.
- Tests: add a post-quantum sigType/key mismatch negative case (a classic OID
  with a PQC key must return ALGO_ID_E).
- Tests: assert the exact ASN_CRL_CONFIRM_E on the tampered-signature case
  rather than just "not success".
- Tests: heap-allocate the issuer DER buffer instead of a 1 KB stack array.
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.

2 participants