Add X509 verify_result

This commit is contained in:
Zhi Guan
2026-06-19 18:43:24 +08:00
parent 3d44be73cd
commit 2bcfb4a42b
7 changed files with 130 additions and 5 deletions

View File

@@ -821,7 +821,7 @@ endif()
#
set(CPACK_PACKAGE_NAME "GmSSL")
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1107")
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1108")
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
set(CPACK_NSIS_MODIFY_PATH ON)
include(CPack)

View File

@@ -18,7 +18,7 @@ extern "C" {
#define GMSSL_VERSION_NUM 30200
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1107"
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1108"
int gmssl_version_num(void);
const char *gmssl_version_str(void);

View File

@@ -380,6 +380,19 @@ typedef enum {
X509_cert_chain_client,
} X509_CERT_CHAIN_TYPE;
typedef enum {
X509_verify_ok = 0,
X509_verify_err_certificate,
X509_verify_err_cert_chain,
X509_verify_err_trust_anchor,
X509_verify_err_depth,
X509_verify_err_crl,
X509_verify_err_ocsp,
X509_verify_err_constraints,
X509_verify_err_tls_extensions,
X509_verify_err_hostname,
} X509_VERIFY_RESULT;
#define X509_MAX_VERIFY_DEPTH 6
//int x509_cert_chain_verify(const uint8_t *certs, size_t certslen,
// const uint8_t *cacerts, size_t cacertslen, int depth, int *verify_result);

View File

@@ -748,7 +748,7 @@ int tlcp_recv_server_certificate(TLS_CONNECT *conn)
int ret;
const uint8_t *server_cert;
size_t server_cert_len;
int verify_result;
int verify_result = X509_verify_ok;
if ((ret = tls_recv_record(conn)) != 1) {
if (ret != TLS_ERROR_RECV_AGAIN) {
@@ -795,10 +795,12 @@ int tlcp_recv_server_certificate(TLS_CONNECT *conn)
if ((ret = tls_cert_match_server_name(server_cert, server_cert_len,
conn->host_name, conn->host_name_len)) < 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
} else if (ret == 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -812,10 +814,12 @@ int tlcp_recv_server_certificate(TLS_CONNECT *conn)
NULL, 0,
conn->ctx->verify_depth, &verify_result) != 1) {
error_print();
conn->verify_result = verify_result;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
}
conn->verify_result = verify_result;
if (conn->client_certs_len) {
sm2_sign_update(&conn->sign_ctx, conn->record + 5, conn->recordlen - 5);

View File

@@ -1324,6 +1324,7 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
// check server certificate matches negotiated cipher_suite
if (!tls12_cipher_suite_match_cert_group(conn->cipher_suite, server_group)) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -1343,6 +1344,7 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
break;
default:
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -1352,6 +1354,7 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
if (!tls_type_is_in_list(server_group, conn->ctx->supported_groups,
conn->ctx->supported_groups_cnt)) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -1364,16 +1367,19 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
conn->ctx->signature_algorithms_cnt,
&cert_sig_alg)) < 0) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
} else if (ret == 0) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (!tls12_signature_scheme_match_cert_group(cert_sig_alg, server_group)
|| !tls12_signature_scheme_match_cipher_suite(cert_sig_alg, conn->cipher_suite)) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -1393,10 +1399,12 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
conn->peer_cert_chain, conn->peer_cert_chain_len,
signature_algorithms_cert, signature_algorithms_cert_cnt)) < 0) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
} else if (ret == 0) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -1407,10 +1415,12 @@ int tls_recv_server_certificate(TLS_CONNECT *conn)
if ((ret = tls_cert_match_server_name(server_cert, server_cert_len,
conn->host_name, conn->host_name_len)) < 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
} else if (ret == 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -2798,9 +2808,11 @@ int tls_recv_client_certificate(TLS_CONNECT *conn)
NULL, 0,
conn->ctx->verify_depth, &verify_result) != 1) {
error_print();
conn->verify_result = verify_result;
tls_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
conn->verify_result = verify_result;
if (digest_update(&conn->dgst_ctx, conn->record + 5, conn->recordlen - 5) != 1) {

View File

@@ -6172,7 +6172,7 @@ int tls13_recv_server_certificate(TLS_CONNECT *conn)
const uint8_t *host_name = NULL;
size_t host_name_len = 0;
int verify_result;
int verify_result = X509_verify_ok;
if(conn->verbose) tls_trace("recv server {Certificate}\n");
@@ -6224,6 +6224,7 @@ int tls13_recv_server_certificate(TLS_CONNECT *conn)
}
if (!conn->peer_cert_chain_len) {
error_print();
conn->verify_result = X509_verify_err_certificate;
tls13_send_alert(conn, TLS_alert_illegal_parameter);
return -1;
}
@@ -6241,6 +6242,26 @@ int tls13_recv_server_certificate(TLS_CONNECT *conn)
host_name = conn->host_name;
host_name_len = conn->host_name_len;
}
if (host_name && host_name_len) {
if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
conn->peer_cert_chain_len, 0, &cert, &certlen) != 1) {
error_print();
conn->verify_result = X509_verify_err_certificate;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if ((ret = tls_cert_match_server_name(cert, certlen, host_name, host_name_len)) < 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
} else if (ret == 0) {
error_print();
conn->verify_result = X509_verify_err_hostname;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
}
if (tls_cert_chain_match_extensions(conn->peer_cert_chain, conn->peer_cert_chain_len,
conn->ctx->signature_algorithms, conn->ctx->signature_algorithms_cnt,
signature_algorithms_cert, signature_algorithms_cert_cnt,
@@ -6249,6 +6270,7 @@ int tls13_recv_server_certificate(TLS_CONNECT *conn)
host_name, host_name_len,
NULL) != 1) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -6266,14 +6288,17 @@ int tls13_recv_server_certificate(TLS_CONNECT *conn)
conn->ctx->verify_depth, &verify_result);
if (ret < 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (ret == 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_certificate_revoked);
return -1;
}
conn->verify_result = verify_result;
// signed_certificate_timestamp
if (leaf_signed_certificate_timestamp) {
if (x509_certs_get_cert_by_index(conn->peer_cert_chain,
@@ -8523,7 +8548,7 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn)
const uint8_t *oid_filters = NULL;
size_t oid_filters_len = 0;
int verify_result;
int verify_result = X509_verify_ok;
if(conn->verbose) tls_trace("recv client {Certificate*}\n");
@@ -8609,6 +8634,7 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn)
NULL, 0, // server_name not in CertificateRequest
NULL) != 1) {
error_print();
conn->verify_result = X509_verify_err_tls_extensions;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
@@ -8621,14 +8647,17 @@ int tls13_recv_client_certificate(TLS_CONNECT *conn)
conn->ctx->verify_depth, &verify_result);
if (ret < 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_bad_certificate);
return -1;
}
if (ret == 0) {
error_print();
conn->verify_result = verify_result;
tls13_send_alert(conn, TLS_alert_certificate_revoked);
return -1;
}
conn->verify_result = verify_result;
// signed_certificate_timestamp
if (signed_certificate_timestamp) {
if (x509_certs_get_cert_by_index(conn->peer_cert_chain,

View File

@@ -1950,6 +1950,13 @@ static int x509_cert_check_optional_ocsp(const uint8_t *cert, size_t certlen,
return ret;
}
static void x509_verify_set_result(int *verify_result, int result)
{
if (verify_result) {
*verify_result = result;
}
}
int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
const uint8_t *rootcerts, size_t rootcertslen,
const uint8_t *crl, size_t crl_len,
@@ -1967,6 +1974,8 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
int path_len = 0;
x509_verify_set_result(verify_result, X509_verify_ok);
switch (certs_type) {
case X509_cert_chain_server:
entity_cert_type = X509_cert_server_auth;
@@ -1976,25 +1985,30 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
break;
default:
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
// entity cert
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_check(cert, certlen, entity_cert_type) != 1) {
error_print();
x509_cert_print(stderr, 0, 10, "Invalid Entity Certificate", cert, certlen);
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if ((ret = x509_cert_check_optional_crl(cert, certlen, crl, crl_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return -1;
}
if (ret == 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return 0;
}
@@ -2002,24 +2016,29 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_check(cacert, cacertlen, X509_cert_ca) != 1) {
error_print();
x509_cert_print(stderr, 0, 10, "Invalid CA Certificate", cacert, cacertlen);
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if ((ret = x509_cert_check_optional_crl(cacert, cacertlen, crl, crl_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return -1;
}
if (ret == 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return 0;
}
if (path_len > depth) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_depth);
return -1;
}
@@ -2027,16 +2046,19 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_cert_chain);
return -1;
}
if (path_len == 0) {
if ((ret = x509_cert_check_optional_ocsp(cert, certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
}
@@ -2050,28 +2072,34 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
rootcerts, rootcertslen, &cacert, &cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_trust_anchor);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_trust_anchor);
return -1;
}
if (x509_cert_check(cacert, cacertlen, X509_cert_ca) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (path_len > depth) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_depth);
return -1;
}
if (path_len == 0) {
if ((ret = x509_cert_check_optional_ocsp(cert, certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
}
@@ -2079,15 +2107,18 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type,
if (x509_certs_check_basic_constraints(cert_chain, cert_chain_len,
cacert, cacertlen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
if ((ret = x509_certs_check_name_constraints(cert_chain, cert_chain_len,
cacert, cacertlen)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
@@ -2115,6 +2146,8 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
int path_len = 0;
x509_verify_set_result(verify_result, X509_verify_ok);
switch (certs_type) {
case X509_cert_chain_server:
sign_cert_type = X509_cert_server_auth;
@@ -2122,50 +2155,61 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
break;
default:
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_from_der(&cert, &certlen, &certs, &certslen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_check(cert, certlen, sign_cert_type) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if ((ret = x509_cert_check_optional_crl(cert, certlen, crl, crl_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return -1;
}
if (ret == 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return 0;
}
// entity key encipherment cert
if (x509_cert_from_der(&kenc_cert, &kenc_certlen, &certs, &certslen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_check(kenc_cert, kenc_certlen, kenc_cert_type) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if ((ret = x509_cert_check_optional_crl(kenc_cert, kenc_certlen, crl, crl_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return -1;
}
if (ret == 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return 0;
}
if ((ret = x509_tlcp_cert_pair_entity_match(cert, certlen,
kenc_cert, kenc_certlen)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
@@ -2173,18 +2217,22 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
if (x509_cert_from_der(&cacert, &cacertlen, &certs, &certslen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (x509_cert_check(cacert, cacertlen, X509_cert_ca) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if ((ret = x509_cert_check_optional_crl(cacert, cacertlen, crl, crl_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return -1;
}
if (ret == 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_crl);
return 0;
}
@@ -2193,36 +2241,43 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
if (x509_cert_verify_by_ca_cert(kenc_cert, kenc_certlen, cacert, cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_cert_chain);
return -1;
}
}
if (path_len > depth) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_depth);
return -1;
}
if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_cert_chain);
return -1;
}
if (path_len == 0) {
if ((ret = x509_cert_check_optional_ocsp(cert, certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
if ((ret = x509_cert_check_optional_ocsp(kenc_cert, kenc_certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
}
@@ -2236,18 +2291,22 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
rootcerts, rootcertslen, &cacert, &cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_trust_anchor);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_trust_anchor);
return -1;
}
if (x509_cert_check(cacert, cacertlen, X509_cert_ca) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_certificate);
return -1;
}
if (path_len > depth) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_depth);
return -1;
}
@@ -2256,24 +2315,29 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
if (x509_cert_verify_by_ca_cert(kenc_cert, kenc_certlen, cacert, cacertlen,
SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_cert_chain);
return -1;
}
if ((ret = x509_cert_check_optional_ocsp(cert, certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
if ((ret = x509_cert_check_optional_ocsp(kenc_cert, kenc_certlen,
cacert, cacertlen, ocsp, ocsp_len)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_ocsp);
return 0;
}
}
@@ -2281,15 +2345,18 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
if (x509_certs_check_basic_constraints_tlcp(cert_chain, cert_chain_len,
cacert, cacertlen) != 1) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
if ((ret = x509_certs_check_name_constraints_tlcp(cert_chain, cert_chain_len,
cacert, cacertlen)) < 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
if (ret == 0) {
error_print();
x509_verify_set_result(verify_result, X509_verify_err_constraints);
return -1;
}
return 1;