代码拉取完成,页面将自动刷新
同步操作将从 OpenCloudOS Stream/openssl 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From f2f68b548d18078134071c456be8b75733af6811 Mon Sep 17 00:00:00 2001
From: wynnfeng <wynnfeng>
Date: Sun, 28 Apr 2024 23:01:58 +0800
Subject: [PATCH] support rfc8998
---
apps/s_client.c | 18 +
apps/s_server.c | 18 +
crypto/asn1/a_verify.c | 28 ++
crypto/err/openssl.txt | 2 +
crypto/evp/p_legacy.c | 5 +
crypto/evp/p_lib.c | 20 +
doc/man1/openssl-s_client.pod.in | 7 +
doc/man1/openssl-s_server.pod.in | 7 +
include/openssl/evp.h | 6 +
include/openssl/ssl.h.in | 7 +
include/openssl/sslerr.h | 2 +
include/openssl/tls1.h | 4 +
include/openssl/x509.h.in | 8 +
ssl/record/ssl3_record_tls13.c | 8 +-
ssl/s3_lib.c | 67 ++-
ssl/ssl_cert_table.h | 4 +
ssl/ssl_ciph.c | 22 +-
ssl/ssl_conf.c | 22 +
ssl/ssl_err.c | 4 +
ssl/ssl_lib.c | 28 ++
ssl/ssl_local.h | 20 +
ssl/statem/statem_clnt.c | 128 +++++
ssl/statem/statem_lib.c | 62 +++
ssl/statem/statem_local.h | 11 +
ssl/statem/statem_srvr.c | 67 +++
ssl/statem_tlcp/tlcp_statem_clnt.c | 39 ++
ssl/statem_tlcp/tlcp_statem_lib.c | 35 ++
ssl/t1_lib.c | 26 +-
test/certs/sm2-chain-ca.crt | 30 ++
test/certs/sm2-first-crt.pem | 14 +
test/certs/sm2-first-key.pem | 5 +
test/certs/sm2-leaf.crt | 65 +++
test/certs/sm2-leaf.key | 8 +
test/cipherlist_test.c | 10 +
test/ciphername_test.c | 2 +
test/helpers/handshake.c | 11 +
test/helpers/handshake.h | 3 +
test/helpers/ssl_test_ctx.c | 19 +
test/helpers/ssl_test_ctx.h | 8 +
test/recipes/80-test_ssl_new.t | 4 +-
test/ssl-tests/30-tls13-sm.cnf | 712 ++++++++++++++++++++++++++++
test/ssl-tests/30-tls13-sm.cnf.in | 499 +++++++++++++++++++
test/ssl_cert_table_internal_test.c | 4 +
test/ssl_test.c | 13 +
test/sslapitest.c | 7 +-
test/verify_extra_test.c | 76 +++
util/libcrypto.num | 2 +-
util/libssl.num | 4 +
util/missingcrypto.txt | 1 +
util/missingssl.txt | 4 +
util/other.syms | 1 +
51 files changed, 2166 insertions(+), 11 deletions(-)
create mode 100644 test/certs/sm2-chain-ca.crt
create mode 100644 test/certs/sm2-first-crt.pem
create mode 100644 test/certs/sm2-first-key.pem
create mode 100644 test/certs/sm2-leaf.crt
create mode 100644 test/certs/sm2-leaf.key
create mode 100644 test/ssl-tests/30-tls13-sm.cnf
create mode 100644 test/ssl-tests/30-tls13-sm.cnf.in
diff --git a/apps/s_client.c b/apps/s_client.c
index d78edb6..921f0dc 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -451,6 +451,9 @@ typedef enum OPTION_choice {
OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
#ifndef OPENSSL_NO_TLCP
OPT_TLCP, OPT_ENABLE_TLCP,
+#endif
+#ifndef OPENSSL_NO_SM2
+ OPT_ENABLE_SM_TLS13_STRICT,
#endif
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS,
OPT_CERT_CHAIN, OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN,
@@ -651,6 +654,9 @@ const OPTIONS s_client_options[] = {
{"tlcp", OPT_TLCP, '-', "Just use TLCP"},
{"enable_tlcp", OPT_ENABLE_TLCP, '-', "enable tlcp"},
#endif
+#ifndef OPENSSL_NO_SM2
+ {"enable_sm_tls13_strict", OPT_ENABLE_SM_TLS13_STRICT, '-', "enable sm tls13 strict"},
+#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any version of DTLS"},
{"timeout", OPT_TIMEOUT, '-',
@@ -843,6 +849,9 @@ int s_client_main(int argc, char **argv)
char *enc_cert_file = NULL, *enc_key_file = NULL;
char *sign_cert_file = NULL, *sign_key_file = NULL;
int enable_tlcp = 0;
+#endif
+#ifndef OPENSSL_NO_SM2
+ int enable_sm_tls13_strict = 0;
#endif
char *chCApath = NULL, *chCAfile = NULL, *chCAstore = NULL, *host = NULL;
char *thost = NULL, *tport = NULL;
@@ -1299,6 +1308,11 @@ int s_client_main(int argc, char **argv)
case OPT_ENABLE_TLCP:
enable_tlcp = 1;
break;
+#endif
+#ifndef OPENSSL_NO_SM2
+ case OPT_ENABLE_SM_TLS13_STRICT:
+ enable_sm_tls13_strict = 1;
+ break;
#endif
case OPT_DTLS:
#ifndef OPENSSL_NO_DTLS
@@ -1804,6 +1818,10 @@ int s_client_main(int argc, char **argv)
}
#endif
+#ifndef OPENSSL_NO_SM2
+ if (enable_sm_tls13_strict)
+ SSL_CTX_enable_sm_tls13_strict(ctx);
+#endif
SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
if (sdebug)
diff --git a/apps/s_server.c b/apps/s_server.c
index 866a981..dd6e6dd 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -715,6 +715,9 @@ typedef enum OPTION_choice {
OPT_TLCP, OPT_ENC_CERT, OPT_ENC_KEY, OPT_SIGN_CERT, OPT_SIGN_KEY,
OPT_ENABLE_TLCP, OPT_ENC_CERTFORM, OPT_SIGN_CERTFORM,
OPT_ENC_KEYFORM, OPT_SIGN_KEYFORM,
+#endif
+#ifndef OPENSSL_NO_SM2
+ OPT_ENABLE_SM_TLS13_STRICT,
#endif
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_LISTEN, OPT_STATELESS,
OPT_ID_PREFIX, OPT_SERVERNAME, OPT_SERVERNAME_FATAL,
@@ -957,6 +960,9 @@ const OPTIONS s_server_options[] = {
{"tlcp", OPT_TLCP, '-', "Just talk TLCP"},
{"enable_tlcp", OPT_ENABLE_TLCP, '-', "enable tlcp"},
#endif
+#ifndef OPENSSL_NO_SM2
+ {"enable_sm_tls13_strict", OPT_ENABLE_SM_TLS13_STRICT, '-', "enable sm tls13 strict"},
+#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any DTLS version"},
{"listen", OPT_LISTEN, '-',
@@ -1083,6 +1089,9 @@ int s_server_main(int argc, char *argv[])
int s_sign_key_format = FORMAT_PEM;
int enable_tlcp = 0;
#endif
+#ifndef OPENSSL_NO_SM2
+ int enable_sm_tls13_strict = 0;
+#endif
#ifndef OPENSSL_NO_OCSP
int s_tlsextstatus = 0;
#endif
@@ -1598,6 +1607,11 @@ int s_server_main(int argc, char *argv[])
case OPT_ENABLE_TLCP:
enable_tlcp = 1;
break;
+#endif
+#ifndef OPENSSL_NO_SM2
+ case OPT_ENABLE_SM_TLS13_STRICT:
+ enable_sm_tls13_strict = 1;
+ break;
#endif
case OPT_SCTP:
#ifndef OPENSSL_NO_SCTP
@@ -1970,6 +1984,10 @@ skip:
if (enable_tlcp)
SSL_CTX_enable_tlcp(ctx);
#endif
+#ifndef OPENSSL_NO_SM2
+ if (enable_sm_tls13_strict)
+ SSL_CTX_enable_sm_tls13_strict(ctx);
+#endif
SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
index a618eda..d371f42 100644
--- a/crypto/asn1/a_verify.c
+++ b/crypto/asn1/a_verify.c
@@ -193,6 +193,34 @@ int ASN1_item_verify_ctx(const ASN1_ITEM *it, const X509_ALGOR *alg,
}
}
+#ifndef OPENSSL_NO_SM2
+ if (pknid == NID_sm2) {
+ EVP_PKEY_CTX *pctx = NULL, *opctx = EVP_MD_CTX_get_pkey_ctx(ctx);
+
+ if (pknid == NID_sm2 && !EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ pctx = EVP_PKEY_CTX_new_from_pkey(opctx->libctx, pkey,
+ opctx->propquery);
+ if (pctx == NULL) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set1_id(pctx,
+ opctx->cached_parameters.dist_id,
+ opctx->cached_parameters.dist_id_len) != 1) {
+ ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ EVP_PKEY_CTX_free(opctx);
+ EVP_MD_CTX_set_pkey_ctx(ctx, pctx);
+ }
+#endif
+
/*
* Note that some algorithms (notably Ed25519 and Ed448) may allow
* a NULL digest value.
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index b9a42b7..e05766b 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -1248,6 +1248,8 @@ SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT:272:\
attempt to reuse session in different context
SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE:158:\
at least (D)TLS 1.2 needed in Suite B mode
+SSL_R_BAD_CERTIFICATE_SIGNATURE_TYPE:321:bad certificate signature type
+SSL_R_BAD_CERTIFICATE_USAGE:322:bad certificate usage
SSL_R_BAD_CHANGE_CIPHER_SPEC:103:bad change cipher spec
SSL_R_BAD_CIPHER:186:bad cipher
SSL_R_BAD_DATA:390:bad data
diff --git a/crypto/evp/p_legacy.c b/crypto/evp/p_legacy.c
index 6c65e7e..3da32cc 100644
--- a/crypto/evp/p_legacy.c
+++ b/crypto/evp/p_legacy.c
@@ -68,7 +68,12 @@ int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
EC_KEY *evp_pkey_get0_EC_KEY_int(const EVP_PKEY *pkey)
{
+# ifndef OPENSSL_NO_SM2
+ if (EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC &&
+ EVP_PKEY_get_base_id(pkey) != EVP_PKEY_SM2) {
+# else
if (EVP_PKEY_get_base_id(pkey) != EVP_PKEY_EC) {
+# endif
ERR_raise(ERR_LIB_EVP, EVP_R_EXPECTING_A_EC_KEY);
return NULL;
}
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 04b148a..2a2b7a2 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -687,6 +687,26 @@ int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len, NULL);
}
+int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
+{
+ if (pkey->type == type) {
+ return 1; /* it already is that type */
+ }
+
+ /*
+ * The application is requesting to alias this to a different pkey type,
+ * but not one that resolves to the base type.
+ */
+ if (EVP_PKEY_get_id(pkey) > EVP_PKEY_NONE &&
+ EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) {
+ EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
+ return 0;
+ }
+
+ pkey->type = type;
+ return 1;
+}
+
# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
{
diff --git a/doc/man1/openssl-s_client.pod.in b/doc/man1/openssl-s_client.pod.in
index c7c1442..00ce046 100644
--- a/doc/man1/openssl-s_client.pod.in
+++ b/doc/man1/openssl-s_client.pod.in
@@ -67,6 +67,7 @@ B<openssl> B<s_client>
[B<-nbio_test>]
[B<-tlcp>]
[B<-enable_tlcp>]
+[B<-enable_sm_tls13_strict>]
[B<-state>]
[B<-nbio>]
[B<-crlf>]
@@ -454,6 +455,12 @@ Just talk TLCP protocol.
Enable TLCP protocol.
+=item B<-enable_sm_tls13_strict>
+
+Strictly check whether the SM2 certificate in TLS1.3 matches the cipher suite.
+Bucause the RFC 8998 demand that server can use "TLS_SM4_GCM_SM3" and
+"TLS_SM4_CCM_SM3" with sm2 cert only.
+
=item B<-state>
Prints out the SSL session states.
diff --git a/doc/man1/openssl-s_server.pod.in b/doc/man1/openssl-s_server.pod.in
index e7a1c52..b8f605c 100644
--- a/doc/man1/openssl-s_server.pod.in
+++ b/doc/man1/openssl-s_server.pod.in
@@ -49,6 +49,7 @@ B<openssl> B<s_server>
[B<-msgfile> I<outfile>]
[B<-tlcp>]
[B<-enable_tlcp>]
+[B<-enable_sm_tls13_strict>]
[B<-state>]
[B<-nocert>]
[B<-quiet>]
@@ -373,6 +374,12 @@ Only use TLCP protocol.
Enable TLCP protocol, including TLCP and GM/T 0024-2014.
+=item B<-enable_sm_tls13_strict>
+
+Strictly check whether the SM2 certificate in TLS1.3 matches the cipher suite.
+Bucause the RFC 8998 demand that server can use "TLS_SM4_GCM_SM3" and
+"TLS_SM4_CCM_SM3" with sm2 cert only.
+
=item B<-state>
Prints the SSL session states.
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index dc65280..7c9fc68 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1326,6 +1326,7 @@ int EVP_PKEY_can_sign(const EVP_PKEY *pkey);
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
int EVP_PKEY_set_type_by_keymgmt(EVP_PKEY *pkey, EVP_KEYMGMT *keymgmt);
+int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
# ifndef OPENSSL_NO_DEPRECATED_3_0
# ifndef OPENSSL_NO_ENGINE
OSSL_DEPRECATEDIN_3_0
@@ -2173,6 +2174,11 @@ OSSL_LIB_CTX *EVP_PKEY_CTX_get0_libctx(EVP_PKEY_CTX *ctx);
const char *EVP_PKEY_CTX_get0_propq(const EVP_PKEY_CTX *ctx);
const OSSL_PROVIDER *EVP_PKEY_CTX_get0_provider(const EVP_PKEY_CTX *ctx);
+/* for compatibility usage */
+# ifndef OPENSSL_NO_SM2
+# define EVP_PKEY_is_sm2(pkey) EVP_PKEY_is_a(pkey, "SM2")
+# endif
+
# ifdef __cplusplus
}
# endif
diff --git a/include/openssl/ssl.h.in b/include/openssl/ssl.h.in
index 8799329..9be9942 100644
--- a/include/openssl/ssl.h.in
+++ b/include/openssl/ssl.h.in
@@ -1806,6 +1806,13 @@ void SSL_CTX_disable_tlcp(SSL_CTX *ctx);
void SSL_enable_tlcp(SSL *s);
void SSL_disable_tlcp(SSL *s);
# endif
+
+# ifndef OPENSSL_NO_SM2
+void SSL_CTX_enable_sm_tls13_strict(SSL_CTX *ctx);
+void SSL_CTX_disable_sm_tls13_strict(SSL_CTX *ctx);
+void SSL_enable_sm_tls13_strict(SSL *s);
+void SSL_disable_sm_tls13_strict(SSL *s);
+# endif
__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
const unsigned char *d, long len);
__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index fd94936..2d66317 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -25,6 +25,8 @@
# define SSL_R_APP_DATA_IN_HANDSHAKE 100
# define SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT 272
# define SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE 158
+# define SSL_R_BAD_CERTIFICATE_SIGNATURE_TYPE 321
+# define SSL_R_BAD_CERTIFICATE_USAGE 322
# define SSL_R_BAD_CHANGE_CIPHER_SPEC 103
# define SSL_R_BAD_CIPHER 186
# define SSL_R_BAD_DATA 390
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index e807bf7..f537f32 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -595,6 +595,8 @@ int SSL_CTX_set_tlsext_ticket_key_evp_cb
# define TLS1_3_CK_CHACHA20_POLY1305_SHA256 0x03001303
# define TLS1_3_CK_AES_128_CCM_SHA256 0x03001304
# define TLS1_3_CK_AES_128_CCM_8_SHA256 0x03001305
+# define TLS1_3_CK_SM4_GCM_SM3 0x030000C6
+# define TLS1_3_CK_SM4_CCM_SM3 0x030000C7
/* Aria ciphersuites from RFC6209 */
# define TLS1_CK_RSA_WITH_ARIA_128_GCM_SHA256 0x0300C050
@@ -675,6 +677,8 @@ int SSL_CTX_set_tlsext_ticket_key_evp_cb
# define TLS1_3_RFC_CHACHA20_POLY1305_SHA256 "TLS_CHACHA20_POLY1305_SHA256"
# define TLS1_3_RFC_AES_128_CCM_SHA256 "TLS_AES_128_CCM_SHA256"
# define TLS1_3_RFC_AES_128_CCM_8_SHA256 "TLS_AES_128_CCM_8_SHA256"
+# define TLS1_3_RFC_SM4_CCM_SM3 "TLS_SM4_CCM_SM3"
+# define TLS1_3_RFC_SM4_GCM_SM3 "TLS_SM4_GCM_SM3"
# define TLS1_RFC_ECDHE_ECDSA_WITH_NULL_SHA "TLS_ECDHE_ECDSA_WITH_NULL_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"
# define TLS1_RFC_ECDHE_ECDSA_WITH_AES_128_CBC_SHA "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA"
diff --git a/include/openssl/x509.h.in b/include/openssl/x509.h.in
index 3ef741f..199c647 100644
--- a/include/openssl/x509.h.in
+++ b/include/openssl/x509.h.in
@@ -578,6 +578,14 @@ ASN1_OCTET_STRING *X509_get0_distinguishing_id(X509 *x);
void X509_REQ_set0_distinguishing_id(X509_REQ *x, ASN1_OCTET_STRING *d_id);
ASN1_OCTET_STRING *X509_REQ_get0_distinguishing_id(X509_REQ *x);
+/* for compattibility usage */
+# ifndef OPENSSL_NO_SM2
+# define X509_set0_sm2_id X509_set0_distinguishing_id
+# define X509_get0_sm2_id X509_get0_distinguishing_id
+# define X509_REQ_set0_sm2_id X509_REQ_set0_distinguishing_id
+# define X509_REQ_get0_sm2_id X509_REQ_get0_distinguishing_id
+# endif
+
int X509_alias_set1(X509 *x, const unsigned char *name, int len);
int X509_keyid_set1(X509 *x, const unsigned char *id, int len);
unsigned char *X509_alias_get0(X509 *x, int *len);
diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c
index c605fa7..358098f 100644
--- a/ssl/record/ssl3_record_tls13.c
+++ b/ssl/record/ssl3_record_tls13.c
@@ -106,6 +106,12 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
taglen = EVP_GCM_TLS_TAG_LEN;
} else if (alg_enc & SSL_CHACHA20) {
taglen = EVP_CHACHAPOLY_TLS_TAG_LEN;
+#ifndef OPENSSL_NO_SM4
+ } else if (alg_enc & SSL_SM4GCM) {
+ taglen = EVP_GCM_TLS_TAG_LEN;
+ } else if (alg_enc & SSL_SM4CCM) {
+ taglen = EVP_CCM_TLS_TAG_LEN;
+#endif
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
return 0;
@@ -168,7 +174,7 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending,
* For CCM we must explicitly set the total plaintext length before we add
* any AAD.
*/
- if (((alg_enc & SSL_AESCCM) != 0
+ if (((alg_enc & SSL_AESCCM || alg_enc & SSL_SM4CCM) != 0
&& EVP_CipherUpdate(ctx, NULL, &lenu, NULL,
(unsigned int)rec->length) <= 0)
|| EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index c8f8184..0fdada2 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -112,7 +112,42 @@ static SSL_CIPHER tls13_ciphers[] = {
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
+ },
+#if (!defined OPENSSL_NO_SM2) && (!defined OPENSSL_NO_SM3) \
+ && (!defined OPENSSL_NO_SM4)
+ /* Cipher 0x00C6 and 0x00C7, Reference to RFC 8998 */
+ {
+ 1,
+ TLS1_3_RFC_SM4_GCM_SM3,
+ TLS1_3_RFC_SM4_GCM_SM3,
+ TLS1_3_CK_SM4_GCM_SM3,
+ SSL_kANY,
+ SSL_aANY,
+ SSL_SM4GCM,
+ SSL_AEAD,
+ TLS1_3_VERSION,TLS1_3_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3,
+ 128,
+ 128,
+ }, {
+ 1,
+ TLS1_3_RFC_SM4_CCM_SM3,
+ TLS1_3_RFC_SM4_CCM_SM3,
+ TLS1_3_CK_SM4_CCM_SM3,
+ SSL_kANY,
+ SSL_aANY,
+ SSL_SM4CCM,
+ SSL_AEAD,
+ TLS1_3_VERSION,TLS1_3_VERSION,
+ 0, 0,
+ SSL_HIGH,
+ SSL_HANDSHAKE_MAC_SM3 | TLS1_PRF_SM3,
+ 128,
+ 128,
}
+#endif
};
/*
@@ -4383,6 +4418,20 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
DTLS_VERSION_GT(s->version, c->max_dtls)))
continue;
+#ifndef OPENSSL_NO_SM2
+ /*
+ * RFC 8998 demand that server can use
+ * "TLS_SM4_GCM_SM3" and "TLS_SM4_CCM_SM3" with sm2 cert only
+ */
+ if (s->enable_sm_tls13_strict) {
+ if (c->id == TLS1_3_CK_SM4_GCM_SM3
+ || c->id == TLS1_3_CK_SM4_CCM_SM3) {
+ if (!ssl_has_cert(s, SSL_PKEY_SM2))
+ continue;
+ }
+ }
+#endif
+
/*
* Since TLS 1.3 ciphersuites can be used with any auth or
* key exchange scheme skip tests.
@@ -4844,8 +4893,12 @@ EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id)
goto err;
}
- pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
- s->ctx->propq);
+ if (!SSL_is_server(s) && id == TLSEXT_curve_SM2)
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, "EC",
+ s->ctx->propq);
+ else
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
+ s->ctx->propq);
if (pctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
@@ -4882,8 +4935,12 @@ EVP_PKEY *ssl_generate_param_group(SSL *s, uint16_t id)
if (ginf == NULL)
goto err;
- pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
- s->ctx->propq);
+ if (SSL_IS_TLS13(s) && id == TLSEXT_curve_SM2)
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, "EC",
+ s->ctx->propq);
+ else
+ pctx = EVP_PKEY_CTX_new_from_name(s->ctx->libctx, ginf->algorithm,
+ s->ctx->propq);
if (pctx == NULL)
goto err;
@@ -4935,7 +4992,7 @@ int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey, int gensecret)
int rv = 0;
unsigned char *pms = NULL;
size_t pmslen = 0;
- EVP_PKEY_CTX *pctx;
+ EVP_PKEY_CTX *pctx = NULL;
if (privkey == NULL || pubkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
diff --git a/ssl/ssl_cert_table.h b/ssl/ssl_cert_table.h
index b21df8b..4ae128a 100644
--- a/ssl/ssl_cert_table.h
+++ b/ssl/ssl_cert_table.h
@@ -14,7 +14,11 @@ static const SSL_CERT_LOOKUP ssl_cert_info [] = {
{EVP_PKEY_RSA, SSL_aRSA}, /* SSL_PKEY_RSA */
{EVP_PKEY_RSA_PSS, SSL_aRSA}, /* SSL_PKEY_RSA_PSS_SIGN */
{EVP_PKEY_DSA, SSL_aDSS}, /* SSL_PKEY_DSA_SIGN */
+#ifndef OPENSSL_NO_SM2
+ {EVP_PKEY_EC, SSL_aECDSA | SSL_aSM2}, /* SSL_PKEY_ECC */
+#else
{EVP_PKEY_EC, SSL_aECDSA}, /* SSL_PKEY_ECC */
+#endif
{NID_id_GostR3410_2001, SSL_aGOST01}, /* SSL_PKEY_GOST01 */
{NID_id_GostR3410_2012_256, SSL_aGOST12}, /* SSL_PKEY_GOST12_256 */
{NID_id_GostR3410_2012_512, SSL_aGOST12}, /* SSL_PKEY_GOST12_512 */
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index ead1fef..06c171a 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -1594,6 +1594,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(SSL_CTX *ctx,
* server has both certificates, and is using the DEFAULT, or a client
* preference).
*/
+
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
-1, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
@@ -2337,9 +2338,22 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
int ssl_cert_is_disabled(SSL_CTX *ctx, size_t idx)
{
const SSL_CERT_LOOKUP *cl = ssl_cert_lookup_by_idx(idx);
+ uint32_t amask;
+
+ if (cl == NULL)
+ return 1;
+
+ amask = cl->amask;
if (cl == NULL || (cl->amask & ctx->disabled_auth_mask) != 0)
+#ifndef OPENSSL_NO_SM2
+ if (cl->nid == EVP_PKEY_EC && (ctx->disabled_auth_mask & SSL_aSM2) != 0)
+ amask &= ~SSL_aSM2;
+#endif
+
+ if ((amask & ctx->disabled_auth_mask) != 0)
return 1;
+
return 0;
}
@@ -2362,7 +2376,13 @@ const char *OSSL_default_ciphersuites(void)
{
return "TLS_AES_256_GCM_SHA384:"
"TLS_CHACHA20_POLY1305_SHA256:"
- "TLS_AES_128_GCM_SHA256";
+ "TLS_AES_128_GCM_SHA256"
+#if (!defined OPENSSL_NO_SM2) && (!defined OPENSSL_NO_SM3) \
+ && (!defined OPENSSL_NO_SM4)
+ ":TLS_SM4_GCM_SM3"
+ ":TLS_SM4_CCM_SM3"
+#endif
+ ;
}
unsigned long SSL_CIPHER_get_mkey(const SSL_CIPHER *c)
diff --git a/ssl/ssl_conf.c b/ssl/ssl_conf.c
index 3d8d1a4..b531cce 100644
--- a/ssl/ssl_conf.c
+++ b/ssl/ssl_conf.c
@@ -768,6 +768,25 @@ static int cmd_Enable_tlcp(SSL_CONF_CTX *cctx, const char *value)
return 1;
}
#endif
+
+#ifndef OPENSSL_NO_SM2
+static int cmd_Enable_sm_tls13_strict(SSL_CONF_CTX *cctx, const char *value)
+{
+ if (strcmp(value, "on") == 0) {
+ if (cctx->ctx)
+ SSL_CTX_enable_sm_tls13_strict(cctx->ctx);
+ if (cctx->ssl)
+ SSL_enable_sm_tls13_strict(cctx->ssl);
+ } else {
+ if (cctx->ctx)
+ SSL_CTX_disable_sm_tls13_strict(cctx->ctx);
+ if (cctx->ssl)
+ SSL_disable_sm_tls13_strict(cctx->ssl);
+ }
+ return 1;
+}
+#endif
+
typedef struct {
int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
const char *str_file;
@@ -879,6 +898,9 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD(SignPrivateKey, "sign_key", SSL_CONF_FLAG_CERTIFICATE,
SSL_CONF_TYPE_FILE),
#endif
+#ifndef OPENSSL_NO_SM2
+ SSL_CONF_CMD_STRING(Enable_sm_tls13_strict, "Enable_sm_tls13_strict", 0),
+#endif
};
/* Supported switches: must match order of switches in ssl_conf_cmds */
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 8822593..feb3944 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -23,6 +23,10 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"attempt to reuse session in different context"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_AT_LEAST_TLS_1_2_NEEDED_IN_SUITEB_MODE),
"at least (D)TLS 1.2 needed in Suite B mode"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CERTIFICATE_SIGNATURE_TYPE),
+ "bad certificate signature type"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CERTIFICATE_USAGE),
+ "bad certificate usage"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CHANGE_CIPHER_SPEC),
"bad change cipher spec"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_BAD_CIPHER), "bad cipher"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 6d365d6..df265bf 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -714,6 +714,9 @@ SSL *SSL_new(SSL_CTX *ctx)
#ifndef OPENSSL_NO_TLCP
s->enable_tlcp = ctx->enable_tlcp;
#endif
+#ifndef OPENSSL_NO_SM2
+ s->enable_sm_tls13_strict = ctx->enable_sm_tls13_strict;
+#endif
/* Shallow copy of the ciphersuites stack */
s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites);
@@ -3264,6 +3267,9 @@ SSL_CTX *SSL_CTX_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
#ifndef OPENSSL_NO_TLCP
ret->enable_tlcp = 0;
+#endif
+#ifndef OPENSSL_NO_SM2
+ ret->enable_sm_tls13_strict = 0;
#endif
ret->method = meth;
ret->min_proto_version = 0;
@@ -6326,3 +6332,25 @@ void SSL_debug(SSL *s, unsigned char *str, int len)
printf("\n");
printf("%d\n", len);
}
+
+#ifndef OPENSSL_NO_SM2
+void SSL_CTX_enable_sm_tls13_strict(SSL_CTX *ctx)
+{
+ ctx->enable_sm_tls13_strict = 1;
+}
+
+void SSL_CTX_disable_sm_tls13_strict(SSL_CTX *ctx)
+{
+ ctx->enable_sm_tls13_strict = 0;
+}
+
+void SSL_enable_sm_tls13_strict(SSL *s)
+{
+ s->enable_sm_tls13_strict = 1;
+}
+
+void SSL_disable_sm_tls13_strict(SSL *s)
+{
+ s->enable_sm_tls13_strict = 0;
+}
+#endif
\ No newline at end of file
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
index 35c8469..cd4d2b9 100644
--- a/ssl/ssl_local.h
+++ b/ssl/ssl_local.h
@@ -41,6 +41,9 @@
# define OPENSSL_EXTERN OPENSSL_EXPORT
# endif
+# define SM2_DEFAULT_ID "1234567812345678"
+# define SM2_DEFAULT_ID_LEN (sizeof(SM2_DEFAULT_ID) - 1)
+
# define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
@@ -1241,6 +1244,14 @@ struct ssl_ctx_st {
/* Tag of TLCP */
int enable_tlcp;
#endif
+#ifndef OPENSSL_NO_SM2
+ /*
+ * tag of determining whether we should strict follow RFC 8998,
+ * when this tag set to 1, we will reject "TLS_SM4_GCM_SM3" and "TLS_SM4_CCM_SM3"
+ * without sm2 cert at server. This tag set to 0 default
+ */
+ int enable_sm_tls13_strict;
+#endif
};
typedef struct cert_pkey_st CERT_PKEY;
@@ -1844,6 +1855,15 @@ struct ssl_st {
# ifndef OPENSSL_NO_TLCP
int enable_tlcp;
# endif
+
+# ifndef OPENSSL_NO_SM2
+ /*
+ * tag of determining whether we should strict follow RFC 8998,
+ * when this tag set to 1, we will reject "TLS_SM4_GCM_SM3" and "TLS_SM4_CCM_SM3"
+ * without sm2 cert at server. This tag set to 0 default
+ */
+ int enable_sm_tls13_strict;
+# endif
};
/*
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 3cd1ee2..1fad242 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -23,6 +23,7 @@
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
+#include <openssl/x509v3.h>
#include <openssl/trace.h>
#include <openssl/core_names.h>
#include <openssl/param_build.h>
@@ -1659,6 +1660,26 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
goto err;
}
+#ifndef OPENSSL_NO_SM2
+ /*
+ * To use the cipher suites TLS_SM4_GCM_SM3 and TLS_SM4_CCM_SM3,
+ * RFC 8998 demand that:
+ * For the key_share extension, a KeyShareEntry with SM2-related
+ * values MUST be added.
+ */
+ if (SSL_IS_TLS13(s) && s->enable_sm_tls13_strict == 1) {
+ const SSL_CIPHER *cipher = s->s3.tmp.new_cipher;
+
+ if (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3) {
+ if (s->s3.group_id != TLSEXT_curve_SM2) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
+ goto err;
+ }
+ }
+ }
+#endif
+
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
@@ -1843,6 +1864,45 @@ MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
}
x = NULL;
}
+
+#ifndef OPENSSL_NO_SM2
+ {
+ EVP_PKEY *pkey = NULL;
+ int n = sk_X509_num(s->session->peer_chain) - 1;
+
+ x = sk_X509_value(s->session->peer_chain, 0);
+ pkey = X509_get0_pubkey(x);
+
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey)) {
+ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ while (n >= 0) {
+ X509 *cert = sk_X509_value(s->session->peer_chain, n);
+ ASN1_OCTET_STRING *sm2_id;
+ sm2_id = ASN1_OCTET_STRING_new();
+
+ if (sm2_id == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!ASN1_OCTET_STRING_set(sm2_id,
+ (const unsigned char *)CERTVRIFY_SM2_ID,
+ CERTVRIFY_SM2_ID_LEN)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ ASN1_OCTET_STRING_free(sm2_id);
+ goto err;
+ }
+
+ X509_set0_sm2_id(cert, sm2_id);
+ n--;
+ }
+ }
+ }
+#endif
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
@@ -1922,6 +1982,41 @@ WORK_STATE tls_post_process_server_certificate(SSL *s, WORK_STATE wst)
}
}
+#ifndef OPENSSL_NO_SM2
+ /*
+ * RFC 8998 requires that
+ * The public key in the certificate MUST be a valid SM2 public key.
+ * The signature algorithm used by the CA to sign the current
+ * certificate MUST be "sm2sig_sm3".
+ * The certificate MUST be capable of signing; e.g., the digitalSignature
+ * bit of X.509's Key Usage extension is set.
+ */
+ if (SSL_IS_TLS13(s) && s->enable_sm_tls13_strict == 1) {
+ const SSL_CIPHER *cipher = s->s3.tmp.new_cipher;
+
+ if (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3) {
+ if (EVP_PKEY_id(pkey) != EVP_PKEY_SM2) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
+ SSL_R_WRONG_CERTIFICATE_TYPE);
+ return WORK_ERROR;
+ }
+
+ if (X509_get_signature_nid(x) != NID_SM2_with_SM3) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
+ SSL_R_BAD_CERTIFICATE_SIGNATURE_TYPE);
+ return WORK_ERROR;
+ }
+
+ if ((X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE) == 0) {
+ SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
+ SSL_R_BAD_CERTIFICATE_USAGE);
+ return WORK_ERROR;
+ }
+ }
+ }
+#endif
+
X509_free(s->session->peer);
X509_up_ref(x);
s->session->peer = x;
@@ -2381,6 +2476,39 @@ MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
return MSG_PROCESS_ERROR;
}
OPENSSL_free(rawexts);
+#ifndef OPENSSL_NO_SM2
+ /*
+ * RFC 8998 requires that
+ * if the server chooses TLS_SM4_GCM_SM3 or TLS_SM4_CCM_SM3,
+ * the only valid signature algorithm present in
+ * "signature_algorithms" extension MUST be "sm2sig_sm3".
+ */
+ if (s->enable_sm_tls13_strict == 1) {
+ const SSL_CIPHER *cipher = s->s3.tmp.new_cipher;
+
+ if (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3) {
+
+ if (s->s3.tmp.peer_sigalgslen > 0
+ && (s->s3.tmp.peer_sigalgslen != 1
+ || s->s3.tmp.peer_sigalgs[0] != TLSEXT_SIGALG_sm2sig_sm3))
+ {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ return MSG_PROCESS_ERROR;
+ }
+
+ if (s->s3.tmp.peer_cert_sigalgslen > 0
+ && (s->s3.tmp.peer_cert_sigalgslen != 1
+ || s->s3.tmp.peer_cert_sigalgs[0] != TLSEXT_SIGALG_sm2sig_sm3))
+ {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
+ SSL_R_NO_SUITABLE_SIGNATURE_ALGORITHM);
+ return MSG_PROCESS_ERROR;
+ }
+ }
+ }
+#endif
if (!tls1_process_sigalgs(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_R_BAD_LENGTH);
return MSG_PROCESS_ERROR;
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index b1ee38b..bb83aa6 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -299,6 +299,27 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
goto err;
}
+#ifndef OPENSSL_NO_SM2
+ if (EVP_PKEY_is_sm2(pkey)) {
+ if (pkey != NULL) {
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pkey,
+ s->ctx->propq);
+ if (pctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set1_id(pctx, HANDSHAKE_SM2_ID,
+ HANDSHAKE_SM2_ID_LEN) != 1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+ }
+ }
+#endif
+
/* Get the data to be signed */
if (!get_cert_verify_tbs_data(s, tls13tbs, &hdata, &hdatalen)) {
/* SSLfatal() already called */
@@ -387,10 +408,19 @@ int tls_construct_cert_verify(SSL *s, WPACKET *pkt)
OPENSSL_free(sig);
EVP_MD_CTX_free(mctx);
+#ifndef OPENSSL_NO_SM2
+ /*other sig call EVP_PKEY_CTX_free there may cause segfault */
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey))
+ EVP_PKEY_CTX_free(pctx);
+#endif
return 1;
err:
OPENSSL_free(sig);
EVP_MD_CTX_free(mctx);
+#ifndef OPENSSL_NO_SM2
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey))
+ EVP_PKEY_CTX_free(pctx);
+#endif
return 0;
}
@@ -424,6 +454,15 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
goto err;
}
+#ifndef OPENSSL_NO_SM2
+ if (EVP_PKEY_is_sm2(pkey)) {
+ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
+
if (ssl_cert_lookup_by_pkey(pkey, NULL) == NULL) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE);
@@ -489,6 +528,24 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
OSSL_TRACE1(TLS, "Using client verify alg %s\n",
md == NULL ? "n/a" : EVP_MD_get0_name(md));
+#ifndef OPENSSL_NO_SM2
+ if (EVP_PKEY_is_sm2(pkey)) {
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pkey, s->ctx->propq);
+ if (pctx == NULL) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set1_id(pctx, HANDSHAKE_SM2_ID,
+ HANDSHAKE_SM2_ID_LEN) != 1) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+ }
+#endif
+
if (EVP_DigestVerifyInit_ex(mctx, &pctx,
md == NULL ? NULL : EVP_MD_get0_name(md),
s->ctx->libctx, s->ctx->propq, pkey,
@@ -558,6 +615,11 @@ MSG_PROCESS_RETURN tls_process_cert_verify(SSL *s, PACKET *pkt)
EVP_MD_CTX_free(mctx);
#ifndef OPENSSL_NO_GOST
OPENSSL_free(gost_data);
+#endif
+#ifndef OPENSSL_NO_SM2
+ /*other sig call EVP_PKEY_CTX_free there may cause segfault */
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey))
+ EVP_PKEY_CTX_free(pctx);
#endif
return ret;
}
diff --git a/ssl/statem/statem_local.h b/ssl/statem/statem_local.h
index ad4d93b..4c143c6 100644
--- a/ssl/statem/statem_local.h
+++ b/ssl/statem/statem_local.h
@@ -42,6 +42,17 @@
#define TLSEXT_TYPE_out_of_range 0x10001
unsigned int ossl_get_extension_type(size_t idx);
+#ifndef OPENSSL_NO_SM2
+/*
+ * standard handshake sm2-id and cert verify id is defined in RFC 8998
+ */
+# define HANDSHAKE_SM2_ID "TLSv1.3+GM+Cipher+Suite"
+# define HANDSHAKE_SM2_ID_LEN sizeof(HANDSHAKE_SM2_ID) - 1
+# define CERTVRIFY_SM2_ID "1234567812345678"
+# define CERTVRIFY_SM2_ID_LEN sizeof(CERTVRIFY_SM2_ID) - 1
+
+#endif
+
extern const unsigned char hrrrandom[];
/* Message processing return codes */
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index a9e67f9..d0d3e75 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1753,6 +1753,24 @@ static int tls_early_post_process_client_hello(SSL *s)
goto err;
}
s->s3.tmp.new_cipher = cipher;
+#ifndef OPENSSL_NO_SM2
+ /*
+ * According to RFC 8998, if server chooses TLS_SM4_GCM_SM3 or
+ * TLS_SM4_CCM_SM3, the named group must be curveSM2.
+ */
+ if (s->enable_sm_tls13_strict == 1
+ && (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3)) {
+ int sm2_group = NID_sm2;
+
+ if (!tls1_set_groups(&s->ext.supportedgroups,
+ &s->ext.supportedgroups_len,
+ &sm2_group, 1)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
}
/* We need to do this before getting the session */
@@ -1864,7 +1882,56 @@ static int tls_early_post_process_client_hello(SSL *s)
/* SSLfatal() already called */
goto err;
}
+
+#ifndef OPENSSL_NO_SM2
+ /*
+ * To use the cipher suites TLS_SM4_GCM_SM3 and TLS_SM4_CCM_SM3,
+ * RFC 8998 demand that:
+ * The certificate must be a SM2 cert;
+ * For the signature_algorithms extension, "sm2sig_sm3" MUST be included.
+ * For the signature_algorithms_cert extension (if present), "sm2sig_sm3"
+ * MUST be included.
+ * For the key_share extension, a KeyShareEntry for the "curveSM2"
+ * group MUST be included.
+ */
+ if (SSL_IS_TLS13(s) && s->enable_sm_tls13_strict == 1) {
+ const SSL_CIPHER *cipher = s->s3.tmp.new_cipher;
+ if (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3) {
+ uint16_t *peer_sig = s->s3.tmp.peer_sigalgs;
+ size_t idx;
+
+ for (idx = 0; idx < s->s3.tmp.peer_sigalgslen; idx++) {
+ if (peer_sig[idx] == TLSEXT_SIGALG_sm2sig_sm3)
+ break;
+ }
+
+ if (s->s3.tmp.peer_sigalgslen > 0
+ && idx >= s->s3.tmp.peer_sigalgslen) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_VALUE);
+ goto err;
+ }
+
+ peer_sig = s->s3.tmp.peer_cert_sigalgs;
+ for (idx = 0; idx < s->s3.tmp.peer_cert_sigalgslen; idx++) {
+ if (peer_sig[idx] == TLSEXT_SIGALG_sm2sig_sm3)
+ break;
+ }
+
+ if (s->s3.tmp.peer_cert_sigalgslen > 0
+ && idx >= s->s3.tmp.peer_cert_sigalgslen) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_VALUE);
+ goto err;
+ }
+
+ if (s->s3.group_id != TLSEXT_curve_SM2) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_BAD_KEY_SHARE);
+ goto err;
+ }
+ }
+ }
+#endif
/*
* Check if we want to use external pre-shared secret for this handshake
* for not reused session only. We need to generate server_random before
diff --git a/ssl/statem_tlcp/tlcp_statem_clnt.c b/ssl/statem_tlcp/tlcp_statem_clnt.c
index b9f4e69..ab7067b 100644
--- a/ssl/statem_tlcp/tlcp_statem_clnt.c
+++ b/ssl/statem_tlcp/tlcp_statem_clnt.c
@@ -1287,6 +1287,45 @@ MSG_PROCESS_RETURN tls_process_server_certificate_tlcp(SSL *s, PACKET *pkt)
x = NULL;
}
+# ifndef OPENSSL_NO_SM2
+ {
+ EVP_PKEY *pkey = NULL;
+ int n = sk_X509_num(s->session->peer_chain) - 1;
+
+ x = sk_X509_value(s->session->peer_chain, 0);
+ pkey = X509_get0_pubkey(x);
+
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey)) {
+ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ while (n >= 0) {
+ X509 *cert = sk_X509_value(s->session->peer_chain, n);
+ ASN1_OCTET_STRING *sm2_id;
+ sm2_id = ASN1_OCTET_STRING_new();
+
+ if (sm2_id == NULL) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (!ASN1_OCTET_STRING_set(sm2_id,
+ (const unsigned char *)CERTVRIFY_SM2_ID,
+ CERTVRIFY_SM2_ID_LEN)) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ ASN1_OCTET_STRING_free(sm2_id);
+ goto err;
+ }
+
+ X509_set0_sm2_id(cert, sm2_id);
+ n--;
+ }
+ }
+ }
+# endif
+
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
diff --git a/ssl/statem_tlcp/tlcp_statem_lib.c b/ssl/statem_tlcp/tlcp_statem_lib.c
index 21d303e..81003f4 100644
--- a/ssl/statem_tlcp/tlcp_statem_lib.c
+++ b/ssl/statem_tlcp/tlcp_statem_lib.c
@@ -336,6 +336,36 @@ MSG_PROCESS_RETURN tls_process_cert_verify_tlcp(SSL *s, PACKET *pkt)
OSSL_TRACE1(TLS, "Using client verify alg %s\n",
md == NULL ? "n/a" : EVP_MD_get0_name(md));
+#ifndef OPENSSL_NO_SM2
+ if (EVP_PKEY_is_sm2(pkey)) {
+ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2)) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (pkey != NULL) {
+ pctx = EVP_PKEY_CTX_new_from_pkey(s->ctx->libctx, pkey, s->ctx->propq);
+ if (pctx == NULL) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+
+ if (EVP_PKEY_CTX_set1_id(pctx, HANDSHAKE_SM2_ID,
+ HANDSHAKE_SM2_ID_LEN) != 1) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_EVP_LIB);
+ goto err;
+ }
+
+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx);
+ }
+
+ if (!EVP_PKEY_set_alias_type(pkey, EVP_PKEY_EC)) {
+ SSLfatal_tlcp(s, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
+ goto err;
+ }
+ }
+#endif
+
if (EVP_DigestVerifyInit_ex(mctx, &pctx,
md == NULL ? NULL : EVP_MD_get0_name(md),
s->ctx->libctx, s->ctx->propq, pkey,
@@ -374,6 +404,11 @@ MSG_PROCESS_RETURN tls_process_cert_verify_tlcp(SSL *s, PACKET *pkt)
EVP_MD_CTX_free(mctx2);
EVP_MD_CTX_free(mctx);
+#ifndef OPENSSL_NO_SM2
+ /*other sig call EVP_PKEY_CTX_free there may cause segfault */
+ if (pkey != NULL && EVP_PKEY_is_sm2(pkey))
+ EVP_PKEY_CTX_free(pctx);
+#endif
return ret;
}
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 0cfbdaf..5440199 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -728,6 +728,10 @@ int tls1_set_groups(uint16_t **pext, size_t *pextlen,
unsigned long idmask;
uint16_t id;
id = tls1_nid2group_id(groups[i]);
+ if (ngroups == 1) {
+ glist[i] = id;
+ break;
+ }
if ((id & 0x00FF) >= (sizeof(unsigned long) * 8))
goto err;
idmask = 1L << (id & 0x00FF);
@@ -1592,7 +1596,7 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
*/
if (lu == NULL
|| (SSL_IS_TLS13(s) && (lu->hash == NID_sha1 || lu->hash == NID_sha224))
- || (pkeyid != lu->sig
+ || (pkeyid != lu->sig && lu->sig != EVP_PKEY_SM2
&& (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
@@ -2296,6 +2300,26 @@ int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
if (lu == NULL
|| !tls12_sigalg_allowed(s, SSL_SECOP_SIGALG_SUPPORTED, lu))
continue;
+
+#ifndef OPENSSL_NO_SM2
+ /*
+ * RFC 8998 requires that
+ * if the server chooses TLS_SM4_GCM_SM3 or TLS_SM4_CCM_SM3,
+ * the only valid signature algorithm present in
+ * "signature_algorithms" extension MUST be "sm2sig_sm3".
+ */
+ if (SSL_IS_TLS13(s) && s->enable_sm_tls13_strict == 1 && s->server) {
+ const SSL_CIPHER *cipher = s->s3.tmp.new_cipher;
+
+ if (cipher != NULL &&
+ (cipher->id == TLS1_3_CK_SM4_GCM_SM3
+ || cipher->id == TLS1_3_CK_SM4_CCM_SM3)) {
+ if (lu->sigalg != TLSEXT_SIGALG_sm2sig_sm3)
+ continue;
+ }
+ }
+#endif
+
if (!WPACKET_put_bytes_u16(pkt, *psig))
return 0;
/*
diff --git a/test/cipherlist_test.c b/test/cipherlist_test.c
index 4ff2aa1..42db42d 100644
--- a/test/cipherlist_test.c
+++ b/test/cipherlist_test.c
@@ -69,6 +69,10 @@ static const uint32_t default_ciphers_in_order[] = {
TLS1_3_CK_CHACHA20_POLY1305_SHA256,
# endif
TLS1_3_CK_AES_128_GCM_SHA256,
+# if (!defined OPENSSL_NO_SM2) && (!defined OPENSSL_NO_SM3) \
+ && (!defined OPENSSL_NO_SM4)
+ TLS1_3_CK_SM4_GCM_SM3,
+# endif
#endif
#ifndef OPENSSL_NO_TLS1_2
# ifndef OPENSSL_NO_EC
@@ -161,6 +166,11 @@ static int test_default_cipherlist(SSL_CTX *ctx)
num_expected_ciphers = OSSL_NELEM(default_ciphers_in_order);
num_ciphers = sk_SSL_CIPHER_num(ciphers);
+ for (i = 0; i < num_ciphers; i++) {
+ expected_cipher_id = default_ciphers_in_order[i];
+ cipher_id = SSL_CIPHER_get_id(sk_SSL_CIPHER_value(ciphers, i));
+ fprintf(stderr, "%x <-> %x\n", cipher_id, expected_cipher_id);
+ }
if (!TEST_int_eq(num_ciphers, num_expected_ciphers))
goto err;
diff --git a/test/ciphername_test.c b/test/ciphername_test.c
index e3aefab..1c4bfbf 100644
--- a/test/ciphername_test.c
+++ b/test/ciphername_test.c
@@ -361,6 +361,7 @@ static CIPHER_ID_NAME cipher_names[] = {
{0x1303, "TLS_CHACHA20_POLY1305_SHA256"},
{0x1304, "TLS_AES_128_CCM_SHA256"},
{0x1305, "TLS_AES_128_CCM_8_SHA256"},
+ {0x00C6, "TLS_SM4_GCM_SM3"},
{0xFEFE, "SSL_RSA_FIPS_WITH_DES_CBC_SHA"},
{0xFEFF, "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA"},
{0xE011, "ECDHE_SM4_CBC_SM3"},
diff --git a/test/sslapitest.c b/test/sslapitest.c
index 78f6c56..5f071d8 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -7703,7 +7703,12 @@ static struct {
"AES256-SHA:AES128-SHA256",
NULL,
"TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:"
- "TLS_AES_128_GCM_SHA256:AES256-SHA",
+ "TLS_AES_128_GCM_SHA256:"
+# if !defined(OPENSSL_NO_SM2) && !defined(OPENSSL_NO_SM3) \
+ && !defined(OPENSSL_NO_SM4)
+ "TLS_SM4_GCM_SM3:"
+# endif
+ "AES256-SHA",
"TLS_AES_256_GCM_SHA384:TLS_AES_128_GCM_SHA256:AES256-SHA"
},
#endif
diff --git a/test/ssl_cert_table_internal_test.c b/test/ssl_cert_table_internal_test.c
index e8969aa..5c5434f 100644
--- a/test/ssl_cert_table_internal_test.c
+++ b/test/ssl_cert_table_internal_test.c
@@ -46,7 +46,11 @@ static int test_ssl_cert_table(void)
return TEST_size_t_eq(OSSL_NELEM(ssl_cert_info), SSL_PKEY_NUM)
&& test_cert_table(EVP_PKEY_RSA, SSL_aRSA, SSL_PKEY_RSA)
&& test_cert_table(EVP_PKEY_DSA, SSL_aDSS, SSL_PKEY_DSA_SIGN)
+#ifndef OPENSSL_NO_SM2
+ && test_cert_table(EVP_PKEY_EC, SSL_aECDSA | SSL_aSM2, SSL_PKEY_ECC)
+#else
&& test_cert_table(EVP_PKEY_EC, SSL_aECDSA, SSL_PKEY_ECC)
+#endif
&& test_cert_table(NID_id_GostR3410_2001, SSL_aGOST01,
SSL_PKEY_GOST01)
&& test_cert_table(NID_id_GostR3410_2012_256, SSL_aGOST12,
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 3476881..9732986 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -4391,7 +4391,7 @@ EVP_PKEY_get_raw_public_key 4518 3_0_0 EXIST::FUNCTION:
EVP_PKEY_get_raw_private_key 4519 3_0_0 EXIST::FUNCTION:
EVP_PKEY_asn1_set_get_priv_key 4520 3_0_0 EXIST::FUNCTION:
EVP_PKEY_asn1_set_get_pub_key 4521 3_0_0 EXIST::FUNCTION:
-EVP_PKEY_set_alias_type 4522 3_0_0 NOEXIST::FUNCTION:DEPRECATEDIN_3_0
+EVP_PKEY_set_alias_type 4522 3_0_0 EXIST::FUNCTION:
RAND_keep_random_devices_open 4523 3_0_0 EXIST::FUNCTION:
EC_POINT_set_compressed_coordinates 4524 3_0_0 EXIST::FUNCTION:EC
EC_POINT_set_affine_coordinates 4525 3_0_0 EXIST::FUNCTION:EC
diff --git a/util/libssl.num b/util/libssl.num
index bfa0dc0..8ad73a4 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -564,3 +564,7 @@ SSL_CTX_certs_clear 564 3_0_3 EXIST::FUNCTION:
SSL_check_tlsext_status 565 3_0_3 EXIST::FUNCTION:
SSL_get_master_key 566 3_0_3 EXIST::FUNCTION:
SSL_debug 567 3_0_3 EXIST::FUNCTION:
+SSL_CTX_enable_sm_tls13_strict 568 3_0_3 EXIST::FUNCTION:SM2
+SSL_CTX_disable_sm_tls13_strict 569 3_0_3 EXIST::FUNCTION:SM2
+SSL_enable_sm_tls13_strict 570 3_0_3 EXIST::FUNCTION:SM2
+SSL_disable_sm_tls13_strict 571 3_0_3 EXIST::FUNCTION:SM2
diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt
index 27c8018..443bb6b 100644
--- a/util/missingcrypto.txt
+++ b/util/missingcrypto.txt
@@ -1376,3 +1376,4 @@ v2i_ASN1_BIT_STRING(3)
v2i_GENERAL_NAME(3)
v2i_GENERAL_NAMES(3)
v2i_GENERAL_NAME_ex(3)
+EVP_PKEY_set_alias_type(3)
diff --git a/util/missingssl.txt b/util/missingssl.txt
index 41ca8a8..cf171dc 100644
--- a/util/missingssl.txt
+++ b/util/missingssl.txt
@@ -31,3 +31,7 @@ SSL_set_session_ticket_ext_cb(3)
SSL_srp_server_param_with_username(3)
SSL_test_functions(3)
SSL_trace(3)
+SSL_CTX_enable_sm_tls13_strict(3)
+SSL_CTX_disable_sm_tls13_strict(3)
+SSL_enable_sm_tls13_strict(3)
+SSL_disable_sm_tls13_strict(3)
diff --git a/util/other.syms b/util/other.syms
index 89eb5bc..a12826c 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -707,3 +707,4 @@ SSL_CTX_certs_clear define
OPENSSL_CHECK_TLSEXT_STATUS define
SSL_set_SESSION_CTX define
SSL_debug define
+EVP_PKEY_is_sm2 define
--
2.41.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。