Commit e483d93b39 for openssl.org
commit e483d93b393bec71327c3b31779e8dcf37b3f42b
Author: slontis <shane.lontis@oracle.com>
Date: Tue Feb 17 16:05:14 2026 +1100
Doc: Add documentation for existing Hybrid ML_KEM algorithms used by
TLS1.3.
Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Neil Horman <nhorman@openssl.org>
MergeDate: Mon May 4 11:51:12 2026
(Merged from https://github.com/openssl/openssl/pull/30037)
diff --git a/doc/build.info b/doc/build.info
index e5c62b258a..d0e5088b9c 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -4831,6 +4831,10 @@ DEPEND[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod
GENERATE[html/man7/EVP_PKEY-ML-KEM.html]=man7/EVP_PKEY-ML-KEM.pod
DEPEND[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.pod
GENERATE[man/man7/EVP_PKEY-ML-KEM.7]=man7/EVP_PKEY-ML-KEM.pod
+DEPEND[html/man7/EVP_PKEY-MLX-KEM.html]=man7/EVP_PKEY-MLX-KEM.pod
+GENERATE[html/man7/EVP_PKEY-MLX-KEM.html]=man7/EVP_PKEY-MLX-KEM.pod
+DEPEND[man/man7/EVP_PKEY-MLX-KEM.7]=man7/EVP_PKEY-MLX-KEM.pod
+GENERATE[man/man7/EVP_PKEY-MLX-KEM.7]=man7/EVP_PKEY-MLX-KEM.pod
DEPEND[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
GENERATE[html/man7/EVP_PKEY-RSA.html]=man7/EVP_PKEY-RSA.pod
DEPEND[man/man7/EVP_PKEY-RSA.7]=man7/EVP_PKEY-RSA.pod
@@ -5274,6 +5278,7 @@ html/man7/EVP_PKEY-HMAC.html \
html/man7/EVP_PKEY-LMS.html \
html/man7/EVP_PKEY-ML-DSA.html \
html/man7/EVP_PKEY-ML-KEM.html \
+html/man7/EVP_PKEY-MLX-KEM.html \
html/man7/EVP_PKEY-RSA.html \
html/man7/EVP_PKEY-SLH-DSA.html \
html/man7/EVP_PKEY-SM2.html \
@@ -5439,6 +5444,7 @@ man/man7/EVP_PKEY-HMAC.7 \
man/man7/EVP_PKEY-LMS.7 \
man/man7/EVP_PKEY-ML-DSA.7 \
man/man7/EVP_PKEY-ML-KEM.7 \
+man/man7/EVP_PKEY-MLX-KEM.7 \
man/man7/EVP_PKEY-RSA.7 \
man/man7/EVP_PKEY-SLH-DSA.7 \
man/man7/EVP_PKEY-SM2.7 \
diff --git a/doc/man7/EVP_PKEY-MLX-KEM.pod b/doc/man7/EVP_PKEY-MLX-KEM.pod
new file mode 100644
index 0000000000..12134056b0
--- /dev/null
+++ b/doc/man7/EVP_PKEY-MLX-KEM.pod
@@ -0,0 +1,221 @@
+=pod
+
+=head1 NAME
+
+EVP_PKEY-MLX-KEM, EVP_KEYMGMT-MLX-KEM - Hybrid ML-KEM key support for TLS 1.3
+
+=head1 DESCRIPTION
+
+These hybrid ML_KEM algorithms derive the session secret from both a
+ECDH (classical) algorithm (such as X25519, or P-256) and a post-quantum
+algorithm (ML_KEM), ensuring that key agreement remains secure unless both
+schemes are broken.
+
+The algorithms supported here are specifically for use in TLS 1.3 and are not
+suitable for other purposes. There is no encoder/decoder support, and
+EVP_PKEY_CTX_new_id() is also not supported as there are no associated EVP_PKEY
+type identifiers.
+
+The following names can be used by EVP_PKEY_CTX_new_from_name() using OpenSSL's
+default and FIPS providers.
+
+=over 4
+
+=item B<X25519MLKEM768>
+
+The shared secret is the concatenation of a 32 byte L<EVP_PKEY-ML-KEM(7)> shared
+secret followed by a 32 byte L<EVP_PKEY-X25519(7)> shared secret. X25519 is not an
+approved FIPS algorithm, but this combination is still allowed by FIPS 140-3
+since ML-KEM is FIPS approved.
+
+=item B<X448MLKEM1024>
+
+Similar to B<X25519MLKEM768> with a higher security strength, the shared secret
+is the concatenation of a 32 byte L<EVP_PKEY-ML-KEM(7)> shared secret followed
+by a 56 byte L<EVP_PKEY-X448(7)> shared secret.
+
+=item B<SecP256r1MLKEM768>
+
+The shared secret is the concatenation of a 32 byte L<EVP_PKEY-EC(7)> shared
+secret followed by a 32 byte L<EVP_PKEY-ML-KEM(7)> shared secret.
+Both algorithms used are FIPS approved.
+
+=item B<SecP384r1MLKEM1024>
+
+Similar to B<SecP256r1MLKEM768> with a higher security strength, the shared
+secret is the concatenation of a 48 byte L<EVP_PKEY-EC(7)> shared
+secret followed by a 32 byte L<EVP_PKEY-ML-KEM(7)> shared secret.
+
+=back
+
+The following name is supported only in OpenSSL's default provider.
+
+=over 4
+
+=item B<curveSM2MLKEM768>
+
+The shared secret is the concatenation of a 32 byte L<EVP_PKEY-SM2(7)> shared
+secret followed by a 32 byte L<EVP_PKEY-ML-KEM(7)> shared secret.
+
+=back
+
+=head2 Keygen Parameters
+
+No mandatory parameters are required for generating a key pair.
+To set the optional parameter, use L<EVP_PKEY_CTX_set_params(3)> after calling
+L<EVP_PKEY_keygen_init(3)>.
+
+=over 4
+
+=item "properties" (B<OSSL_PKEY_PARAM_PROPERTIES>) <UTF8 string>
+
+Sets properties to be used when fetching algorithm implementations used for
+the B<ML-KEM>, B<ECDH> or B<SM2> algorithms.
+
+=back
+
+=head2 Common parameters
+
+See L<provider-keymgmt(7)/Common Information Parameters>)
+for common information related to parameters.
+
+The following common gettables can be retrieved using
+L<EVP_PKEY_get_int_param(3)>, they retrieve information related to the ML-KEM
+algorithm.
+
+=over 4
+
+=item 'bits' (B<OSSL_PKEY_PARAM_BITS>) <integer>
+
+=item "security-bits" (B<OSSL_PKEY_PARAM_SECURITY_BITS>) <integer>
+
+=item "security-category" (B<OSSL_PKEY_PARAM_SECURITY_CATEGORY>) <integer>
+
+=item "max-size" (B<OSSL_PKEY_PARAM_MAX_SIZE>) <integer>
+
+This value is the combined size of the 2 shared secrets as described above.
+
+=back
+
+The following parameters are also handled.
+
+=over 4
+
+=item "encoded-pub-key" (B<OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY>) <octet string>
+
+Used for getting and setting the encoding of concatenated public keys.
+The public keys can not be modified once they are set.
+
+The format of the public keys for the different algorithms is:
+
+=over 4
+
+=item B<SecP256r1MLKEM768>
+
+A 65 byte EC public key followed by a 1184 byte ML-KEM-768 public key.
+
+=item B<SecP384r1MLKEM1024>
+
+A 97 byte EC public key followed by a 1568 byte ML-KEM-1024 public key.
+
+=item B<X25519MLKEM768>
+
+A 1184 byte ML-KEM-768 public key followed by a 32 byte X25519 public key.
+
+=item B<X448MLKEM1024>
+
+A 1568 byte ML-KEM-1024 public key followed by a 56 byte X448 public key.
+
+=item B<curveSM2MLKEM768>
+
+A 65 byte SM2 public key followed by a 1184 byte ML-KEM-768 public key.
+
+=back
+
+=item "pub" (B<OSSL_PKEY_PARAM_PUB_KEY>) <octet string>
+
+The public key value.
+
+This parameter is only used when importing or exporting the public key value with
+the EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
+The public key format format is the same as "encoded-pub-key".
+
+=item "priv" (B<OSSL_PKEY_PARAM_PRIV_KEY>) <octet string>
+
+The private key value which is the concatenation of 2 internal private keys.
+
+This parameter can be used when importing or exporting the private key value
+using the EVP_PKEY_fromdata() and EVP_PKEY_todata() functions.
+Initial import aside, this parameter is otherwise only gettable.
+
+The format of the private keys for the different algorithms is:
+
+=over 4
+
+=item B<SecP256r1MLKEM768>
+
+32 byte EC private key followed by a 2400 byte ML-KEM-768 private key.
+
+=item B<SecP384r1MLKEM1024>
+
+48 byte EC private key followed by a 3168 byte ML-KEM-1024 private key.
+
+=item B<X25519MLKEM768>
+
+2400 byte ML-KEM-768 private key followed by a 32 byte X25519 private key.
+
+=item B<X448MLKEM1024>
+
+3168 byte ML-KEM-1024 private key followed by a 56 byte X448 private key.
+
+=item B<curveSM2MLKEM768>
+
+32 byte SM2 private key followed by a 2400 byte ML-KEM-768 private key.
+
+=back
+
+=back
+
+=head1 CONFORMING TO
+
+=over 4
+
+=item https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/
+
+Note that B<X448MLKEM1024> is not defined by this document.
+
+=item SP800-227
+
+The general notation used in this document says that outputs are
+combined/processed in order of the names.
+B<X25519MLKEM768> and B<X448MLKEM768> however use the reverse order since
+X25519 and X448 are not FIPS approved algorithms.
+Even though they are not FIPS approved the hybrid combination is still allowed
+since MLKEM is FIPS approved.
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_KEM-ML-KEM(7)>,
+L<EVP_PKEY-X25519(7)>,
+L<EVP_PKEY-EC(7)>,
+L<EVP_PKEY-SM2(7)>,
+L<provider-keymgmt(7)>
+
+=head1 HISTORY
+
+This functionality was added in OpenSSL 3.5.
+
+Support for B<curveSM2MLKEM768> was added in OpenSSL 4.0.
+
+=head1 COPYRIGHT
+
+Copyright 2026 The OpenSSL Project Authors. All Rights Reserved.
+
+Licensed under the Apache License 2.0 (the "License"). You may not use
+this file except in compliance with the License. You can obtain a copy
+in the file LICENSE in the source distribution or at
+L<https://www.openssl.org/source/license.html>.
+
+=cut
diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod
index 04e722f1dc..c45788ddf9 100644
--- a/doc/man7/OSSL_PROVIDER-FIPS.pod
+++ b/doc/man7/OSSL_PROVIDER-FIPS.pod
@@ -153,7 +153,19 @@ It is used internally as a sub algorithm of CSHAKE.
=item X448, see L<EVP_KEYEXCH-X448(7)>
-=item ML-KEM, see L<EVP_KEM-ML-KEM(7)>
+=item ML-KEM-512, see L<EVP_KEM-ML-KEM-512(7)>
+
+=item ML-KEM-768, see L<EVP_KEM-ML-KEM-768(7)>
+
+=item ML-KEM-1024, see L<EVP_KEM-ML-KEM-1024(7)>
+
+=item X25519MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item X448MLKEM1024, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item SecP256r1MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item SecP384r1MLKEM1024, see L<EVP_PKEY-MLX-KEM(7)>
=item TLS1-PRF
@@ -257,6 +269,20 @@ included in SP 800-56Arev3 are not approved for key agreement".
=item ML-DSA-87, see L<EVP_KEYMGMT-ML-DSA(7)>
+=item MK-KEM-512, see L<EVP_KEYMGMT-ML-KEM-512(7)>
+
+=item MK-KEM-768, see L<EVP_KEYMGMT-ML-KEM-768(7)>
+
+=item MK-KEM-1024, see L<EVP_KEYMGMT-ML-KEM-1024(7)>
+
+=item X25519MLKEM768, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item X448MLKEM1024, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item SecP256r1MLKEM768, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item SecP384r1MLKEM1024, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
=item SLH-DSA-SHA2-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
=item SLH-DSA-SHA2-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod
index c987e9de96..e61d3d8137 100644
--- a/doc/man7/OSSL_PROVIDER-default.pod
+++ b/doc/man7/OSSL_PROVIDER-default.pod
@@ -189,6 +189,16 @@ The OpenSSL default provider supports these operations and algorithms:
=item ML-KEM-1024, see L<EVP_KEM-ML-KEM-1024(7)>
+=item X25519MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item X448MLKEM1024, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item SecP256r1MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item SecP384r1MLKEM1024, see L<EVP_PKEY-MLX-KEM(7)>
+
+=item curveSM2MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
=item TLS1-PRF
=item HKDF
@@ -323,6 +333,16 @@ The OpenSSL default provider supports these operations and algorithms:
=item MK-KEM-1024, see L<EVP_KEYMGMT-ML-KEM-1024(7)>
+=item X25519MLKEM768, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item X448MLKEM1024, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item SecP256r1MLKEM768, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item SecP384r1MLKEM1024, see L<EVP_KEYMGMT-MLX-KEM(7)>
+
+=item curveSM2MLKEM768, see L<EVP_PKEY-MLX-KEM(7)>
+
=item SLH-DSA-SHA2-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
=item SLH-DSA-SHA2-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
@@ -548,16 +568,21 @@ L<OSSL_PROVIDER-base(7)>
=head1 HISTORY
-Support for B<LMS> Public Key (SubjectPublicKeyInfo) encoders and decoders
-was added in OpenSSL 4.0.
+Base functionality was added in OpenSSL 3.0.
The RIPEMD160 digest was added to the default provider in OpenSSL 3.0.7.
+Support for B<X25519MLKEM768>, B<X448MLKEM1024>, B<SecP256r1MLKEM768> and
+B<SecP384r1MLKEM1024> was added in OpenSSL 3.5.
+
The HKDF-SHA256, HKDF-SHA384 and HKDF-SHA512 algorithms were added in OpenSSL 3.6.
-The CSHAKE-128 and CSHAKE-256 algorithms were added in OpenSSL 4.0.
+Support for B<LMS> Public Key (SubjectPublicKeyInfo) encoders and decoders
+was added in OpenSSL 4.0.
+
+Support for B<curveSM2MLKEM768> was added in OpenSSL 4.0.
-All other functionality was added in OpenSSL 3.0.
+Support for CSHAKE-128 and CSHAKE-256 was added in OpenSSL 4.0.
=head1 COPYRIGHT