Open-Source Wikis

/

OpenSSL

/

Features

/

Post-quantum cryptography

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.inc

Three 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 uses RAND_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 NTT

Three 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.info

Twelve 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.info

LMS 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.c and a signature/KEM entry in the corresponding directory. Most algorithms have the parameter table in crypto/<algo>/<algo>_params.c.
  • New asm-accelerated path: drop a crypto/<algo>/asm/<algo>_<op>-<arch>.pl perlasm file and wire it into the algorithm's build.info.
  • Hybrid TLS group: extend the TLS-GROUP table in providers/common/capabilities.c and the hybrid handling in ssl/t1_lib.c.

Documentation

  • doc/man7/EVP_KEM-ML-KEM.pod
  • doc/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.

Post-quantum cryptography – OpenSSL wiki | Factory