From 58c0bca3a29af1e8038e07add592bcbaa45fc143 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sun, 5 Feb 2023 23:10:31 +0800 Subject: [PATCH] Update X509 --- include/gmssl/file.h | 1 + src/http.c | 10 ++++- src/x509_crl.c | 81 +++++++++++++++++++----------------- src/x509_ext.c | 97 ++++++++++++++++++++++++++++++-------------- tests/x509_exttest.c | 21 +++++----- 5 files changed, 131 insertions(+), 79 deletions(-) diff --git a/include/gmssl/file.h b/include/gmssl/file.h index 1165e5be..435c37c6 100644 --- a/include/gmssl/file.h +++ b/include/gmssl/file.h @@ -12,6 +12,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/src/http.c b/src/http.c index f0e5afbc..8c2b7a23 100644 --- a/src/http.c +++ b/src/http.c @@ -74,14 +74,19 @@ int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *con error_print(); return -1; } - if (!(p = strnstr(buf, "\r\n\r\n", buflen))) { + if (buf[buflen] != 0) { + error_print(); + return -1; + } + if (!(p = strstr(buf, "\r\n\r\n"))) { error_print(); return -1; } *content = (uint8_t *)(p + 4); headerlen = *content - (uint8_t *)buf; + *p = 0; - if (!(p = strnstr(buf, "\r\nContent-Length: ", headerlen))) { + if (!(p = strstr(buf, "\r\nContent-Length: "))) { error_print(); return -1; } @@ -154,6 +159,7 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen) error_print(); goto end; } + response[len] = 0; // process response header and retrieve left if (http_parse_response(response, len, &p, contentlen, &left) != 1) { diff --git a/src/x509_crl.c b/src/x509_crl.c index 6358cb3c..34cfd966 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -1029,7 +1029,6 @@ err: return -1; } -// 这类函数应该支持返回0,也就是没有加入数据,这样就不用检查输入是否为空了 int x509_crl_exts_add_authority_key_identifier( uint8_t *exts, size_t *extslen, size_t maxlen, int critical, @@ -1037,14 +1036,11 @@ int x509_crl_exts_add_authority_key_identifier( const uint8_t *issuer, size_t issuer_len, const uint8_t *serial, size_t serial_len) { - if (!keyid || !keyid_len) { - error_print(); - return -1; - } - if (x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, - keyid, keyid_len, issuer, issuer_len, serial, serial_len) != 1) { - error_print(); - return -1; + int ret; + if ((ret = x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, + keyid, keyid_len, issuer, issuer_len, serial, serial_len)) != 1) { + if (ret < 0) error_print(); + return ret; } return 1; } @@ -1052,9 +1048,10 @@ int x509_crl_exts_add_authority_key_identifier( int x509_crl_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, const SM2_KEY *public_key) { - if (x509_exts_add_default_authority_key_identifier(exts, extslen, maxlen, public_key) != 1) { - error_print(); - return -1; + int ret; + if ((ret = x509_exts_add_default_authority_key_identifier(exts, extslen, maxlen, public_key)) != 1) { + if (ret < 0) error_print(); + return ret; } return 1; } @@ -1064,9 +1061,10 @@ int x509_crl_exts_add_issuer_alt_name( int critical, const uint8_t *d, size_t dlen) { - if (x509_exts_add_issuer_alt_name(exts, extslen, maxlen, critical, d, dlen) != 1) { - error_print(); - return -1; + int ret; + if ((ret = x509_exts_add_issuer_alt_name(exts, extslen, maxlen, critical, d, dlen)) != 1) { + if (ret < 0) error_print(); + return ret; } return 1; } @@ -1135,27 +1133,34 @@ int x509_crl_exts_add_issuing_distribution_point( int only_contains_attr_certs) { int oid = OID_ce_issuing_distribution_point; + int ret; size_t curlen = *extslen; uint8_t val[512]; size_t vlen = 0; uint8_t *p = val; size_t len = 0; + if ((ret = x509_issuing_distribution_point_to_der( + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, NULL, &len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (len > sizeof(val)) { + error_print(); + return -1; + } if (x509_issuing_distribution_point_to_der( - dist_point_uri, dist_point_uri_len, - only_contains_user_certs, - only_contains_ca_certs, - only_some_reasons, - indirect_crl, - only_contains_attr_certs, NULL, &len) != 1 - || asn1_length_le(len, sizeof(val)) != 1 - || x509_issuing_distribution_point_to_der( - dist_point_uri, dist_point_uri_len, - only_contains_user_certs, - only_contains_ca_certs, - only_some_reasons, - indirect_crl, - only_contains_attr_certs, &p, &vlen) != 1) { + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, &p, &vlen) != 1) { error_print(); return -1; } @@ -1174,10 +1179,11 @@ int x509_crl_exts_add_freshest_crl( const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) { int oid = OID_ce_freshest_crl; - if (x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, - oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen) != 1) { - error_print(); - return -1; + int ret; + if ((ret = x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, + oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen)) != 1) { + if (ret < 0) error_print(); + return ret; } return 1; } @@ -1186,10 +1192,11 @@ int x509_crl_exts_add_authority_info_acess( uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const char *ca_issuers_uri, size_t ca_issuers_urilen, const char *ocsp_uri, size_t ocsp_urilen) { - if (x509_exts_add_authority_info_access(exts, extslen, maxlen, critical, - ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen) != 1) { - error_print(); - return -1; + int ret; + if ((ret = x509_exts_add_authority_info_access(exts, extslen, maxlen, critical, + ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen)) != 1) { + if (ret < 0) error_print(); + return ret; } return 1; } diff --git a/src/x509_ext.c b/src/x509_ext.c index 6e992dcb..841d5be7 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -195,6 +195,9 @@ int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen, { size_t curlen = *extslen; + if (dlen == 0) { + return 0; + } exts += *extslen; if (x509_ext_to_der_ex(oid, critical, d, dlen, NULL, &curlen) != 1 || asn1_length_le(curlen, maxlen) != 1 @@ -218,6 +221,9 @@ int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_ size_t vlen = 0; size_t len = 0; + if (keyid_len == 0 && issuer_len == 0 && serial_len == 0) { + return 0; + } exts += *extslen; if (x509_authority_key_identifier_to_der( keyid, keyid_len, @@ -246,6 +252,9 @@ int x509_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extsle uint8_t id[32]; int critical = -1; + if (!public_key) { + return 0; + } sm2_point_to_uncompressed_octets(&public_key->public_key, buf); sm3_digest(buf, sizeof(buf), id); @@ -266,6 +275,9 @@ int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t uint8_t *p = val; size_t vlen = 0; + if (dlen == 0) { + return 0; + } if (dlen < X509_SUBJECT_KEY_IDENTIFIER_MIN_LEN || dlen > X509_SUBJECT_KEY_IDENTIFIER_MAX_LEN) { error_print(); @@ -289,6 +301,9 @@ int x509_exts_add_subject_key_identifier_ex(uint8_t *exts, size_t *extslen, size uint8_t buf[65]; uint8_t id[32]; + if (!subject_key) { + return 0; + } sm2_point_to_uncompressed_octets(&subject_key->public_key, buf); sm3_digest(buf, sizeof(buf), id); @@ -307,8 +322,11 @@ int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int c uint8_t *p = val; size_t vlen = 0; + if (bits == -1) { + return 0; + } if (!bits) { - // TODO: 检查是否在合法范围内 + // TODO: 检查是否在合法范围内 error_print(); return -1; } @@ -371,6 +389,9 @@ int x509_exts_add_name_constraints(uint8_t *exts, size_t *extslen, size_t maxlen size_t vlen = 0; size_t len = 0; + if (permitted_subtrees_len == 0 && excluded_subtrees_len == 0) { + return 0; + } exts += *extslen; if (x509_name_constraints_to_der( permitted_subtrees, permitted_subtrees_len, @@ -399,6 +420,9 @@ int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxl uint8_t *p = val; size_t vlen = 0; + if (require_explicit_policy == -1 && inhibit_policy_mapping == -1) { + return 0; + } exts += *extslen; if (x509_policy_constraints_to_der( require_explicit_policy, @@ -422,6 +446,9 @@ int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxle uint8_t *p = val; size_t vlen = 0; + if (ca == -1 && path_len_constraint == -1) { + return 0; + } exts += *extslen; if (x509_basic_constraints_to_der(ca, path_len_constraint, &p, &vlen) != 1 || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 @@ -443,6 +470,9 @@ int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, size_t vlen = 0; size_t len = 0; + if (key_purposes_cnt == 0) { + return 0; + } exts += *extslen; if (x509_ext_key_usage_to_der(key_purposes, key_purposes_cnt, NULL, &len) != 1 || asn1_length_le(len, sizeof(val)) != 1 @@ -465,6 +495,9 @@ int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, siz size_t vlen = 0; size_t len = 0; + if (urilen == 0 && ldap_urilen == 0) { + return 0; + } if (x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, NULL, &len) != 1 || asn1_length_le(len, sizeof(val)) != 1 || x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, &p, &vlen) != 1) { @@ -502,6 +535,9 @@ int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxl uint8_t *p = val; size_t vlen = 0; + if (skip_certs == -1) { + return 0; + } exts += *extslen; if (x509_inhibit_any_policy_to_der(skip_certs, &p, &vlen) != 1 || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 @@ -513,16 +549,11 @@ int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxl return 1; } -// 是否支持输入为空,这样返回0?我感觉这是一个比较高层的API,可能被应用直接调用,还是做严格检查比较好 int x509_exts_add_freshest_crl(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen) { int oid = OID_ce_freshest_crl; - if (x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen) != 1) { - error_print(); - return -1; - } - return 1; + return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); } int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid, @@ -738,12 +769,16 @@ int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t if (dlen == 0) { return 0; } - switch (choice) { + case X509_gn_other_name: 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: if ((ret = asn1_implicit_to_der(choice, d, dlen, out, outlen)) != 1) { if (ret < 0) error_print(); return ret; @@ -858,7 +893,7 @@ int x509_general_names_add_other_name(uint8_t *gns, size_t *gnslen, size_t maxle const uint8_t *value, size_t value_len) { int choice = X509_gn_other_name; - uint8_t buf[128]; + uint8_t buf[256]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; @@ -879,7 +914,7 @@ int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t m int party_name_tag, const uint8_t *party_name, size_t party_name_len) { int choice = X509_gn_edi_party_name; - uint8_t buf[128]; + uint8_t buf[256]; uint8_t *p = buf; const uint8_t *cp = buf; size_t len = 0; @@ -902,7 +937,7 @@ int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t ma const uint32_t *nodes, size_t nodes_cnt) { int choice = X509_gn_registered_id; - uint8_t d[128]; + uint8_t d[64]; size_t dlen; if (asn1_object_identifier_to_octets(nodes, nodes_cnt, d, &dlen) != 1 @@ -1031,6 +1066,7 @@ int x509_authority_key_identifier_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; + if (keyid_len == 0 && issuer_len == 0 && serial_len == 0) { return 0; } @@ -1603,8 +1639,7 @@ int x509_policy_mapping_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; - if (issuer_policy_nodes_cnt == 0 - && subject_policy_nodes_cnt == 0) { + if (issuer_policy_oid == -1 && subject_policy_oid == -1) { return 0; } if (x509_cert_policy_id_to_der(issuer_policy_oid, @@ -1767,6 +1802,11 @@ int x509_attributes_print(FILE *fp, int fmt, int ind, const char *label, const u int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen) { size_t len = 0; + + if (ca == -1 && path_len_cons == -1) { + error_print(); + return -1; + } if (asn1_boolean_to_der(ca, NULL, &len) < 0 || asn1_int_to_der(path_len_cons, NULL, &len) < 0 || asn1_sequence_header_to_der(len, out, outlen) != 1 @@ -1786,12 +1826,12 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t * if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); + else *ca = *path_len_cons = -1; return ret; } - if (!d || !dlen) { - *ca = -1; - *path_len_cons = -1; - return 1; + if (dlen == 0) { + error_print(); + return -1; } if (asn1_boolean_from_der(ca, &d, &dlen) < 0 || asn1_int_from_der(path_len_cons, &d, &dlen) < 0 @@ -1799,15 +1839,9 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t * error_print(); return -1; } - if (*ca < 0 && *path_len_cons < 0) { - error_print(); - return -1; - } - // from_der() MUST NOT set default value to *ca return 1; } - // 这个函数原型可能要改一下 int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type) { @@ -2029,6 +2063,11 @@ int x509_policy_constraints_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; + + if (require_explicit_policy == -1 && inhibit_policy_mapping == -1) { + error_print(); + return -1; + } if (asn1_implicit_int_to_der(0, require_explicit_policy, NULL, &len) < 0 || asn1_implicit_int_to_der(1, inhibit_policy_mapping, NULL, &len) < 0 || asn1_sequence_header_to_der(len, out, outlen) != 1 @@ -2051,10 +2090,13 @@ int x509_policy_constraints_from_der( if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); + else *require_explicit_policy = *inhibit_policy_mapping = -1; return ret; } - *require_explicit_policy = -1; - *inhibit_policy_mapping = -1; + if (dlen == 0) { + error_print(); + return -1; + } if (asn1_implicit_int_from_der(0, require_explicit_policy, &d, &dlen) < 0 || asn1_implicit_int_from_der(1, inhibit_policy_mapping, &d, &dlen) < 0 || asn1_length_is_zero(dlen) != 1) { @@ -2917,11 +2959,6 @@ int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t m size_t vlen = 0; size_t len = 0; - // Conforming CAs MUST mark this extension as non-critical. - if (critical == 1) { - error_print(); - return -1; - } if (x509_authority_info_access_to_der(ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen, NULL, &len) != 1 || asn1_length_le(len, sizeof(val)) != 1 || x509_authority_info_access_to_der(ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen, &p, &vlen) != 1) { diff --git a/tests/x509_exttest.c b/tests/x509_exttest.c index 9a350170..a202b58d 100644 --- a/tests/x509_exttest.c +++ b/tests/x509_exttest.c @@ -136,7 +136,8 @@ static int test_x509_general_name(void) return -1; } gnslen = 0; - if (x509_general_names_add_other_name(gns, &gnslen, sizeof(gns), other_id, cnt(other_id), value, sizeof(value)) != 1 + if (0 + || x509_general_names_add_other_name(gns, &gnslen, sizeof(gns), other_id, cnt(other_id), value, sizeof(value)) != 1 || x509_general_names_add_rfc822_name(gns, &gnslen, sizeof(gns), "guan@pku.edu.cn") != 1 || x509_general_names_add_dns_name(gns, &gnslen, sizeof(gns), "www.pku.edu.cn") != 1 || x509_general_names_add_x400_address(gns, &gnslen, sizeof(gns), x400, sizeof(x400)) != 1 @@ -503,8 +504,8 @@ static int test_x509_basic_constraints(void) cp = p = buf; len = 0; - if (x509_basic_constraints_to_der(-1, -1, &p, &len) != 1 - || asn1_sequence_from_der(&d, &dlen, &cp, &len) != -1 // empty sequence is not allowed + if (x509_basic_constraints_to_der(-1, -1, &p, &len) != -1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 0 // empty sequence is not allowed || asn1_length_is_zero(len) != 1) { error_print(); return -1; @@ -524,7 +525,7 @@ static int test_x509_basic_constraints(void) cp = p = buf; len = 0; if (x509_basic_constraints_to_der(-1, 4, &p, &len) != 1 || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 1 - || asn1_check(ca == 0) != 1 + || asn1_check(ca == -1) != 1 || asn1_check(path == 4) != 1 || asn1_length_is_zero(len) != 1) { error_print(); @@ -532,8 +533,8 @@ static int test_x509_basic_constraints(void) } cp = p = buf; len = 0; - if (x509_basic_constraints_to_der(-1, -1, &p, &len) != 1 // should return error - || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != -1) { + if (x509_basic_constraints_to_der(-1, -1, &p, &len) != -1 // should return error + || x509_basic_constraints_from_der(&ca, &path, &cp, &len) != 0) { error_print(); return -1; } @@ -649,10 +650,10 @@ static int test_x509_policy_constraints(void) cp = p = buf; len = 0; val1 = val2 = 99; - if (x509_policy_constraints_to_der(-1, -1, &p, &len) != 1 - || x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != -1 // empty sequence is not allowed - // || asn1_check(val1 == -1) != 1 - // || asn1_check(val2 == -1) != 1 + if (x509_policy_constraints_to_der(-1, -1, &p, &len) != -1 + || x509_policy_constraints_from_der(&val1, &val2, &cp, &len) != 0 // empty sequence is not allowed + || asn1_check(val1 == -1) != 1 + || asn1_check(val2 == -1) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1;