Skip to content

Commit

Permalink
修复TLS 1.3使用商密套件时未严格遵循RFC 8998问题
Browse files Browse the repository at this point in the history
Fixed #491

强制遵循RFC 8998时:
当使用商密套件且加载双证书时,修复未选择SM2证书问题;
收到CertificateVerify需要检查签名算法,如果不是sm2sig_sm3,应该alert。

修复TLS 1.3商密套件trace,unknown问题;
SSL conf中增加Trace配置项,Trace设置为on时,可以输出TLS消息,方便定位问题。
  • Loading branch information
dongbeiouba committed Nov 30, 2023
1 parent 6a4ad4d commit d1c45d5
Show file tree
Hide file tree
Showing 5 changed files with 223 additions and 1 deletion.
35 changes: 35 additions & 0 deletions ssl/ssl_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,38 @@ static int cmd_Enable_sign_by_dc(SSL_CONF_CTX *cctx, const char *value)

#endif

#ifndef OPENSSL_NO_SSL_TRACE
static void trace_cb(int write_p, int version, int content_type,
const void *buf, size_t msglen, SSL *ssl, void *arg)
{
BIO *bio = NULL;
if (arg == NULL) {
bio = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT);
if (bio == NULL)
return;

arg = bio;
}

SSL_trace(write_p, version, content_type, buf, msglen, ssl, arg);

BIO_free(bio);
}

static int cmd_Trace(SSL_CONF_CTX *cctx, const char *value)
{
if (strcmp(value, "on") == 0) {
if (cctx->ctx)
SSL_CTX_set_msg_callback(cctx->ctx, trace_cb);

if (cctx->ssl)
SSL_set_msg_callback(cctx->ssl, trace_cb);
}

return 1;
}
#endif

typedef struct {
int (*cmd) (SSL_CONF_CTX *cctx, const char *value);
const char *str_file;
Expand Down Expand Up @@ -885,6 +917,9 @@ static const ssl_conf_cmd_tbl ssl_conf_cmds[] = {
SSL_CONF_CMD_STRING(Enable_verify_peer_by_dc, "Enable_verify_peer_by_dc", 0),
SSL_CONF_CMD_STRING(Enable_sign_by_dc, "Enable_sign_by_dc", 0),
#endif
#ifndef OPENSSL_NO_SSL_TRACE
SSL_CONF_CMD_STRING(Trace, "Trace", 0),
#endif
};

/* Supported switches: must match order of switches in ssl_conf_cmds */
Expand Down
40 changes: 40 additions & 0 deletions ssl/t1_lib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,26 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
if (pkeyid == -1)
return -1;
if (SSL_IS_TLS13(s)) {
#ifndef OPENSSL_NO_SM2
/*
* RFC 8998 requires that if TLS_SM4_GCM_SM3 or TLS_SM4_CCM_SM3 was
* choosen, the only valid signature algorithm MUST be "sm2sig_sm3".
*/
if (s->enable_sm_tls13_strict == 1) {
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 (sig != TLSEXT_SIGALG_sm2sig_sm3) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS12_CHECK_PEER_SIGALG,
SSL_R_WRONG_SIGNATURE_TYPE);
return 0;
}
}
}
#endif

/* Disallow DSA for TLS 1.3 */
if (pkeyid == EVP_PKEY_DSA) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS12_CHECK_PEER_SIGALG,
Expand Down Expand Up @@ -2860,6 +2880,26 @@ static const SIGALG_LOOKUP *find_sig_alg(SSL *s, X509 *x, EVP_PKEY *pkey)
if ((pkey == NULL && !has_usable_cert(s, lu, -1))
|| (pkey != NULL && !is_cert_usable(s, lu, x, pkey)))
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

tmppkey = (pkey != NULL) ? pkey
: s->cert->pkeys[lu->sig_idx].privatekey;

Expand Down
86 changes: 85 additions & 1 deletion test/ssl-tests/30-tls13-sm.conf
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Generated with generate_ssl_tests.pl

num_tests = 22
num_tests = 24

test-0 = 0-test ciphersuites TLS_SM4_GCM_SM3
test-1 = 1-test series of ciphersuites includes TLS_SM4_GCM_SM3
Expand All @@ -24,6 +24,8 @@ test-18 = 18-test client success when enable sm_tls13_strict with SM2 key_share
test-19 = 19-test client should fail when enable sm_tls13_strict with ecdsa cert and TLS_SM4_GCM_SM3 cipher
test-20 = 20-test client auth fail when enable sm_tls13_strict, CertificateRequest with other signature algorithms except sm2sig_sm3
test-21 = 21-test client auth success when both enable sm_tls13_strict
test-22 = 22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3
test-23 = 23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3
# ===========================================================

[0-test ciphersuites TLS_SM4_GCM_SM3]
Expand Down Expand Up @@ -711,3 +713,85 @@ ExpectedHRR = Yes
ExpectedResult = Success


# ===========================================================

[22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3]
ssl_conf = 22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-ssl

[22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-ssl]
server = 22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-server
client = 22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-client

[22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-server]
Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
CipherString = DEFAULT
Ciphersuites = TLS_SM4_GCM_SM3
Enable_sm_tls13_strict = on
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
RSA.Certificate = ${ENV::TEST_CERTS_DIR}/servercert.pem
RSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/serverkey.pem
SM2.Certificate = ${ENV::TEST_CERTS_DIR}/sm2-leaf.crt
SM2.PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-leaf.key
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-root.crt
VerifyMode = Require

