diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b176080..6e81ae34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/include/gmssl/version.h b/include/gmssl/version.h index 6e0dce8d..8adb0efe 100644 --- a/include/gmssl/version.h +++ b/include/gmssl/version.h @@ -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); diff --git a/include/gmssl/x509_cer.h b/include/gmssl/x509_cer.h index 8b02ecfa..a93e3caf 100644 --- a/include/gmssl/x509_cer.h +++ b/include/gmssl/x509_cer.h @@ -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); diff --git a/src/tlcp.c b/src/tlcp.c index 056d82aa..711dd388 100644 --- a/src/tlcp.c +++ b/src/tlcp.c @@ -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); diff --git a/src/tls12.c b/src/tls12.c index 6118cc3b..6b41c17a 100644 --- a/src/tls12.c +++ b/src/tls12.c @@ -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) { diff --git a/src/tls13.c b/src/tls13.c index beba8130..937cd7e5 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -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, diff --git a/src/x509_cer.c b/src/x509_cer.c index 9624869f..55539baa 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -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;