From 1bf47fea14b0ba31cc08bab30c7a131089cf6ab0 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Wed, 17 Jun 2026 09:14:03 +0800 Subject: [PATCH] Add x.509 ext critical check --- CMakeLists.txt | 2 +- include/gmssl/version.h | 2 +- include/gmssl/x509_ext.h | 1 + src/x509_ext.c | 42 ++++++++++++++++++++++++++++++++++++++-- 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2e58bc37..f4457e3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -818,7 +818,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.2.0-dev.1070") +set(CPACK_PACKAGE_VERSION "3.2.0-dev.1071") 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 bb1ae3ac..b72df3b4 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.1070" +#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1071" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/include/gmssl/x509_ext.h b/include/gmssl/x509_ext.h index 1695bcac..3ef10ac8 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -605,6 +605,7 @@ NetscapeCertComment ::= IA5String */ int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits); +int x509_ext_check_critical(int oid, int is_ca, int critical); int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, int *path_len_constraints); diff --git a/src/x509_ext.c b/src/x509_ext.c index 131c0284..e95d65f0 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -72,7 +72,6 @@ static const ASN1_OID_INFO x509_ext_ids[] = { { OID_pe_authority_info_access, "AuthorityInformationAccess", oid_pe_authority_info_access, sizeof(oid_pe_authority_info_access)/sizeof(int) }, { OID_ct_precertificate_scts, "CT-PrecertificateSCTs", oid_ct_precertificate_scts, sizeof(oid_ct_precertificate_scts)/sizeof(int) }, }; - static const int x509_ext_ids_count = sizeof(x509_ext_ids)/sizeof(x509_ext_ids[0]); @@ -127,6 +126,41 @@ int x509_ext_id_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uin return 1; } +typedef struct { + int oid; + int only_critical_for_ca_certs; +} X509_EXT_CRITICAL; + +#define X509_EXT_ONLY_CRITICAL_FOR_CA_CERTS 1 + +static const X509_EXT_CRITICAL x509_ext_critical[] = { + { OID_ce_basic_constraints, X509_EXT_ONLY_CRITICAL_FOR_CA_CERTS }, + { OID_ce_name_constraints, 0 }, + { OID_ce_policy_constraints, 0 }, + { OID_ce_inhibit_any_policy, 0 }, +}; +static const size_t x509_ext_critical_cnt = + sizeof(x509_ext_critical)/sizeof(x509_ext_critical[0]); + +int x509_ext_check_critical(int oid, int is_ca, int critical) +{ + size_t i; + + for (i = 0; i < x509_ext_critical_cnt; i++) { + if (oid == x509_ext_critical[i].oid) { + if (x509_ext_critical[i].only_critical_for_ca_certs && !is_ca) { + return 1; + } + if (critical != X509_critical) { + error_print(); + return -1; + } + return 1; + } + } + return 1; +} + int x509_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen) { size_t len = 0; @@ -2839,6 +2873,7 @@ int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, int key_usage; int ext_key_usages[X509_MAX_KEY_PURPOSES]; size_t ext_key_usages_cnt; + int is_ca = (cert_type == X509_cert_ca || cert_type == X509_cert_root_ca) ? 1 : 0; *path_len_constraint = -1; @@ -2847,6 +2882,10 @@ int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, error_print(); return -1; } + if (x509_ext_check_critical(oid, is_ca, critical) != 1) { + error_print(); + return -1; + } switch (oid) { case OID_ce_authority_key_identifier: @@ -2935,7 +2974,6 @@ int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type, case OID_ce_crl_distribution_points: case OID_ce_inhibit_any_policy: case OID_ce_freshest_crl: - break; default: if (critical == X509_critical) {