[22-test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-client]
Certificate = ${ENV::TEST_CERTS_DIR}/sm2-first-crt.pem
CipherString = DEFAULT
Ciphersuites = TLS_SM4_GCM_SM3
Enable_sm_tls13_strict = on
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-first-key.pem
SignatureAlgorithms = rsa_pss_rsae_sha256:sm2sig_sm3
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-chain-ca.crt
VerifyMode = Peer

[test-22]
ExpectedCipher = TLS_SM4_GCM_SM3
ExpectedResult = Success
ExpectedServerCertType = SM2


# ===========================================================

[23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3]
ssl_conf = 23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-ssl

[23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-ssl]
server = 23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-server
client = 23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-client

[23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-server]
Certificate = ${ENV::TEST_CERTS_DIR}/sm2-leaf.crt
CipherString = DEFAULT
Ciphersuites = TLS_SM4_GCM_SM3
Enable_sm_tls13_strict = off
Groups = SM2
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-leaf.key
SignatureAlgorithms = rsa_pss_rsae_sha256:sm2sig_sm3
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-root.crt
VerifyMode = Require

[23-test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3-client]
CipherString = DEFAULT
Ciphersuites = TLS_SM4_GCM_SM3
Enable_sm_tls13_strict = on
MaxProtocol = TLSv1.3
MinProtocol = TLSv1.3
RSA.Certificate = ${ENV::TEST_CERTS_DIR}/ee-client-chain.pem
RSA.PrivateKey = ${ENV::TEST_CERTS_DIR}/ee-key.pem
SM2.Certificate = ${ENV::TEST_CERTS_DIR}/sm2-first-crt.pem
SM2.PrivateKey = ${ENV::TEST_CERTS_DIR}/sm2-first-key.pem
VerifyCAFile = ${ENV::TEST_CERTS_DIR}/sm2-chain-ca.crt
VerifyMode = Peer

[test-23]
ExpectedClientAlert = IllegalParameter
ExpectedResult = ClientFail


62 changes: 62 additions & 0 deletions test/ssl-tests/30-tls13-sm.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -485,4 +485,66 @@ our @tests = (
"ExpectedHRR" => "Yes",
},
},

{
name => "test sm_tls13_strict server with sm2 and rsa certs, client signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3",
server => {
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
"Ciphersuites" => "TLS_SM4_GCM_SM3",
"SM2.Certificate" => test_pem("sm2-leaf.crt"),
"SM2.PrivateKey" => test_pem("sm2-leaf.key"),
"RSA.Certificate" => test_pem("servercert.pem"),
"RSA.PrivateKey" => test_pem("serverkey.pem"),
"Enable_sm_tls13_strict" => "on",
"VerifyMode" => "Require",
"VerifyCAFile" => test_pem("sm2-root.crt"),
},
client => {
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
"Ciphersuites" => "TLS_SM4_GCM_SM3",
"SignatureAlgorithms" => "rsa_pss_rsae_sha256:sm2sig_sm3",
"Enable_sm_tls13_strict" => "on",
"VerifyCAFile" => test_pem("sm2-chain-ca.crt"),
"Certificate" => test_pem("sm2-first-crt.pem"),
"PrivateKey" => test_pem("sm2-first-key.pem"),
},
test => {
"ExpectedResult" => "Success",
"ExpectedCipher" => "TLS_SM4_GCM_SM3",
"ExpectedServerCertType" =>, "SM2",
},
},

{
name => "test sm_tls13_strict client with sm2 and rsa certs, server signature_algorithms with rsa_pss_rsae_sha256 and sm2sig_sm3",
server => {
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
"Ciphersuites" => "TLS_SM4_GCM_SM3",
"SignatureAlgorithms" => "rsa_pss_rsae_sha256:sm2sig_sm3",
"Groups" => "SM2",
"Certificate" => test_pem("sm2-leaf.crt"),
"PrivateKey" => test_pem("sm2-leaf.key"),
"Enable_sm_tls13_strict" => "off",
"VerifyMode" => "Require",
"VerifyCAFile" => test_pem("sm2-root.crt"),
},
client => {
"MinProtocol" => "TLSv1.3",
"MaxProtocol" => "TLSv1.3",
"Ciphersuites" => "TLS_SM4_GCM_SM3",
"Enable_sm_tls13_strict" => "on",
"SM2.Certificate" => test_pem("sm2-first-crt.pem"),
"SM2.PrivateKey" => test_pem("sm2-first-key.pem"),
"RSA.Certificate" => test_pem("ee-client-chain.pem"),
"RSA.PrivateKey" => test_pem("ee-key.pem"),
"VerifyCAFile" => test_pem("sm2-chain-ca.crt"),
},
test => {
"ExpectedResult" => "ClientFail",
"ExpectedClientAlert" => "IllegalParameter",
},
},
);
1 change: 1 addition & 0 deletions test/ssl_test_ctx.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ static const test_enum ssl_alerts[] = {
{"NoApplicationProtocol", SSL_AD_NO_APPLICATION_PROTOCOL},
{"CertificateRequired", SSL_AD_CERTIFICATE_REQUIRED},
{"CertificateExpired", SSL_AD_CERTIFICATE_EXPIRED},
{"IllegalParameter", SSL_AD_ILLEGAL_PARAMETER},
};

__owur static int parse_alert(int *alert, const char *value)
Expand Down

0 comments on commit d1c45d5

Please sign in to comment.