Commit 913e1d4bcd for openssl.org
commit 913e1d4bcd5d964055d0a59220a0fad55b14895d
Author: Viktor Dukhovni <openssl-users@dukhovni.org>
Date: Mon Feb 9 00:45:03 2026 +1100
Document ECDH over SM2 key exchange.
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Yang <paulyang.inf@gmail.com>
MergeDate: Sat Feb 21 13:26:15 2026
(Merged from https://github.com/openssl/openssl/pull/29953)
diff --git a/doc/build.info b/doc/build.info
index 581eb8fab2..09eca72b70 100644
--- a/doc/build.info
+++ b/doc/build.info
@@ -4895,6 +4895,10 @@ DEPEND[html/man7/EVP_SIGNATURE-SLH-DSA.html]=man7/EVP_SIGNATURE-SLH-DSA.pod
GENERATE[html/man7/EVP_SIGNATURE-SLH-DSA.html]=man7/EVP_SIGNATURE-SLH-DSA.pod
DEPEND[man/man7/EVP_SIGNATURE-SLH-DSA.7]=man7/EVP_SIGNATURE-SLH-DSA.pod
GENERATE[man/man7/EVP_SIGNATURE-SLH-DSA.7]=man7/EVP_SIGNATURE-SLH-DSA.pod
+DEPEND[html/man7/EVP_SIGNATURE-SM2.html]=man7/EVP_SIGNATURE-SM2.pod
+GENERATE[html/man7/EVP_SIGNATURE-SM2.html]=man7/EVP_SIGNATURE-SM2.pod
+DEPEND[man/man7/EVP_SIGNATURE-SM2.7]=man7/EVP_SIGNATURE-SM2.pod
+GENERATE[man/man7/EVP_SIGNATURE-SM2.7]=man7/EVP_SIGNATURE-SM2.pod
DEPEND[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
GENERATE[html/man7/OSSL_PROVIDER-FIPS.html]=man7/OSSL_PROVIDER-FIPS.pod
DEPEND[man/man7/OSSL_PROVIDER-FIPS.7]=man7/OSSL_PROVIDER-FIPS.pod
@@ -5273,6 +5277,7 @@ html/man7/EVP_SIGNATURE-LMS.html \
html/man7/EVP_SIGNATURE-ML-DSA.html \
html/man7/EVP_SIGNATURE-RSA.html \
html/man7/EVP_SIGNATURE-SLH-DSA.html \
+html/man7/EVP_SIGNATURE-SM2.html \
html/man7/OSSL_PROVIDER-FIPS.html \
html/man7/OSSL_PROVIDER-base.html \
html/man7/OSSL_PROVIDER-default.html \
@@ -5436,6 +5441,7 @@ man/man7/EVP_SIGNATURE-LMS.7 \
man/man7/EVP_SIGNATURE-ML-DSA.7 \
man/man7/EVP_SIGNATURE-RSA.7 \
man/man7/EVP_SIGNATURE-SLH-DSA.7 \
+man/man7/EVP_SIGNATURE-SM2.7 \
man/man7/OSSL_PROVIDER-FIPS.7 \
man/man7/OSSL_PROVIDER-base.7 \
man/man7/OSSL_PROVIDER-default.7 \
diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod
index 8fd9a671ee..e575cdca49 100644
--- a/doc/man3/SSL_CONF_cmd.pod
+++ b/doc/man3/SSL_CONF_cmd.pod
@@ -863,12 +863,12 @@ added in OpenSSL 3.2.
B<PreferNoDHEKEX> was added in OpenSSL 3.3.
-OpenSSL 3.5 introduces support for post-quantum (PQ) TLS key exchange via the
+OpenSSL 3.5 introduced support for post-quantum (PQ) TLS key exchange via the
B<MLKEM512>, B<MLKEM768> and B<MLKEM1024> TLS groups.
These are based on the underlying B<ML-KEM-512>, B<ML-KEM-768> and
B<ML-KEM-1024> algorithms from FIPS 203.
-OpenSSL 3.5 also introduces support for three B<hybrid> ECDH PQ key exchange
+OpenSSL 3.5 also introduced support for three B<hybrid> ECDH PQ key exchange
TLS groups: B<X25519MLKEM768>, B<SecP256r1MLKEM768> and
B<SecP384r1MLKEM1024>.
They offer CPU performance comparable to the associated ECDH group, though at
@@ -879,6 +879,10 @@ group.
Also its key exchange messages at close to 1700 bytes are larger than the
roughly 1200 bytes for the first two groups.
+OpenSSL 4.0 introduced the B<curveSM2> (also known as C<ECDHE over SM2>) key
+exchange group as specified in RFC8998, and B<curveSM2MLKEM768>, which is a
+hybrid of the B<curveSM2> group with B<ML-KEM-768>.
+
As of OpenSSL 3.5 key exchange group names are case-insensitive.
=head1 COPYRIGHT
diff --git a/doc/man3/SSL_CTX_set1_curves.pod b/doc/man3/SSL_CTX_set1_curves.pod
index 326d7bb4d4..98d6791cce 100755
--- a/doc/man3/SSL_CTX_set1_curves.pod
+++ b/doc/man3/SSL_CTX_set1_curves.pod
@@ -330,7 +330,7 @@ SSL_set1_groups_list() was added in OpenSSL 3.3.
Support for B<ML-KEM> was added in OpenSSL 3.5.
-OpenSSL 3.5 also introduces support for three I<hybrid> ECDH PQ key exchange
+OpenSSL 3.5 also introduced support for three I<hybrid> ECDH PQ key exchange
TLS groups: B<X25519MLKEM768>, B<SecP256r1MLKEM768> and
B<SecP384r1MLKEM1024>.
They offer CPU performance comparable to the associated ECDH group, though at
@@ -341,6 +341,10 @@ group.
Also its key exchange messages at close to 1700 bytes are larger than the
roughly 1200 bytes for the first two groups.
+OpenSSL 4.0 introduced the B<curveSM2> (also known as C<ECDHE over SM2>) key
+exchange group as specified in RFC8998, and B<curveSM2MLKEM768>, which is a
+hybrid of the B<curveSM2> group with B<ML-KEM-768>.
+
As of OpenSSL 3.5 key exchange group names are case-insensitive.
B<SSL_CTX_get0_implemented_groups> was first implemented in OpenSSL 3.5.
diff --git a/doc/man7/EVP_KEYEXCH-ECDH.pod b/doc/man7/EVP_KEYEXCH-ECDH.pod
index 280338ee92..1de8bfb1b7 100644
--- a/doc/man7/EVP_KEYEXCH-ECDH.pod
+++ b/doc/man7/EVP_KEYEXCH-ECDH.pod
@@ -8,6 +8,25 @@ EVP_KEYEXCH-ECDH - ECDH Key Exchange algorithm support
Key exchange support for the B<ECDH> key type.
+This algorithm supports B<ECDH> key agreement for general elliptic curves.
+Specialised support for the B<X25519> and B<X448> curves is documented in
+L<EVP_KEYEXCH-X25519(7)> and L<EVP_KEYEXCH-X448(7)>.
+
+As specified in L<RFC 8998|https://www.rfc-editor.org/rfc/rfc8998.html>, when
+B<curveSM2> is the negotiated key agreement group in TLS, B<ECDH> shared secret
+derivation is used instead of the normal key agreement protocol (KAP) specified
+in the C<GB/T 32918.3-2016> standard for the B<SM2> elliptic curve.
+This B<SM2> key agreement variant is also sometimes called C<ECDH over SM2>.
+When a B<curveSM2> key is generated or imported, the EC group name parameter to
+specify remains C<SM2>.
+The resulting B<curveSM2> key can only be used for C<ECDH over SM2> key
+agreement.
+C<ECDH over SM2> is TLS-specific, it should not be used in other protocols,
+absent a specification of its use in the protocol in question.
+
+The B<curveSM2MLKEM768> hybrid post-quantum key exchange algorithm
+uses C<ECDH over SM2> for its C<classical> component.
+
=head2 ECDH Key Exchange parameters
=over 4
@@ -121,6 +140,10 @@ L<provider-keymgmt(7)>,
L<OSSL_PROVIDER-default(7)>,
L<OSSL_PROVIDER-FIPS(7)>,
+=head1 HISTORY
+
+Support for C<ECDH over SM2> via B<curveSM2> was added in OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man7/EVP_PKEY-SM2.pod b/doc/man7/EVP_PKEY-SM2.pod
index 28a0e995d5..11ff04d36e 100644
--- a/doc/man7/EVP_PKEY-SM2.pod
+++ b/doc/man7/EVP_PKEY-SM2.pod
@@ -7,13 +7,33 @@ EVP_PKEY-SM2, EVP_KEYMGMT-SM2, SM2
=head1 DESCRIPTION
-The B<SM2> algorithm was first defined by the Chinese national standard GM/T
-0003-2012 and was later standardized by ISO as ISO/IEC 14888. B<SM2> is actually
-an elliptic curve based algorithm. The current implementation in OpenSSL supports
-both signature and encryption schemes via the EVP interface.
-
-When doing the B<SM2> signature algorithm, it requires a distinguishing identifier
-to form the message prefix which is hashed before the real message is hashed.
+The B<SM2> algorithm was first defined by the Chinese national standard C<GM/T
+0003-2012> and was later standardized by ISO as ISO/IEC 14888.
+B<SM2> is an elliptic curve-based algorithm.
+Its implementation in OpenSSL supports both signature and encryption schemes
+via the EVP interface.
+Under the name C<curveSM2> it also supports C<ECDH over SM2> as described in
+L<EVP_KEYEXCH-ECDH(7)>.
+
+The B<SM2> signature algorithm takes an optional I<distinguishing identifier>
+parameter (B<OSSL_PKEY_PARAM_DIST_ID>), which is used as part of a message
+prefix before hashing with B<SM3>.
+As specified in L<RFC 8998|https://www.rfc-editor.org/rfc/rfc8998.html>,
+when B<SM2> is used as part of the B<sm2sig_sm3> TLS signature scheme,
+this identifier must be set to the constant string C<TLSv1.3+GM+Cipher+Suite>.
+The OpenSSL TLS stack passes a protocol version parameter
+(B<OSSL_SIGNATURE_PARAM_TLS_VERSION>) to the signature algorithm, which then
+in the case of B<SM2> internally sets the distinguishing identifier to the
+expected constant.
+When B<SM2> is used for other purposes (e.g. in certificate signing or
+verification), and no explicit value of the distinguishing identifier is
+specified, a default value of C<1234567812345678> is used.
+
+An explicit empty distinguishing identifier value may need to be used to verify
+or create signatures that are compatible with versions of OpenSSL prior to 4.0.
+With the commandline tools an empty value can be specified with the use of
+either the B<-pkeyopt> (L<openssl-pkeyutl(1)>) or B<-sigopt>
+(L<openssl-dgst(1)>) option with a value of C<distid:>.
=head2 Common SM2 parameters
@@ -85,6 +105,13 @@ L<EVP_DigestVerifyInit(3)>,
L<EVP_PKEY_CTX_set1_id(3)>,
L<EVP_MD_CTX_set_pkey_ctx(3)>
+=head1 HISTORY
+
+Support for the B<sm2sig_sm3> TLS signature scheme was added in OpenSSL 4.0.
+
+The default value of the SM2 distinguishing identifier changed from empty to
+C<1234567812345678> as of OpenSSL 4.0.
+
=head1 COPYRIGHT
Copyright 2018-2024 The OpenSSL Project Authors. All Rights Reserved.
diff --git a/doc/man7/EVP_SIGNATURE-SM2.pod b/doc/man7/EVP_SIGNATURE-SM2.pod
new file mode 100644
index 0000000000..6eabb62ee8
--- /dev/null
+++ b/doc/man7/EVP_SIGNATURE-SM2.pod
@@ -0,0 +1,97 @@
+=pod
+
+=head1 NAME
+
+EVP_SIGNATURE-SM2 - The EVP_PKEY SM2 signature implementation.
+
+=head1 DESCRIPTION
+
+Support for computing SM2 signatures.
+See L<EVP_PKEY-SM2(7)> for information related to SM2 keys.
+
+This signature algorithm can be explicitly fetched with
+L<EVP_PKEY_sign_init_ex2(3)>, and implicitly fetched (through L<SM2
+keys|EVP_PKEY-SM2(7)>) with L<EVP_DigestSignInit_ex(3)> and
+L<EVP_DigestVerifyInit_ex(3)>.
+
+=head2 SM2 Signature Parameters
+
+The following signature parameters can be set using
+L<EVP_PKEY_CTX_set_params(3)>, L<EVP_DigestSignInit_ex(3)> or
+L<EVP_DigestVerifyInit_ex(3)>.
+
+=over 4
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+This defaults to the C<SM3> digest if not explicitly specified.
+
+=item "digest-size" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <size_t>
+
+This defaults to 32 bytes if not explicitly specified.
+Digests of a different size are not supported with B<SM2>.
+
+=item "distid" (B<OSSL_PKEY_PARAM_DIST_ID>) <UTF8 string>
+
+The I<distinguishing identifier> defaults to C<1234567812345678> if not
+explicitly specified.
+
+An explicit empty distinguishing identifier value may need to be used to verify
+or create signatures that are compatible with versions of OpenSSL prior to 4.0.
+With the commandline tools an empty value can be specified with the use of
+either the B<-pkeyopt> (L<openssl-pkeyutl(1)>) or B<-sigopt>
+(L<openssl-dgst(1)>) option with a value of C<distid:>.
+
+=item "tls-version" (B<OSSL_SIGNATURE_PARAM_TLS_VERSION>) <uint>
+
+The OpenSSL 4.0 or later TLS protocol engine passes this parameter to the
+underlying signature algorithm when signing or verifying TLS
+B<CertificateVerify> messages.
+When the protocol version is TLS 1.3 (0x0304), the SM2 signature algorithm will
+use the RFC8998 I<distinguished identifier> instead of the default value noted
+above.
+
+=back
+
+The following signature parameters can be retrieved using
+EVP_PKEY_CTX_get_params().
+
+=over 4
+
+=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string>
+
+This returns the DER encoding of the B<SM2-with-SM3> signature OID.
+
+=item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string>
+
+=item "digest-size" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <size_t>
+
+=back
+
+=head1 SEE ALSO
+
+L<EVP_PKEY_CTX_set_params(3)>,
+L<EVP_PKEY_sign(3)>,
+L<EVP_PKEY_verify(3)>,
+L<EVP_DigestSignInit_ex(3)>,
+L<EVP_DigestVerifyInit_ex(3)>,
+L<provider-signature(7)>,
+
+=head1 HISTORY
+
+The default value of the SM2 distinguishing identifier changed from empty to
+C<1234567812345678> as of OpenSSL 4.0.
+
+Support for the B<OSSL_SIGNATURE_PARAM_TLS_VERSION> parameter was added in
+OpenSSL 4.0.
+
+=head1 COPYRIGHT
+
+Copyright 2020-2024 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