Commit a1689251bb for openssl.org

commit a1689251bb12d6e21787687cb19bf3584938454f
Author: Viktor Dukhovni <openssl-users@dukhovni.org>
Date:   Wed Feb 11 03:32:17 2026 +1100

    Support for RFC8998 curveSM2 + hybrid

    This adds support for the "sm2sig_sm3" TLS 1.3 signature algorithm, the
    "curveSM2" key exchange group (ECDH over SM2) and the associated
    post-quantum/traditional (PQ/T) hybrid "curveSM2MLKEM768" key exchange.

    The default key agreement group list is expanded to add two additional
    PQ groups, immediately after X25519MLKEM768.  These are the P-256-based
    SecP256r1MLKEM768 and the SM2-based curveSMMLKEM768.  Neither of the new
    groups is a default client keyshare group, these would only come into
    play after a server HRR, if for some reason X25519MLKEM768 is not
    supported by the server, X25519 is not then the server's most
    preferred group, and the server supports and prefers one of these
    of X25519.

    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:07 2026
    (Merged from https://github.com/openssl/openssl/pull/29953)

diff --git a/include/internal/tlsgroups.h b/include/internal/tlsgroups.h
index 7c1eb26e3e..ba7fa60dc2 100644
--- a/include/internal/tlsgroups.h
+++ b/include/internal/tlsgroups.h
@@ -51,6 +51,7 @@
 #define OSSL_TLS_GROUP_ID_gc512A 0x0026
 #define OSSL_TLS_GROUP_ID_gc512B 0x0027
 #define OSSL_TLS_GROUP_ID_gc512C 0x0028
+#define OSSL_TLS_GROUP_ID_curveSM2 0x0029
 #define OSSL_TLS_GROUP_ID_ffdhe2048 0x0100
 #define OSSL_TLS_GROUP_ID_ffdhe3072 0x0101
 #define OSSL_TLS_GROUP_ID_ffdhe4096 0x0102
@@ -62,6 +63,7 @@
 #define OSSL_TLS_GROUP_ID_SecP256r1MLKEM768 0x11EB
 #define OSSL_TLS_GROUP_ID_X25519MLKEM768 0x11EC
 #define OSSL_TLS_GROUP_ID_SecP384r1MLKEM1024 0x11ED
+#define OSSL_TLS_GROUP_ID_curveSM2MLKEM768 0x11EE

 /*
  * RFC 7919: "Codepoints ... between 256 and 511, inclusive ... are set aside
diff --git a/include/internal/tlssigalgs.h b/include/internal/tlssigalgs.h
new file mode 100644
index 0000000000..1d6c9df49f
--- /dev/null
+++ b/include/internal/tlssigalgs.h
@@ -0,0 +1,95 @@
+/*
+ * 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
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef OSSL_INTERNAL_TLSSIGALGS_H
+#define OSSL_INTERNAL_TLSSIGALGS_H
+#pragma once
+
+/* Sigalgs values */
+#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256 0x0403
+#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384 0x0503
+#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603
+#define TLSEXT_SIGALG_ecdsa_sha224 0x0303
+#define TLSEXT_SIGALG_ecdsa_sha1 0x0203
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha256 0x0804
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha384 0x0805
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha512 0x0806
+#define TLSEXT_SIGALG_rsa_pss_pss_sha256 0x0809
+#define TLSEXT_SIGALG_rsa_pss_pss_sha384 0x080a
+#define TLSEXT_SIGALG_rsa_pss_pss_sha512 0x080b
+#define TLSEXT_SIGALG_rsa_pkcs1_sha256 0x0401
+#define TLSEXT_SIGALG_rsa_pkcs1_sha384 0x0501
+#define TLSEXT_SIGALG_rsa_pkcs1_sha512 0x0601
+#define TLSEXT_SIGALG_rsa_pkcs1_sha224 0x0301
+#define TLSEXT_SIGALG_rsa_pkcs1_sha1 0x0201
+#define TLSEXT_SIGALG_dsa_sha256 0x0402
+#define TLSEXT_SIGALG_dsa_sha384 0x0502
+#define TLSEXT_SIGALG_dsa_sha512 0x0602
+#define TLSEXT_SIGALG_dsa_sha224 0x0302
+#define TLSEXT_SIGALG_dsa_sha1 0x0202
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic 0x0840
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic 0x0841
+#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee
+#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef
+#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded
+
+#define TLSEXT_SIGALG_sm2sig_sm3 0x0708
+#define TLSEXT_SIGALG_ed25519 0x0807
+#define TLSEXT_SIGALG_ed448 0x0808
+#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256 0x081a
+#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384 0x081b
+#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512 0x081c
+#define TLSEXT_SIGALG_mldsa44 0x0904
+#define TLSEXT_SIGALG_mldsa65 0x0905
+#define TLSEXT_SIGALG_mldsa87 0x0906
+
+/* Sigalgs names */
+#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name "ecdsa_secp256r1_sha256"
+#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name "ecdsa_secp384r1_sha384"
+#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512_name "ecdsa_secp521r1_sha512"
+#define TLSEXT_SIGALG_ecdsa_sha224_name "ecdsa_sha224"
+#define TLSEXT_SIGALG_ecdsa_sha1_name "ecdsa_sha1"
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha256_name "rsa_pss_rsae_sha256"
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha384_name "rsa_pss_rsae_sha384"
+#define TLSEXT_SIGALG_rsa_pss_rsae_sha512_name "rsa_pss_rsae_sha512"
+#define TLSEXT_SIGALG_rsa_pss_pss_sha256_name "rsa_pss_pss_sha256"
+#define TLSEXT_SIGALG_rsa_pss_pss_sha384_name "rsa_pss_pss_sha384"
+#define TLSEXT_SIGALG_rsa_pss_pss_sha512_name "rsa_pss_pss_sha512"
+#define TLSEXT_SIGALG_rsa_pkcs1_sha256_name "rsa_pkcs1_sha256"
+#define TLSEXT_SIGALG_rsa_pkcs1_sha384_name "rsa_pkcs1_sha384"
+#define TLSEXT_SIGALG_rsa_pkcs1_sha512_name "rsa_pkcs1_sha512"
+#define TLSEXT_SIGALG_rsa_pkcs1_sha224_name "rsa_pkcs1_sha224"
+#define TLSEXT_SIGALG_rsa_pkcs1_sha1_name "rsa_pkcs1_sha1"
+#define TLSEXT_SIGALG_dsa_sha256_name "dsa_sha256"
+#define TLSEXT_SIGALG_dsa_sha384_name "dsa_sha384"
+#define TLSEXT_SIGALG_dsa_sha512_name "dsa_sha512"
+#define TLSEXT_SIGALG_dsa_sha224_name "dsa_sha224"
+#define TLSEXT_SIGALG_dsa_sha1_name "dsa_sha1"
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_name "gostr34102012_256"
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_name "gostr34102012_512"
+#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias "gost2012_256"
+#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_alias "gost2012_512"
+#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name "gost2012_256"
+#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name "gost2012_512"
+#define TLSEXT_SIGALG_gostr34102001_gostr3411_name "gost2001_gost94"
+
+#define TLSEXT_SIGALG_sm2sig_sm3_name "sm2sig_sm3"
+#define TLSEXT_SIGALG_ed25519_name "ed25519"
+#define TLSEXT_SIGALG_ed448_name "ed448"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name "ecdsa_brainpoolP256r1tls13_sha256"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name "ecdsa_brainpoolP384r1tls13_sha384"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name "ecdsa_brainpoolP512r1tls13_sha512"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_alias "ecdsa_brainpoolP256r1_sha256"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_alias "ecdsa_brainpoolP384r1_sha384"
+#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_alias "ecdsa_brainpoolP512r1_sha512"
+#define TLSEXT_SIGALG_mldsa44_name "mldsa44"
+#define TLSEXT_SIGALG_mldsa65_name "mldsa65"
+#define TLSEXT_SIGALG_mldsa87_name "mldsa87"
+
+#endif
diff --git a/providers/common/capabilities.c b/providers/common/capabilities.c
index eb96627a67..dd8af791e7 100644
--- a/providers/common/capabilities.c
+++ b/providers/common/capabilities.c
@@ -16,6 +16,7 @@
 #include <openssl/params.h>
 #include "internal/nelem.h"
 #include "internal/tlsgroups.h"
+#include "internal/tlssigalgs.h"
 #include "prov/providercommon.h"
 #include "internal/e_os.h"
 #include "crypto/ml_kem.h"
@@ -91,6 +92,8 @@ static const TLS_GROUP_CONSTANTS group_list[] = {
     /* 41 */ { OSSL_TLS_GROUP_ID_X25519MLKEM768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
     /* 42 */ { OSSL_TLS_GROUP_ID_SecP256r1MLKEM768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
     /* 43 */ { OSSL_TLS_GROUP_ID_SecP384r1MLKEM1024, ML_KEM_1024_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
+    /* 44 */ { OSSL_TLS_GROUP_ID_curveSM2, 128, TLS1_3_VERSION, 0, -1, -1, 0 },
+    /* 45 */ { OSSL_TLS_GROUP_ID_curveSM2MLKEM768, ML_KEM_768_SECBITS, TLS1_3_VERSION, 0, -1, -1, 1 },
 };

 #define TLS_GROUP_ENTRY(tlsname, realname, algorithm, idx)              \
@@ -187,6 +190,12 @@ static const OSSL_PARAM param_group_list[][11] = {
     TLS_GROUP_ENTRY("brainpoolP256r1tls13", "brainpoolP256r1", "EC", 30),
     TLS_GROUP_ENTRY("brainpoolP384r1tls13", "brainpoolP384r1", "EC", 31),
     TLS_GROUP_ENTRY("brainpoolP512r1tls13", "brainpoolP512r1", "EC", 32),
+#ifndef OPENSSL_NO_SM2
+    TLS_GROUP_ENTRY("curveSM2", "SM2", "curveSM2", 44),
+#if !defined(OPENSSL_NO_ML_KEM)
+    TLS_GROUP_ENTRY("curveSM2MLKEM768", "", "curveSM2MLKEM768", 45),
+#endif
+#endif
 #endif
 #ifndef OPENSSL_NO_ML_KEM
     TLS_GROUP_ENTRY("SecP256r1MLKEM768", "", "SecP256r1MLKEM768", 42),
@@ -272,7 +281,8 @@ static int tls_group_capability(OSSL_CALLBACK *cb, void *arg)

 /* --------------------------------------------------------------- */

-#if !defined(OPENSSL_NO_ML_DSA)
+#if !defined(OPENSSL_NO_ML_DSA) \
+    || (!defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2) && !defined(OPENSSL_NO_SM3))

 typedef struct tls_sigalg_constants_st {
     unsigned int code_point;
@@ -283,10 +293,11 @@ typedef struct tls_sigalg_constants_st {
     int max_dtls; /* Maximum DTLS version (or 0 for undefined) */
 } TLS_SIGALG_CONSTANTS;

-static const TLS_SIGALG_CONSTANTS sigalg_constants_list[3] = {
-    { 0x0904, 128, TLS1_3_VERSION, 0, -1, -1 },
-    { 0x0905, 192, TLS1_3_VERSION, 0, -1, -1 },
-    { 0x0906, 256, TLS1_3_VERSION, 0, -1, -1 },
+static const TLS_SIGALG_CONSTANTS sigalg_constants_list[] = {
+    { TLSEXT_SIGALG_mldsa44, 128, TLS1_3_VERSION, 0, -1, -1 },
+    { TLSEXT_SIGALG_mldsa65, 192, TLS1_3_VERSION, 0, -1, -1 },
+    { TLSEXT_SIGALG_mldsa87, 256, TLS1_3_VERSION, 0, -1, -1 },
+    { TLSEXT_SIGALG_sm2sig_sm3, 128, TLS1_3_VERSION, 0, -1, -1 },
 };

 #define TLS_SIGALG_ENTRY(tlsname, algorithm, oid, idx)               \
@@ -313,15 +324,20 @@ static const TLS_SIGALG_CONSTANTS sigalg_constants_list[3] = {
     }

 static const OSSL_PARAM param_sigalg_list[][10] = {
+#ifndef OPENSSL_NO_ML_DSA
     TLS_SIGALG_ENTRY("mldsa44", "ML-DSA-44", "2.16.840.1.101.3.4.3.17", 0),
     TLS_SIGALG_ENTRY("mldsa65", "ML-DSA-65", "2.16.840.1.101.3.4.3.18", 1),
     TLS_SIGALG_ENTRY("mldsa87", "ML-DSA-87", "2.16.840.1.101.3.4.3.19", 2),
+#endif
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2) && !defined(OPENSSL_NO_SM3)
+    TLS_SIGALG_ENTRY("sm2sig_sm3", "SM2", "1.2.156.10197.1 501", 3),
+#endif
 };
-#endif /* OPENSSL_NO_ML_DSA */
+#endif

 static int tls_sigalg_capability(OSSL_CALLBACK *cb, void *arg)
 {
-#if !defined(OPENSSL_NO_ML_DSA)
+#if defined(TLS_SIGALG_ENTRY)
     size_t i;

     for (i = 0; i < OSSL_NELEM(param_sigalg_list); i++)
diff --git a/providers/defltprov.c b/providers/defltprov.c
index f71b0e157a..c0f83faf85 100644
--- a/providers/defltprov.c
+++ b/providers/defltprov.c
@@ -570,6 +570,9 @@ static const OSSL_ALGORITHM deflt_asym_kem[] = {
     { PROV_NAMES_SecP256r1MLKEM768, "provider=default", ossl_mlx_kem_asym_kem_functions },
     { PROV_NAMES_SecP384r1MLKEM1024, "provider=default", ossl_mlx_kem_asym_kem_functions },
 #endif
+#if !defined(OPENSSL_NO_SM2)
+    { PROV_NAMES_curveSM2MLKEM768, "provider=default", ossl_mlx_kem_asym_kem_functions },
+#endif
 #endif
     { NULL, NULL, NULL }
 };
@@ -632,6 +635,8 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
 #ifndef OPENSSL_NO_SM2
     { PROV_NAMES_SM2, "provider=default", ossl_sm2_keymgmt_functions,
         PROV_DESCS_SM2 },
+    { PROV_NAMES_curveSM2, "provider=default", ossl_curve_sm2_keymgmt_functions,
+        PROV_DESCS_curveSM2 },
 #endif
 #ifndef OPENSSL_NO_LMS
     { PROV_NAMES_LMS, "provider=default", ossl_lms_keymgmt_functions,
@@ -656,6 +661,10 @@ static const OSSL_ALGORITHM deflt_keymgmt[] = {
     { PROV_NAMES_SecP384r1MLKEM1024, "provider=default", ossl_mlx_p384_kem_kmgmt_functions,
         PROV_DESCS_SecP384r1MLKEM1024 },
 #endif
+#if !defined(OPENSSL_NO_SM2)
+    { PROV_NAMES_curveSM2MLKEM768, "provider=default", ossl_mlx_curve_sm2_kem_kmgmt_functions,
+        PROV_DESCS_curveSM2MLKEM768 },
+#endif
 #endif
 #ifndef OPENSSL_NO_SLH_DSA
     { PROV_NAMES_SLH_DSA_SHA2_128S, "provider=default", ossl_slh_dsa_sha2_128s_keymgmt_functions,
diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h
index a3b0187b80..86f876a0db 100644
--- a/providers/implementations/include/prov/implementations.h
+++ b/providers/implementations/include/prov/implementations.h
@@ -337,6 +337,7 @@ extern const OSSL_DISPATCH ossl_ed448_keymgmt_functions[];
 #endif
 #ifndef OPENSSL_NO_SM2
 extern const OSSL_DISPATCH ossl_sm2_keymgmt_functions[];
+extern const OSSL_DISPATCH ossl_curve_sm2_keymgmt_functions[];
 #endif
 #endif
 #ifndef OPENSSL_NO_LMS
@@ -356,6 +357,9 @@ extern const OSSL_DISPATCH ossl_mlx_x448_kem_kmgmt_functions[];
 #endif
 extern const OSSL_DISPATCH ossl_mlx_p256_kem_kmgmt_functions[];
 extern const OSSL_DISPATCH ossl_mlx_p384_kem_kmgmt_functions[];
+#ifndef OPENSSL_NO_SM2
+extern const OSSL_DISPATCH ossl_mlx_curve_sm2_kem_kmgmt_functions[];
+#endif
 #endif
 #endif
 #ifndef OPENSSL_NO_SLH_DSA
diff --git a/providers/implementations/include/prov/names.h b/providers/implementations/include/prov/names.h
index 70c4eb0373..8bfed63ff5 100644
--- a/providers/implementations/include/prov/names.h
+++ b/providers/implementations/include/prov/names.h
@@ -414,6 +414,8 @@
 #define PROV_DESCS_RSA_PSS "OpenSSL RSA-PSS implementation"
 #define PROV_NAMES_SM2 "SM2:1.2.156.10197.1.301"
 #define PROV_DESCS_SM2 "OpenSSL SM2 implementation"
+#define PROV_NAMES_curveSM2 "curveSM2"
+#define PROV_DESCS_curveSM2 "OpenSSL curveSM2 implementation"
 #define PROV_NAMES_LMS "LMS"
 #define PROV_DESCS_LMS "OpenSSL LMS implementation"
 #define PROV_NAMES_ML_DSA_44 "ML-DSA-44:MLDSA44:2.16.840.1.101.3.4.3.17:id-ml-dsa-44"
@@ -436,6 +438,8 @@
 #define PROV_DESCS_SecP256r1MLKEM768 "P-256+ML-KEM-768 TLS hybrid implementation"
 #define PROV_NAMES_SecP384r1MLKEM1024 "SecP384r1MLKEM1024"
 #define PROV_DESCS_SecP384r1MLKEM1024 "P-384+ML-KEM-1024 TLS hybrid implementation"
+#define PROV_NAMES_curveSM2MLKEM768 "curveSM2MLKEM768"
+#define PROV_DESCS_curveSM2MLKEM768 "curveSM2+ML-KEM-768 TLS hybrid implementation"
 #define PROV_NAMES_SLH_DSA_SHA2_128S "SLH-DSA-SHA2-128s:id-slh-dsa-sha2-128s:2.16.840.1.101.3.4.3.20"
 #define PROV_NAMES_SLH_DSA_SHA2_128F "SLH-DSA-SHA2-128f:id-slh-dsa-sha2-128f:2.16.840.1.101.3.4.3.21"
 #define PROV_NAMES_SLH_DSA_SHA2_192S "SLH-DSA-SHA2-192s:id-slh-dsa-sha2-192s:2.16.840.1.101.3.4.3.22"
diff --git a/providers/implementations/keymgmt/ec_kmgmt.c b/providers/implementations/keymgmt/ec_kmgmt.c
index 2768bc8e00..fdd5d6c698 100644
--- a/providers/implementations/keymgmt/ec_kmgmt.c
+++ b/providers/implementations/keymgmt/ec_kmgmt.c
@@ -71,6 +71,7 @@ static OSSL_FUNC_keymgmt_gettable_params_fn sm2_gettable_params;
 static OSSL_FUNC_keymgmt_settable_params_fn sm2_settable_params;
 static OSSL_FUNC_keymgmt_import_fn sm2_import;
 static OSSL_FUNC_keymgmt_query_operation_name_fn sm2_query_operation_name;
+static OSSL_FUNC_keymgmt_query_operation_name_fn curve_sm2_query_operation_name;
 static OSSL_FUNC_keymgmt_validate_fn sm2_validate;
 #endif
 #endif
@@ -91,8 +92,7 @@ static const char *ec_query_operation_name(int operation_id)
     return NULL;
 }

-#ifndef FIPS_MODULE
-#ifndef OPENSSL_NO_SM2
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2)
 static const char *sm2_query_operation_name(int operation_id)
 {
     switch (operation_id) {
@@ -101,7 +101,14 @@ static const char *sm2_query_operation_name(int operation_id)
     }
     return NULL;
 }
-#endif
+static const char *curve_sm2_query_operation_name(int operation_id)
+{
+    switch (operation_id) {
+    case OSSL_OP_KEYEXCH:
+        return "ECDH";
+    }
+    return NULL;
+}
 #endif

 /*
@@ -1482,33 +1489,36 @@ const OSSL_DISPATCH ossl_ec_keymgmt_functions[] = {

 #ifndef FIPS_MODULE
 #ifndef OPENSSL_NO_SM2
-const OSSL_DISPATCH ossl_sm2_keymgmt_functions[] = {
-    { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },
-    { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },
-    { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,
-        (void (*)(void))ec_gen_set_template },
-    { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },
-    { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,
-        (void (*)(void))ec_gen_settable_params },
-    { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },
-    { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },
-    { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },
-    { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
-    { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))sm2_get_params },
-    { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))sm2_gettable_params },
-    { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))ec_set_params },
-    { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))sm2_settable_params },
-    { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
-    { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },
-    { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },
-    { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },
-    { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
-    { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
-    { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
-    { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
-        (void (*)(void))sm2_query_operation_name },
-    { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },
-    OSSL_DISPATCH_END
-};
+#define SM2_FUNCS(variant)                                                          \
+    const OSSL_DISPATCH ossl_##variant##_keymgmt_functions[] = {                    \
+        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))sm2_newdata },                     \
+        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))sm2_gen_init },               \
+        { OSSL_FUNC_KEYMGMT_GEN_SET_TEMPLATE,                                       \
+            (void (*)(void))ec_gen_set_template },                                  \
+        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ec_gen_set_params },    \
+        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,                                    \
+            (void (*)(void))ec_gen_settable_params },                               \
+        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))sm2_gen },                         \
+        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ec_gen_cleanup },          \
+        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))sm2_load },                       \
+        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },                    \
+        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))sm2_get_params },           \
+        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))sm2_gettable_params }, \
+        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))ec_set_params },            \
+        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))sm2_settable_params }, \
+        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },                          \
+        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ec_match },                      \
+        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))sm2_validate },               \
+        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))sm2_import },                   \
+        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },        \
+        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },                    \
+        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },        \
+        { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,                                   \
+            (void (*)(void))variant##_query_operation_name },                       \
+        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ec_dup },                          \
+        OSSL_DISPATCH_END                                                           \
+    }
+SM2_FUNCS(sm2);
+SM2_FUNCS(curve_sm2);
 #endif
 #endif
diff --git a/providers/implementations/keymgmt/mlx_kmgmt.c b/providers/implementations/keymgmt/mlx_kmgmt.c
index b533468aaa..f58724dfe9 100644
--- a/providers/implementations/keymgmt/mlx_kmgmt.c
+++ b/providers/implementations/keymgmt/mlx_kmgmt.c
@@ -50,6 +50,14 @@ static const ECDH_VINFO hybrid_vtable[] = {
 #if !defined(OPENSSL_NO_ECX)
     { "X25519", NULL, 32, 32, 32, 0, EVP_PKEY_ML_KEM_768 },
     { "X448", NULL, 56, 56, 56, 0, EVP_PKEY_ML_KEM_1024 },
+#else
+    { NULL, NULL, 0, 0, 0, 0, NID_undef },
+    { NULL, NULL, 0, 0, 0, 0, NID_undef },
+#endif
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2)
+    { "curveSM2", "SM2", 65, 32, 32, 1, EVP_PKEY_ML_KEM_768 },
+#else
+    { NULL, NULL, 0, 0, 0, 0, NID_undef },
 #endif
 };

@@ -794,3 +802,6 @@ DECLARE_DISPATCH(p384, 1);
 DECLARE_DISPATCH(x25519, 2);
 DECLARE_DISPATCH(x448, 3);
 #endif
+#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_SM2)
+DECLARE_DISPATCH(curve_sm2, 4);
+#endif
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index daf195fd03..4fd1ab36b9 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -31,6 +31,7 @@
 #include "internal/packet.h"
 #include "internal/dane.h"
 #include "internal/refcount.h"
+#include "internal/tlssigalgs.h"
 #include "internal/tsan_assist.h"
 #include "internal/bio.h"
 #include "internal/ktls.h"
@@ -2211,85 +2212,6 @@ typedef enum downgrade_en {
  */
 #define TLSEXT_STATUSTYPE_nothing -1

-/* Sigalgs values */
-#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256 0x0403
-#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384 0x0503
-#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603
-#define TLSEXT_SIGALG_ecdsa_sha224 0x0303
-#define TLSEXT_SIGALG_ecdsa_sha1 0x0203
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha256 0x0804
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha384 0x0805
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha512 0x0806
-#define TLSEXT_SIGALG_rsa_pss_pss_sha256 0x0809
-#define TLSEXT_SIGALG_rsa_pss_pss_sha384 0x080a
-#define TLSEXT_SIGALG_rsa_pss_pss_sha512 0x080b
-#define TLSEXT_SIGALG_rsa_pkcs1_sha256 0x0401
-#define TLSEXT_SIGALG_rsa_pkcs1_sha384 0x0501
-#define TLSEXT_SIGALG_rsa_pkcs1_sha512 0x0601
-#define TLSEXT_SIGALG_rsa_pkcs1_sha224 0x0301
-#define TLSEXT_SIGALG_rsa_pkcs1_sha1 0x0201
-#define TLSEXT_SIGALG_dsa_sha256 0x0402
-#define TLSEXT_SIGALG_dsa_sha384 0x0502
-#define TLSEXT_SIGALG_dsa_sha512 0x0602
-#define TLSEXT_SIGALG_dsa_sha224 0x0302
-#define TLSEXT_SIGALG_dsa_sha1 0x0202
-#define TLSEXT_SIGALG_gostr34102012_256_intrinsic 0x0840
-#define TLSEXT_SIGALG_gostr34102012_512_intrinsic 0x0841
-#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee
-#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef
-#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded
-
-#define TLSEXT_SIGALG_ed25519 0x0807
-#define TLSEXT_SIGALG_ed448 0x0808
-#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256 0x081a
-#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384 0x081b
-#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512 0x081c
-#define TLSEXT_SIGALG_mldsa44 0x0904
-#define TLSEXT_SIGALG_mldsa65 0x0905
-#define TLSEXT_SIGALG_mldsa87 0x0906
-
-/* Sigalgs names */
-#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256_name "ecdsa_secp256r1_sha256"
-#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384_name "ecdsa_secp384r1_sha384"
-#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512_name "ecdsa_secp521r1_sha512"
-#define TLSEXT_SIGALG_ecdsa_sha224_name "ecdsa_sha224"
-#define TLSEXT_SIGALG_ecdsa_sha1_name "ecdsa_sha1"
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha256_name "rsa_pss_rsae_sha256"
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha384_name "rsa_pss_rsae_sha384"
-#define TLSEXT_SIGALG_rsa_pss_rsae_sha512_name "rsa_pss_rsae_sha512"
-#define TLSEXT_SIGALG_rsa_pss_pss_sha256_name "rsa_pss_pss_sha256"
-#define TLSEXT_SIGALG_rsa_pss_pss_sha384_name "rsa_pss_pss_sha384"
-#define TLSEXT_SIGALG_rsa_pss_pss_sha512_name "rsa_pss_pss_sha512"
-#define TLSEXT_SIGALG_rsa_pkcs1_sha256_name "rsa_pkcs1_sha256"
-#define TLSEXT_SIGALG_rsa_pkcs1_sha384_name "rsa_pkcs1_sha384"
-#define TLSEXT_SIGALG_rsa_pkcs1_sha512_name "rsa_pkcs1_sha512"
-#define TLSEXT_SIGALG_rsa_pkcs1_sha224_name "rsa_pkcs1_sha224"
-#define TLSEXT_SIGALG_rsa_pkcs1_sha1_name "rsa_pkcs1_sha1"
-#define TLSEXT_SIGALG_dsa_sha256_name "dsa_sha256"
-#define TLSEXT_SIGALG_dsa_sha384_name "dsa_sha384"
-#define TLSEXT_SIGALG_dsa_sha512_name "dsa_sha512"
-#define TLSEXT_SIGALG_dsa_sha224_name "dsa_sha224"
-#define TLSEXT_SIGALG_dsa_sha1_name "dsa_sha1"
-#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_name "gostr34102012_256"
-#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_name "gostr34102012_512"
-#define TLSEXT_SIGALG_gostr34102012_256_intrinsic_alias "gost2012_256"
-#define TLSEXT_SIGALG_gostr34102012_512_intrinsic_alias "gost2012_512"
-#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256_name "gost2012_256"
-#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512_name "gost2012_512"
-#define TLSEXT_SIGALG_gostr34102001_gostr3411_name "gost2001_gost94"
-
-#define TLSEXT_SIGALG_ed25519_name "ed25519"
-#define TLSEXT_SIGALG_ed448_name "ed448"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_name "ecdsa_brainpoolP256r1tls13_sha256"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name "ecdsa_brainpoolP384r1tls13_sha384"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name "ecdsa_brainpoolP512r1tls13_sha512"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP256r1_sha256_alias "ecdsa_brainpoolP256r1_sha256"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_alias "ecdsa_brainpoolP384r1_sha384"
-#define TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_alias "ecdsa_brainpoolP512r1_sha512"
-#define TLSEXT_SIGALG_mldsa44_name "mldsa44"
-#define TLSEXT_SIGALG_mldsa65_name "mldsa65"
-#define TLSEXT_SIGALG_mldsa87_name "mldsa87"
-
 /* Known PSK key exchange modes */
 #define TLSEXT_KEX_MODE_KE 0x00
 #define TLSEXT_KEX_MODE_KE_DHE 0x01
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index cdf75bb22d..c0b2f2073a 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -205,8 +205,18 @@ static const unsigned char ecformats_all[] = {

 /* Group list string of the built-in pseudo group DEFAULT */
 #define DEFAULT_GROUP_NAME "DEFAULT"
-#define TLS_DEFAULT_GROUP_LIST \
-    "?*X25519MLKEM768 / ?*X25519:?secp256r1 / ?X448:?secp384r1:?secp521r1 / ?ffdhe2048:?ffdhe3072"
+#ifndef OPENSSL_NO_ECX
+#define TLS_DEFAULT_GROUP_LIST                                 \
+    "?*X25519MLKEM768:?SecP256r1MLKEM768:?curveSM2MLKEM768 / " \
+    "?*X25519:?secp256r1 / "                                   \
+    "?X448:?secp384r1:?secp521r1 / "                           \
+    "?ffdhe2048:?ffdhe3072"
+#else
+#define TLS_DEFAULT_GROUP_LIST                 \
+    "?*SecP256r1MLKEM768:?curveSM2MLKEM768 / " \
+    "?*secp256r1 / ?secp384r1:?secp521r1 / "   \
+    "?ffdhe2048:?ffdhe3072"
+#endif

 static const uint16_t suiteb_curves[] = {
     OSSL_TLS_GROUP_ID_secp256r1,
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index 31e2844c20..0f10dda34f 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -548,6 +548,7 @@ static const ssl_trace_tbl ssl_groups_tbl[] = {
     { 38, "GC512A" },
     { 39, "GC512B" },
     { 40, "GC512C" },
+    { 41, "curveSM2" },
     { 256, "ffdhe2048" },
     { 257, "ffdhe3072" },
     { 258, "ffdhe4096" },
@@ -559,6 +560,7 @@ static const ssl_trace_tbl ssl_groups_tbl[] = {
     { 4587, "SecP256r1MLKEM768" },
     { 4588, "X25519MLKEM768" },
     { 4589, "SecP384r1MLKEM1024" },
+    { 4590, "curveSM2MLKEM768" },
     { 25497, "X25519Kyber768Draft00" },
     { 25498, "SecP256r1Kyber768Draft00" },
     { 0xFF01, "arbitrary_explicit_prime_curves" },
@@ -612,13 +614,14 @@ static const ssl_trace_tbl ssl_sigalg_tbl[] = {
     { TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384, TLSEXT_SIGALG_ecdsa_brainpoolP384r1_sha384_name },
     { TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512, TLSEXT_SIGALG_ecdsa_brainpoolP512r1_sha512_name },
     /*
-     * Well known groups that we happen to know about, but only come from
+     * Well known sigalgs that we happen to know about, but only come from
      * provider capability declarations (hence no macros for the
      * codepoints/names)
      */
     { 0x0904, "mldsa44" },
     { 0x0905, "mldsa65" },
-    { 0x0906, "mldsa87" }
+    { 0x0906, "mldsa87" },
+    { 0x0708, "sm2sig_sm3" },
 };

 static const ssl_trace_tbl ssl_ctype_tbl[] = {
diff --git a/test/quicapitest.c b/test/quicapitest.c
index 5afd571b8b..e0d3ce0796 100644
--- a/test/quicapitest.c
+++ b/test/quicapitest.c
@@ -40,10 +40,11 @@ static SSL_CTX *create_server_ctx(void);
 static int qc_init(SSL *qconn, BIO_ADDR *dst_addr);

 /* The ssltrace test assumes some options are switched on/off */
-#if !defined(OPENSSL_NO_SSL_TRACE)                            \
-    && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD) \
-    && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH)    \
-    && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM)
+#if !defined(OPENSSL_NO_SSL_TRACE)                                \
+    && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD)     \
+    && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH)        \
+    && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM) \
+    && !defined(OPENSSL_NO_SM2)
 #define DO_SSL_TRACE_TEST
 #endif

diff --git a/test/recipes/70-test_key_share.t b/test/recipes/70-test_key_share.t
index 5964d778ff..1f6e433c7f 100644
--- a/test/recipes/70-test_key_share.t
+++ b/test/recipes/70-test_key_share.t
@@ -148,6 +148,15 @@ SKIP: {
     #Test 7: An acceptable key_share after a list of non-acceptable ones should
     #succeed
     $proxy->clear();
+    # The test assumes that one of the client initial keyshares includes
+    # either X25519 if ECX is enabled or P-256 otherwise.  While the default
+    # groups have been adjusted to make it true for now, the test was brittle,
+    # best to set the client groups explicitly.
+    if (disabled("ecx")) {
+        $proxy->clientflags("-groups P-256");
+    } else {
+        $proxy->clientflags("-groups X25519:P-256");
+    }
     $testtype = ACCEPTABLE_AT_END;
     $proxy->start();
     ok(TLSProxy::Message->success(), "Acceptable key_share at end of list");
diff --git a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt
index 1e3e1d6f8b..faea976b90 100644
--- a/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt
+++ b/test/recipes/75-test_quicapi_data/ssltraceref-zlib.txt
@@ -19,8 +19,10 @@ Header:
           000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06   ...............
           001e - 04 80 08 00 00 07 04 80-08 00 00 08 02 40 64   .............@d
           002d - 09 02 40 64                                    ..@d
-        extension_type=supported_groups(10), length=18
+        extension_type=supported_groups(10), length=22
           X25519MLKEM768 (4588)
+          SecP256r1MLKEM768 (4587)
+          curveSM2MLKEM768 (4590)
           ecdh_x25519 (29)
           secp256r1 (P-256) (23)
           ecdh_x448 (30)
@@ -52,6 +54,7 @@ Header:
           rsa_pkcs1_sha256 (0x0401)
           rsa_pkcs1_sha384 (0x0501)
           rsa_pkcs1_sha512 (0x0601)
+          sm2sig_sm3 (0x0708)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
diff --git a/test/recipes/75-test_quicapi_data/ssltraceref.txt b/test/recipes/75-test_quicapi_data/ssltraceref.txt
index 5b554df9f9..56c395b15a 100644
--- a/test/recipes/75-test_quicapi_data/ssltraceref.txt
+++ b/test/recipes/75-test_quicapi_data/ssltraceref.txt
@@ -19,8 +19,10 @@ Header:
           000f - 01 02 04 04 80 0c 00 00-05 04 80 08 00 00 06   ...............
           001e - 04 80 08 00 00 07 04 80-08 00 00 08 02 40 64   .............@d
           002d - 09 02 40 64                                    ..@d
-        extension_type=supported_groups(10), length=18
+        extension_type=supported_groups(10), length=22
           X25519MLKEM768 (4588)
+          SecP256r1MLKEM768 (4587)
+          curveSM2MLKEM768 (4590)
           ecdh_x25519 (29)
           secp256r1 (P-256) (23)
           ecdh_x448 (30)
@@ -52,6 +54,7 @@ Header:
           rsa_pkcs1_sha256 (0x0401)
           rsa_pkcs1_sha384 (0x0501)
           rsa_pkcs1_sha512 (0x0601)
+          sm2sig_sm3 (0x0708)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
diff --git a/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt b/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt
index a9a503345f..68d46c8b38 100644
--- a/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt
+++ b/test/recipes/90-test_sslapi_data/ssltraceref-zlib.txt
@@ -48,6 +48,7 @@ Header:
           rsa_pkcs1_sha256 (0x0401)
           rsa_pkcs1_sha384 (0x0501)
           rsa_pkcs1_sha512 (0x0601)
+          sm2sig_sm3 (0x0708)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
diff --git a/test/recipes/90-test_sslapi_data/ssltraceref.txt b/test/recipes/90-test_sslapi_data/ssltraceref.txt
index 273fd35c11..d84d0e02fb 100644
--- a/test/recipes/90-test_sslapi_data/ssltraceref.txt
+++ b/test/recipes/90-test_sslapi_data/ssltraceref.txt
@@ -48,6 +48,7 @@ Header:
           rsa_pkcs1_sha256 (0x0401)
           rsa_pkcs1_sha384 (0x0501)
           rsa_pkcs1_sha512 (0x0601)
+          sm2sig_sm3 (0x0708)
         extension_type=supported_versions(43), length=3
           TLS 1.3 (772)
         extension_type=psk_key_exchange_modes(45), length=2
diff --git a/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in b/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in
index a14e10e8f2..2ed47253b8 100644
--- a/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in
+++ b/test/recipes/95-test_external_tlsfuzzer_data/cert.json.in
@@ -12,12 +12,12 @@
        {"name" : "test-tls13-certificate-verify.py",
         "arguments" : ["-k", "tests/clientX509Key.pem",
                        "-c", "tests/clientX509Cert.pem",
-                       "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512",
+                       "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 7+8",
                        "-p", "@PORT@"]},
        {"name" : "test-tls13-ecdsa-in-certificate-verify.py",
           "arguments" : ["-k", "tests/serverECKey.pem",
                          "-c", "tests/serverECCert.pem",
-                         "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512",
+                         "-s", "9+5 9+6 9+4 ecdsa_secp256r1_sha256 ecdsa_secp384r1_sha384 ecdsa_secp521r1_sha512 ed25519 ed448 8+26 8+27 8+28 rsa_pss_pss_sha256 rsa_pss_pss_sha384 rsa_pss_pss_sha512 rsa_pss_rsae_sha256 rsa_pss_rsae_sha384 rsa_pss_rsae_sha512 rsa_pkcs1_sha256 rsa_pkcs1_sha384 rsa_pkcs1_sha512 7+8",
                          "-p", "@PORT@"]}
      ]
     },
diff --git a/test/sslapitest.c b/test/sslapitest.c
index eb57864979..c75832b6b3 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -133,7 +133,7 @@ static X509 *ocspcert = NULL;
     && defined(OPENSSL_NO_BROTLI) && defined(OPENSSL_NO_ZSTD)     \
     && !defined(OPENSSL_NO_ECX) && !defined(OPENSSL_NO_DH)        \
     && !defined(OPENSSL_NO_ML_DSA) && !defined(OPENSSL_NO_ML_KEM) \
-    && !defined(OPENSSL_NO_TLS1_3)
+    && !defined(OPENSSL_NO_TLS1_3) && !defined(OPENSSL_NO_SM2)
 #define DO_SSL_TRACE_TEST
 #endif

diff --git a/test/tls13groupselection_test.c b/test/tls13groupselection_test.c
index 5796b307af..09b5d50eb9 100644
--- a/test/tls13groupselection_test.c
+++ b/test/tls13groupselection_test.c
@@ -180,11 +180,17 @@ static const struct tls13groupselection_test_st tls13groupselection_tests[] = {
      * (I) Check handling of the "DEFAULT" 'pseudo group name'
      */
     { "*X25519:DEFAULT:-prime256v1:-X448", /* test 18 */
-        "DEFAULT:-X25519:-?X25519MLKEM768",
+        "DEFAULT:-X25519"
+        ":-?X25519MLKEM768"
+        ":-?SecP256r1MLKEM768"
+        ":-?curveSM2MLKEM768",
         CLIENT_PREFERENCE,
         "secp384r1", HRR },
     { "*X25519:DEFAULT:-prime256v1:-X448", /* test 19 */
-        "DEFAULT:-X25519:-?X25519MLKEM768",
+        "DEFAULT:-X25519"
+        ":-?X25519MLKEM768"
+        ":-?SecP256r1MLKEM768"
+        ":-?curveSM2MLKEM768",
         SERVER_PREFERENCE,
         "secp384r1", HRR },
     /*