From bcb80f23d5af477e8d22e6968db354f2e673ed46 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 10 May 2026 16:24:42 +0800 Subject: [PATCH] TLS 1.3 Update CertificateRequest with empty client Certificate and no client CertificateVerify --- src/tls13.c | 49 ++++++++++++++++++++++++++++++++++---------- tools/tls13_server.c | 11 +++++----- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index d097ae12..955fd0c3 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -456,10 +456,8 @@ int tls13_do_recv(TLS_CONNECT *conn) conn->record_offset = 0; conn->recordlen = TLS_RECORD_HEADER_SIZE; conn->state = TLS_state_recv_record_header; - error_print(); case TLS_state_recv_record_header: - error_print(); while (conn->recordlen) { if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -484,8 +482,6 @@ int tls13_do_recv(TLS_CONNECT *conn) conn->state = TLS_state_recv_record_data; case TLS_state_recv_record_data: - error_print(); - while (conn->recordlen) { if ((n = tls_socket_recv(conn->sock, conn->record + conn->record_offset, conn->recordlen, 0)) <= 0) { if (errno == EAGAIN || errno == EWOULDBLOCK) { @@ -2997,6 +2993,8 @@ int _tls13_record_get_handshake_certificate(const uint8_t *record, */ +// FIMXE: 这里 entity_status_request_ocsp_response 改为 leaf_xxxx + // even if status_request, signed_certificate_timestamp not requested // server/client can still return certificate with these two extensions int tls13_record_get_handshake_certificate(const uint8_t *record, @@ -3033,6 +3031,19 @@ int tls13_record_get_handshake_certificate(const uint8_t *record, return -1; } + // 客户端的证书链中的cert_list 可能为空 + if (!cert_list) { + *cert_chain_len = 0; + *entity_status_request_ocsp_response = NULL; + *entity_status_request_ocsp_response_len = 0; + *entity_signed_certificate_timestamp = NULL; + *entity_signed_certificate_timestamp_len = 0; + return 1; + } + + + + if (tls13_certificate_entry_from_bytes(&cert, &certlen, entity_status_request_ocsp_response, entity_status_request_ocsp_response_len, entity_signed_certificate_timestamp, entity_signed_certificate_timestamp_len, @@ -5627,7 +5638,15 @@ int tls13_recv_certificate_request(TLS_CONNECT *conn) // * [oid_filter] // if (client_cert) { - if ((ret = tls13_cert_chains_select(conn->ctx->cert_chains, conn->ctx->cert_chains_len, + // client provides no certificate + if (!conn->ctx->cert_chains_len) { + warning_print(); + conn->cert_chain = NULL; + conn->cert_chain_len = 0; + conn->cert_chain_idx = 0; + ret = 0; + } else if ((ret = tls13_cert_chains_select( + conn->ctx->cert_chains, conn->ctx->cert_chains_len, common_sig_algs, common_sig_algs_cnt, common_sig_algs_cert, common_sig_algs_cert_cnt, ca_names, ca_names_len, @@ -7993,6 +8012,9 @@ int tls13_send_server_finished(TLS_CONNECT *conn) return ret; } + conn->record_offset = 0; + conn->recordlen = 0; + return 1; } @@ -8016,7 +8038,7 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn) int verify_result; - tls_trace("recv {Certificate*}\n"); + tls_trace("recv client {Certificate*}\n"); if ((ret = tls_recv_record(conn)) != 1) { if (ret != TLS_ERROR_RECV_AGAIN) { @@ -8024,7 +8046,6 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn) } return ret; } - tls13_record_print(stderr, 0, 0, conn->record, conn->recordlen); if (tls_record_protocol(conn->record) != TLS_protocol_tls12) { error_print(); @@ -8069,10 +8090,14 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn) tls13_send_alert(conn, TLS_alert_illegal_parameter); return -1; } + + // 即使服务器发送CertificateRequest,客户端可能没有合适的证书 + // 客户端可能发送一个空的Certificate,并且不发送CertificateVerify if (!conn->peer_cert_chain_len) { - error_print(); - tls13_send_alert(conn, TLS_alert_illegal_parameter); - return -1; + warning_print(); + //tls13_send_alert(conn, TLS_alert_illegal_parameter); + //return -1; + return 0; } // client cert_chain match CertificateRequest extensions @@ -8607,7 +8632,9 @@ int tls13_do_server_handshake(TLS_CONNECT *conn) case TLS_state_client_certificate: ret = tls13_recv_client_certificate(conn); - next_state = TLS_state_client_certificate_verify; + if (ret == 0) // 客户端提供了一个空的Certificate消息 + next_state = TLS_state_client_finished; + else next_state = TLS_state_client_certificate_verify; break; case TLS_state_client_certificate_verify: diff --git a/tools/tls13_server.c b/tools/tls13_server.c index 9b280acb..a7341516 100644 --- a/tools/tls13_server.c +++ b/tools/tls13_server.c @@ -229,11 +229,6 @@ static const char *help = " gmssl tls13_client -host 127.0.0.1 -port 4430 -cipher_suite TLS_SM4_GCM_SM3 \\\n" " -psk_ke -psk_identity 001 -psk_cipher_suite TLS_SM4_GCM_SM3 -psk_key $PSK \\\n" " -early_data early_data.txt\n" - -// 有一种情况需要验证,就是服务器发送证书请求,但是客户端只是发送一个空的证书,但是不提供CertificateVerify - -// 客户端证书暂时用服务器一样的证书吧 - "\n" "CertificateRequest\n" "\n" @@ -243,8 +238,12 @@ static const char *help = "\n" " gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert sm2rootcacert.pem \\\n" " -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3 \\\n" -// 客户端也需要支持载入多个证书 " -cert sm2certs.pem -key sm2signkey.pem -pass 1234\n" +"\n" +"CertificateRequest without CertificateVerify\n" +"\n" +" gmssl tls13_client -host 127.0.0.1 -port 4430 -cacert sm2rootcacert.pem \\\n" +" -cipher_suite TLS_SM4_GCM_SM3 -supported_group sm2p256v1 -sig_alg sm2sig_sm3\n" "\n";