openssl/openssl
Post-quantum cryptography
Active contributors: Pauli, slontis, Tomas Mraz, Viktor Dukhovni, Neil Horman
Purpose
OpenSSL has merged in-tree implementations of every NIST-finalised post-quantum algorithm and the IETF stateful hash-based signature LMS:
| Algorithm | Standard | Type | Source | Merged |
|---|---|---|---|---|
| ML-KEM (Kyber) | FIPS 203 | KEM | crypto/ml_kem/, providers/implementations/keymgmt/ml_kem_kmgmt.c, providers/implementations/kem/ml_kem_kem.c |
2025-02 (3.5) |
| ML-DSA (Dilithium) | FIPS 204 | Signature | crypto/ml_dsa/, providers/implementations/keymgmt/ml_dsa_kmgmt.c, providers/implementations/signature/ml_dsa_sig.c |
2025-04 (3.5) |
| SLH-DSA (SPHINCS+) | FIPS 205 | Signature (hash-based, stateless) | crypto/slh_dsa/, plus keymgmt and signature in providers |
2025-04 (3.5) |
| LMS | RFC 8554 | Signature (hash-based, stateful) | crypto/lms/, plus keymgmt and signature in providers |
2025 (3.5) |
OpenSSL also exposes the hybrid TLS group X25519MLKEM768 (3.5+) which combines classical X25519 ECDH with ML-KEM-768 encapsulation per draft-ietf-tls-hybrid-design.
ML-KEM (Module-Lattice KEM, FIPS 203)
crypto/ml_kem/:
crypto/ml_kem/
├── ml_kem.c -- the algorithm
├── build.info
└── asm/ -- PowerPC NTT/iNTT acceleration
├── mlkem_ntt_ppc64le.S
├── mlkem_intt_ppc64le.S
└── mlkem_ppc_macros_asm.incThree parameter sets:
| Variant | Public key | Ciphertext | Shared secret | Security |
|---|---|---|---|---|
| ML-KEM-512 | 800 B | 768 B | 32 B | Cat 1 |
| ML-KEM-768 | 1184 B | 1088 B | 32 B | Cat 3 |
| ML-KEM-1024 | 1568 B | 1568 B | 32 B | Cat 5 |
API surface (via EVP_KEM):
EVP_PKEY *kp = NULL;
EVP_PKEY_CTX *kctx = EVP_PKEY_CTX_new_from_name(libctx, "ML-KEM-768", NULL);
EVP_PKEY_keygen_init(kctx);
EVP_PKEY_keygen(kctx, &kp);
/* Encapsulate */
EVP_PKEY_CTX *ectx = EVP_PKEY_CTX_new_from_pkey(libctx, kp, NULL);
EVP_PKEY_encapsulate_init(ectx, NULL);
size_t ctlen = 0, klen = 0;
EVP_PKEY_encapsulate(ectx, NULL, &ctlen, NULL, &klen);
unsigned char *ct = OPENSSL_malloc(ctlen);
unsigned char *ss = OPENSSL_malloc(klen);
EVP_PKEY_encapsulate(ectx, ct, &ctlen, ss, &klen);
/* Decapsulate (peer side) */
EVP_PKEY_decapsulate_init(ectx, NULL);
EVP_PKEY_decapsulate(ectx, ss2, &klen, ct, ctlen);The KEM is exposed under the OSSL_OP_KEM operation. Implementation notes:
- The reference implementation is in
ml_kem.c. It is a clean-room implementation matching FIPS 203's pseudocode. - The PowerPC asm files implement the Number-Theoretic Transform on POWER10 vectors. x86_64 / aarch64 acceleration is reserved for future work.
- Keygen uses
RAND_priv_bytes, encapsulate usesRAND_bytes. - The "implicit rejection" mode (FIPS 203 §6.1) is implemented and is the only mode used.
ML-DSA (Module-Lattice Digital Signature, FIPS 204)
crypto/ml_dsa/:
crypto/ml_dsa/
├── ml_dsa.c, ml_dsa_local.h, ml_dsa_key.[ch]
├── ml_dsa_sign.[ch] -- the sign / verify algorithm
├── ml_dsa_sample.c -- expansion (rejection sampling, expandS, expandA)
├── ml_dsa_matrix.[ch] -- A matrix expansion
├── ml_dsa_poly.h, ml_dsa_vector.h
├── ml_dsa_ntt.c -- forward + inverse NTT
├── ml_dsa_params.c -- parameter sets
├── ml_dsa_hash.h -- SHAKE-128/256 binding
├── ml_dsa_key_compress.c -- HighBits / LowBits / power2round / decompose / makeHint / useHint
├── ml_dsa_encoders.c -- pack / unpack
├── build.info
└── asm/
└── ml_dsa_ntt-x86_64.pl -- AVX2-accelerated NTTThree parameter sets:
| Variant | Pubkey | Sig (avg) | Security |
|---|---|---|---|
| ML-DSA-44 | 1312 B | 2420 B | Cat 2 |
| ML-DSA-65 | 1952 B | 3309 B | Cat 3 |
| ML-DSA-87 | 2592 B | 4627 B | Cat 5 |
Exposed via EVP_SIGNATURE under names ML-DSA-44, -65, -87. Like RSA-PSS, ML-DSA can sign either a pre-hashed digest (HashML-DSA) or the message directly. Both are supported via the EVP_PKEY_sign / EVP_DigestSign paths.
SLH-DSA (SPHINCS+, FIPS 205)
crypto/slh_dsa/:
crypto/slh_dsa/
├── slh_dsa.c, slh_dsa_key.[ch], slh_dsa_local.h
├── slh_dsa_hash_ctx.c
├── slh_adrs.[ch] -- the ADRS field encoding
├── slh_hash.[ch] -- the SHA-2 / SHAKE hash family
├── slh_xmss.c -- XMSS subtrees
├── slh_hypertree.c -- the layered hypertree
├── slh_wots.c -- WOTS+ one-time signatures
├── slh_fors.c -- FORS few-time signatures
├── slh_params.[ch]
└── build.infoTwelve parameter sets: SLH-DSA-{SHA2,SHAKE}-{128,192,256}{s,f} (s = small signatures / slow signing; f = faster signing / larger signatures). Sizes range from 7,856 B (-128s) to 49,856 B (-256f) for signatures.
SLH-DSA is stateless: there is no signer state to maintain between signatures, and a key is safe to reuse arbitrarily (in contrast to LMS).
LMS (Leighton-Micali, RFC 8554)
crypto/lms/:
crypto/lms/
├── lms_key.c
├── lms_params.c -- parameter sets (LMS_SHA256_M32_H{5,10,15,20,25}, …)
├── lms_pubkey_decode.c
├── lms_sig.c -- LMS HSS signatures
├── lms_sig_decoder.c
├── lms_verify.c
├── lm_ots_params.c, lm_ots_verify.c -- the LM-OTS (one-time signature) underneath
└── build.infoLMS is stateful: each signature consumes a one-time signing slot in the tree. Reusing a slot leaks the private key. OpenSSL ships only verification by default — signing with stateful hash-based schemes is hazardous and is intentionally not the default surface; it is enabled in builds that need it for, e.g., FW signing where the signer is a careful HSM. Per the OpenSSL roadmap, signing is exposed but with stern documentation on safe use (see doc/man7/EVP_SIGNATURE-LMS.pod and doc/designs/lms_design.md).
Provider integration
All four algorithms ship under the default provider with provider=default, and under the FIPS provider with provider=fips,fips=yes. They are not in legacy. Encoders and decoders for keys live in providers/implementations/encode_decode/ (ml_kem_codecs.c, ml_dsa_codecs.c, slh_dsa_codecs.c, lms_codecs.c). The encoders produce DER per the IETF drafts (draft-ietf-lamps-kyber-certificates, -dilithium-certificates, -x509-slhdsa, RFC 8554).
Hybrid TLS group X25519MLKEM768
Defined by draft-ietf-tls-hybrid-design, this is a TLS 1.3 named group whose key share concatenates an X25519 ECDH share with an ML-KEM-768 encapsulation. The shared secret is the concatenation of the two component secrets, fed into TLS 1.3's HKDF normally. Implemented in providers/common/capabilities.c (registers X25519MLKEM768 as a TLS-GROUP) and in ssl/t1_lib.c (the hybrid construction). To enable:
SSL_CTX_set1_groups_list(ctx, "X25519MLKEM768:X25519:P-256");OpenSSL also publishes the mldsa44, mldsa65, mldsa87, slhdsa128f, slhdsa128s, slhdsa192f, slhdsa192s, slhdsa256f, slhdsa256s TLS-SIGALGs so an X.509 chain can use a pure-PQ signature.
Performance characteristics
| Algorithm | Keygen | Sign / Encap | Verify / Decap |
|---|---|---|---|
| RSA-2048 (signing baseline) | slow | medium | fast |
| ECDSA-P-256 | fast | fast | medium |
| ML-DSA-65 | fast | fast | fast |
| SLH-DSA-128s | fast | very slow | medium |
| SLH-DSA-128f | fast | medium | medium |
| LMS | (HSS depends on tree shape) | medium | very fast |
| ML-KEM-768 | fast | fast | fast |
Concrete numbers vary by CPU and build; the test/recipe harness includes Test::OpenSSL::PerfTest for repeatable benchmarks (see apps/openssl speed -evp ml-kem-768).
Integration points
- Providers publish them via the standard EVP_KEM / EVP_SIGNATURE / EVP_KEYMGMT operations.
- Encoders/decoders ship matching codecs so PEM/DER serialisation works.
- TLS uses ML-KEM via the hybrid TLS-GROUP and ML-DSA / SLH-DSA via TLS-SIGALG; certificates carrying these signatures are validated by the regular X.509 stack.
- CMS / PKCS#7 / X.509 / OCSP / CMP all work with these keys because every public-key consumer in OpenSSL goes through
EVP_PKEY.
Entry points for modification
- New parameter set: register a new keymgmt entry in
providers/implementations/keymgmt/<algo>_kmgmt.cand a signature/KEM entry in the corresponding directory. Most algorithms have the parameter table incrypto/<algo>/<algo>_params.c. - New asm-accelerated path: drop a
crypto/<algo>/asm/<algo>_<op>-<arch>.plperlasm file and wire it into the algorithm'sbuild.info. - Hybrid TLS group: extend the TLS-GROUP table in
providers/common/capabilities.cand the hybrid handling inssl/t1_lib.c.
Documentation
doc/man7/EVP_KEM-ML-KEM.poddoc/man7/EVP_SIGNATURE-ML-DSA.pod,EVP_SIGNATURE-SLH-DSA.pod,EVP_SIGNATURE-LMS.pod.doc/man7/EVP_PKEY-ML-KEM.pod,EVP_PKEY-ML-DSA.pod,EVP_PKEY-SLH-DSA.pod,EVP_PKEY-LMS.pod.doc/designs/ml-kem.md,ml-dsa.md,slh-dsa.md,lms_design.md.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.