From 35a3455693d6ff2d428cbf18bc5391d16e9d1dab Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Thu, 18 Jun 2026 23:11:23 +0800 Subject: [PATCH] Update root ca cert selection --- CMakeLists.txt | 2 +- include/gmssl/version.h | 2 +- include/gmssl/x509_ext.h | 9 ++- src/x509_cer.c | 48 ++++++++------- src/x509_ext.c | 122 +++++++++++++++++++++++++++++++++------ src/x509_vrf.c | 56 ++++-------------- tests/x509_exttest.c | 47 +++++++++++++++ 7 files changed, 196 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 84505909..9fe53e3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -820,7 +820,7 @@ endif() # set(CPACK_PACKAGE_NAME "GmSSL") set(CPACK_PACKAGE_VENDOR "GmSSL develop team") -set(CPACK_PACKAGE_VERSION "3.2.0-dev.1090") +set(CPACK_PACKAGE_VERSION "3.2.0-dev.1091") 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 799a64ac..459dfbf8 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.1090" +#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1091" 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 3ef10ac8..15907467 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -118,12 +118,12 @@ int x509_edi_party_name_print(FILE *fp, int fmt, int ind, const char *label, con /* GeneralName ::= CHOICE { - otherName [0] IMPLICIT OtherName, -- Only in GeneralName + otherName [0] IMPLICIT OtherName, -- constructed rfc822Name [1] IMPLICIT IA5String, dNSName [2] IMPLICIT IA5String, - x400Address [3] IMPLICIT ORAddress, - directoryName [4] IMPLICIT Name, -- SEQENCE OF - ediPartyName [5] IMPLICIT EDIPartyName, -- Only in GeneralName + x400Address [3] IMPLICIT ORAddress, -- constructed + directoryName [4] EXPLICIT Name, + ediPartyName [5] IMPLICIT EDIPartyName, -- constructed uniformResourceIdentifier [6] IMPLICIT IA5String, iPAddress [7] IMPLICIT OCTET STRING, -- 4 bytes or string? registeredID [8] IMPLICIT OBJECT IDENTIFIER } @@ -644,4 +644,3 @@ int x509_authority_info_access_print(FILE *fp, int fmt, int ind, const char *lab } #endif #endif - diff --git a/src/x509_cer.c b/src/x509_cer.c index 432050f4..7e1f2368 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -1902,8 +1902,8 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, size_t certlen; const uint8_t *cacert; size_t cacertlen; - const uint8_t *name; - size_t namelen; + int matched_root = 0; + int ret; int path_len = 0; int path_len_constraint; @@ -1967,31 +1967,37 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, path_len++; } - if (x509_cert_get_issuer(cert, certlen, &name, &namelen) != 1) { - error_print(); - return -1; - } // 函数提供了一组根证书,我们要从根证书中找到和被验证的证书链匹配的那个根证书 // 如果没有找到对应的根证书,那么就会出错 // 但是这个错误隐藏在这个函数中并不合适!这说明这个函数的接口有问题 // - if (x509_certs_get_cert_by_subject(rootcerts, rootcertslen, name, namelen, - &cacert, &cacertlen) != 1) { - error_print(); - return -1; + while (rootcertslen) { + if (x509_cert_from_der(&cacert, &cacertlen, &rootcerts, &rootcertslen) != 1) { + error_print(); + return -1; + } + if ((ret = x509_cert_is_signed_by_root_ca_cert(cert, certlen, cacert, cacertlen, + SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH)) < 0) { + error_print(); + return -1; + } + if (ret == 0) { + continue; + } + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + error_print(); + return -1; + } + if ((path_len_constraint >= 0 && path_len > path_len_constraint) + || path_len > depth) { + error_print(); + return -1; + } + matched_root = 1; + break; } - if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { - error_print(); - return -1; - } - if ((path_len_constraint >= 0 && path_len > path_len_constraint) - || path_len > depth) { - error_print(); - return -1; - } - if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, - SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) { + if (!matched_root) { error_print(); return -1; } diff --git a/src/x509_ext.c b/src/x509_ext.c index e95d65f0..1340c931 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -870,17 +870,43 @@ err: int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) { int ret; + const uint8_t *p; + size_t len; if (dlen == 0) { return 0; } switch (choice) { case X509_gn_other_name: + case X509_gn_edi_party_name: + if ((ret = asn1_type_to_der(ASN1_TAG_EXPLICIT(choice), d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + break; + case X509_gn_x400_address: + p = d; + len = dlen; + if (asn1_sequence_from_der(&d, &dlen, &p, &len) < 0) { + error_print(); + return -1; + } + if ((ret = asn1_type_to_der(ASN1_TAG_EXPLICIT(choice), d, dlen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + break; + case X509_gn_directory_name: + len = 0; + if (asn1_sequence_to_der(d, dlen, NULL, &len) != 1 + || asn1_explicit_header_to_der(choice, len, out, outlen) != 1 + || asn1_sequence_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + break; case X509_gn_rfc822_name: case X509_gn_dns_name: - case X509_gn_x400_address: - case X509_gn_directory_name: - case X509_gn_edi_party_name: case X509_gn_uniform_resource_identifier: case X509_gn_ip_address: case X509_gn_registered_id: @@ -900,20 +926,78 @@ int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, con { int ret; int tag; + const uint8_t *p; + size_t len; if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) { if (ret < 0) error_print(); return ret; } switch (tag) { - case ASN1_TAG_EXPLICIT(0): *choice = 0; break; - case ASN1_TAG_IMPLICIT(1): *choice = 1; break; - case ASN1_TAG_IMPLICIT(2): *choice = 2; break; - case ASN1_TAG_EXPLICIT(3): *choice = 3; break; - case ASN1_TAG_EXPLICIT(4): *choice = 4; break; - case ASN1_TAG_EXPLICIT(5): *choice = 5; break; - case ASN1_TAG_IMPLICIT(6): *choice = 6; break; - case ASN1_TAG_IMPLICIT(7): *choice = 7; break; - case ASN1_TAG_IMPLICIT(8): *choice = 8; break; + case ASN1_TAG_EXPLICIT(0): + *choice = 0; + if (*dlen && **d == ASN1_TAG_SEQUENCE) { + p = *d; + len = *dlen; + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + } + break; + case ASN1_TAG_IMPLICIT(1): + *choice = 1; + break; + case ASN1_TAG_IMPLICIT(2): + *choice = 2; + break; + case ASN1_TAG_IMPLICIT(3): + case ASN1_TAG_EXPLICIT(3): + *choice = 3; + if (*dlen && **d == ASN1_TAG_SEQUENCE) { + p = *d; + len = *dlen; + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + } + break; + case ASN1_TAG_IMPLICIT(4): + *choice = 4; + break; + case ASN1_TAG_EXPLICIT(4): + *choice = 4; + p = *d; + len = *dlen; + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + break; + case ASN1_TAG_EXPLICIT(5): + *choice = 5; + if (*dlen && **d == ASN1_TAG_SEQUENCE) { + p = *d; + len = *dlen; + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + } + break; + case ASN1_TAG_IMPLICIT(6): + *choice = 6; + break; + case ASN1_TAG_IMPLICIT(7): + *choice = 7; + break; + case ASN1_TAG_IMPLICIT(8): + *choice = 8; + break; default: fprintf(stderr, "%s %d: tag = %x\n", __FILE__, __LINE__, tag); error_print(); @@ -932,15 +1016,17 @@ int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int c switch (choice) { case 0: - case 3: case 4: case 5: - if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { - error_print(); - return -1; + if (dlen && *d == ASN1_TAG_SEQUENCE) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + d = p; + dlen = len; } - d = p; - dlen = len; } switch (choice) { case 0: return x509_other_name_print(fp, fmt, ind, "otherName", d, dlen); diff --git a/src/x509_vrf.c b/src/x509_vrf.c index 1f863797..a22b676e 100644 --- a/src/x509_vrf.c +++ b/src/x509_vrf.c @@ -62,48 +62,6 @@ static int x509_cert_get_authority_key_identifier_keyid(const uint8_t *cert, siz return 1; } -static int x509_general_names_match_directory_name(const uint8_t *general_names, size_t general_names_len, - const uint8_t *name, size_t name_len) -{ - int tag; - const uint8_t *general_name; - size_t general_name_len; - const uint8_t *directory_name; - size_t directory_name_len; - - if (!general_names || !general_names_len || !name || !name_len) { - error_print(); - return -1; - } - - while (general_names_len) { - if (asn1_any_type_from_der(&tag, &general_name, &general_name_len, - &general_names, &general_names_len) != 1) { - error_print(); - return -1; - } - if (tag == ASN1_TAG_IMPLICIT(X509_gn_directory_name)) { - directory_name = general_name; - directory_name_len = general_name_len; - if (x509_name_equ(directory_name, directory_name_len, name, name_len) == 1) { - return 1; - } - } else if (tag == ASN1_TAG_EXPLICIT(X509_gn_directory_name)) { - if (asn1_sequence_from_der(&directory_name, &directory_name_len, - &general_name, &general_name_len) != 1 - || asn1_length_is_zero(general_name_len) != 1) { - error_print(); - return -1; - } - if (x509_name_equ(directory_name, directory_name_len, name, name_len) == 1) { - return 1; - } - } - } - - return 0; -} - static int x509_cert_get_subject_key_identifier(const uint8_t *cert, size_t certlen, const uint8_t **keyid, size_t *keyid_len) { @@ -200,6 +158,8 @@ int x509_cert_is_signed_by_root_ca_cert(const uint8_t *cert, size_t certlen, size_t ski_len; const uint8_t *root_serial; size_t root_serial_len; + const uint8_t *directory_name; + size_t directory_name_len; int issuer_match; X509_KEY public_key; int ret; @@ -253,11 +213,19 @@ int x509_cert_is_signed_by_root_ca_cert(const uint8_t *cert, size_t certlen, // aki_issuer AKI 中的Issuer 是一个GeneralNames.directoryName == ROOTCACERT.subject - if ((ret = x509_general_names_match_directory_name(aki_issuer, aki_issuer_len, - subject, subject_len)) != 1) { + if ((ret = x509_general_names_get_first(aki_issuer, aki_issuer_len, NULL, + X509_gn_directory_name, &directory_name, &directory_name_len)) < 0) { if (ret) error_print(); return ret; } + if (ret == 0) { + return 0; + } + if ((issuer_match = x509_name_equ(directory_name, directory_name_len, + subject, subject_len)) != 1) { + if (issuer_match) error_print(); + return issuer_match; + } if (aki_serial_len != root_serial_len || memcmp(aki_serial, root_serial, root_serial_len) != 0) { diff --git a/tests/x509_exttest.c b/tests/x509_exttest.c index f4312016..3cdf7376 100644 --- a/tests/x509_exttest.c +++ b/tests/x509_exttest.c @@ -127,12 +127,47 @@ static int test_x509_general_name(void) uint8_t name[512]; size_t namelen; uint32_t reg_id[] = { 2,4,6,8 }; + uint8_t other_name[256]; + uint8_t *other_name_p = other_name; + const uint8_t *other_name_cp = other_name; + const uint8_t *other_name_content; + size_t other_name_len = 0; + size_t other_name_content_len; + uint8_t edi_party_name[256]; + uint8_t *edi_party_name_p = edi_party_name; + const uint8_t *edi_party_name_cp = edi_party_name; + const uint8_t *edi_party_name_content; + size_t edi_party_name_len = 0; + size_t edi_party_name_content_len; + uint8_t general_name[512]; + uint8_t *general_name_p = general_name; + size_t general_name_len = 0; + const uint8_t *gn; + size_t gn_len; if (x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "CA") != 1) { error_print(); return -1; } + if (x509_other_name_to_der(other_id, cnt(other_id), value, sizeof(value), + &other_name_p, &other_name_len) != 1 + || asn1_sequence_from_der(&other_name_content, &other_name_content_len, + &other_name_cp, &other_name_len) != 1 + || asn1_length_is_zero(other_name_len) != 1 + || x509_edi_party_name_to_der( + ASN1_TAG_PrintableString, (uint8_t *)"Assigner", strlen("Assigner"), + ASN1_TAG_PrintableString, (uint8_t *)"PartyName", strlen("PartyName"), + &edi_party_name_p, &edi_party_name_len) != 1 + || asn1_sequence_from_der(&edi_party_name_content, &edi_party_name_content_len, + &edi_party_name_cp, &edi_party_name_len) != 1 + || asn1_length_is_zero(edi_party_name_len) != 1 + || x509_general_name_to_der(X509_gn_directory_name, name, namelen, + &general_name_p, &general_name_len) != 1 + || general_name[0] != ASN1_TAG_EXPLICIT(X509_gn_directory_name)) { + error_print(); + return -1; + } gnslen = 0; if (0 || x509_general_names_add_other_name(gns, &gnslen, sizeof(gns), other_id, cnt(other_id), value, sizeof(value)) != 1 @@ -153,6 +188,18 @@ static int test_x509_general_name(void) return -1; } x509_general_names_print(stderr, 0, 0, "GeneralNames", d, dlen); + if (x509_general_names_get_first(d, dlen, NULL, X509_gn_other_name, &gn, &gn_len) != 1 + || gn_len != other_name_content_len + || memcmp(gn, other_name_content, gn_len) != 0 + || x509_general_names_get_first(d, dlen, NULL, X509_gn_directory_name, &gn, &gn_len) != 1 + || gn_len != namelen + || memcmp(gn, name, namelen) != 0 + || x509_general_names_get_first(d, dlen, NULL, X509_gn_edi_party_name, &gn, &gn_len) != 1 + || gn_len != edi_party_name_content_len + || memcmp(gn, edi_party_name_content, gn_len) != 0) { + error_print(); + return -1; + } { size_t i; printf("uint8_t general_names[%zu] = {", dlen);