From 545ea46fdb4066df3aec064a5d69b4ebb99f7235 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Fri, 19 Jun 2026 08:17:04 +0800 Subject: [PATCH] Update X509 name --- CMakeLists.txt | 2 +- include/gmssl/asn1.h | 10 +- include/gmssl/version.h | 2 +- src/x509_vrf.c | 539 +++++++++++++++++----------------------- tests/asn1test.c | 72 +++--- 5 files changed, 283 insertions(+), 342 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bded0f22..ad39d7b7 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.1094") +set(CPACK_PACKAGE_VERSION "3.2.0-dev.1095") set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md) set(CPACK_NSIS_MODIFY_PATH ON) include(CPack) diff --git a/include/gmssl/asn1.h b/include/gmssl/asn1.h index 4381f97e..fabcab55 100644 --- a/include/gmssl/asn1.h +++ b/include/gmssl/asn1.h @@ -214,7 +214,7 @@ int asn1_oid_info_from_der(const ASN1_OID_INFO **info, #define asn1_implicit_enumerated_from_der(i,val,in,inlen) asn1_int_from_der_ex(ASN1_TAG_IMPLICIT(i),val,in,inlen) int asn1_string_is_utf8_string(const char *d, size_t dlen); -int asn1_utf8_string_next_code_point(const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point); +int asn1_utf8_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen); int asn1_utf8_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); #define asn1_utf8_string_to_der(d,dlen,out,outlen) asn1_utf8_string_to_der_ex(ASN1_TAG_UTF8String,d,dlen,out,outlen) @@ -223,7 +223,7 @@ int asn1_utf8_string_from_der_ex(int tag, const char **d, size_t *dlen, const ui #define asn1_implicit_utf8_string_from_der(i,d,dlen,in,inlen) asn1_utf8_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) int asn1_string_is_printable_string(const char *d, size_t dlen); -int asn1_printable_string_next_code_point(const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point); +int asn1_printable_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen); int asn1_printable_string_case_ignore_match(const char *a, size_t alen, const char *b, size_t blen); int asn1_printable_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); int asn1_printable_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); @@ -233,7 +233,7 @@ int asn1_printable_string_from_der_ex(int tag, const char **d, size_t *dlen, con #define asn1_implicit_printable_string_from_der(i,d,dlen,in,inlen) asn1_printable_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) int asn1_string_is_ia5_string(const char *d, size_t dlen); -int asn1_ia5_string_next_code_point(const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point); +int asn1_ia5_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen); int asn1_ia5_string_to_der_ex(int tag, const char *d, size_t dlen, uint8_t **out, size_t *outlen); int asn1_ia5_string_from_der_ex(int tag, const char **d, size_t *dlen, const uint8_t **in, size_t *inlen); #define asn1_ia5_string_to_der(d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IA5String,d,dlen,out,outlen) @@ -241,8 +241,8 @@ int asn1_ia5_string_from_der_ex(int tag, const char **d, size_t *dlen, const uin #define asn1_implicit_ia5_string_to_der(i,d,dlen,out,outlen) asn1_ia5_string_to_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,out,outlen) #define asn1_implicit_ia5_string_from_der(i,d,dlen,in,inlen) asn1_ia5_string_from_der_ex(ASN1_TAG_IMPLICIT(i),d,dlen,in,inlen) -int asn1_bmp_string_next_code_point(const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point); -int asn1_universal_string_next_code_point(const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point); +int asn1_bmp_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen); +int asn1_universal_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen); int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen); diff --git a/include/gmssl/version.h b/include/gmssl/version.h index 2d6ed17b..64a3b7b3 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.1094" +#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1095" int gmssl_version_num(void); const char *gmssl_version_str(void); diff --git a/src/x509_vrf.c b/src/x509_vrf.c index 100e8de9..a8ddee8e 100644 --- a/src/x509_vrf.c +++ b/src/x509_vrf.c @@ -20,7 +20,7 @@ -static int x509_cert_get_authority_key_identifier_keyid(const uint8_t *cert, size_t certlen, +static int x509_cert_get_authority_key_identifier(const uint8_t *cert, size_t certlen, const uint8_t **keyid, size_t *keyid_len, const uint8_t **issuer, size_t *issuer_len, const uint8_t **serial, size_t *serial_len) @@ -115,12 +115,14 @@ static int x509_signed_is_verified_by_key(const uint8_t *a, size_t alen, error_print(); return -1; } - if (x509_key_get_sign_algor(key, &key_sig_alg) != 1) { + if (x509_signed_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { error_print(); return -1; } - if (x509_signed_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 1 - || asn1_length_is_zero(alen) != 1) { + + // FIXME: 改为 x509_key_support_algor + if (x509_key_get_sign_algor(key, &key_sig_alg) != 1) { error_print(); return -1; } @@ -128,6 +130,8 @@ static int x509_signed_is_verified_by_key(const uint8_t *a, size_t alen, return 0; } + + // X509_sign/verify 还是默认就使用SM2的默认ID吧 if (key->algor == OID_ec_public_key && key->algor_param == OID_sm2) { sign_args = (uint8_t *)signer_id; sign_argslen = signer_id_len; @@ -140,6 +144,7 @@ static int x509_signed_is_verified_by_key(const uint8_t *a, size_t alen, return 1; } +// 其实只要把验证签名的步骤拿出来,就可以重用已有的函数 int x509_cert_is_signed_by_root_ca_cert(const uint8_t *cert, size_t certlen, const uint8_t *rootcacert, size_t rootcacertlen, const char *signer_id, size_t signer_id_len) @@ -182,7 +187,7 @@ int x509_cert_is_signed_by_root_ca_cert(const uint8_t *cert, size_t certlen, } // if AKI not exist - if ((ret = x509_cert_get_authority_key_identifier_keyid(cert, certlen, + if ((ret = x509_cert_get_authority_key_identifier(cert, certlen, &aki, &aki_len, &aki_issuer, &aki_issuer_len, &aki_serial, &aki_serial_len)) < 0) { error_print(); return -1; @@ -241,6 +246,9 @@ int x509_cert_is_signed_by_root_ca_cert(const uint8_t *cert, size_t certlen, error_print(); return -1; } + + // 最后才是verify + // 可以修改一下 x509_signed_verify_ex ,验证失败不都显式打印错误。 return x509_signed_is_verified_by_key(cert, certlen, &public_key, signer_id, signer_id_len); } @@ -371,60 +379,57 @@ static int x509_general_names_check(const uint8_t *d, size_t dlen) int x509_cert_check_subject(const uint8_t *cert, size_t certlen, int cert_type) { - int ret; - int is_cacert; + int has_subject; const uint8_t *subject; size_t subject_len; - const uint8_t *exts; - size_t extslen; - const uint8_t *val; - size_t vlen; - const uint8_t *gns; - size_t gnslen; - int critical; if (!cert || !certlen) { error_print(); return -1; } - switch (cert_type) { - case X509_cert_server_auth: - case X509_cert_client_auth: - case X509_cert_server_key_encipher: - case X509_cert_client_key_encipher: - is_cacert = 0; - break; - case X509_cert_ca: - case X509_cert_root_ca: - case X509_cert_crl_sign: - is_cacert = 1; - break; - default: - error_print(); - return -1; - } - if (x509_cert_get_subject(cert, certlen, &subject, &subject_len) != 1) { error_print(); return -1; } - if ((ret = x509_name_check(subject, subject_len)) < 0) { + if ((has_subject = x509_name_check(subject, subject_len)) < 0) { error_print(); return -1; } - if (ret == 0) { - if (is_cacert) { + if (!has_subject) { + int is_cacert; + const uint8_t *exts; + size_t extslen; + int critical; + const uint8_t *val; + size_t vlen; + const uint8_t *gns; + size_t gnslen; + + switch (cert_type) { + case X509_cert_server_auth: + case X509_cert_client_auth: + case X509_cert_server_key_encipher: + case X509_cert_client_key_encipher: + is_cacert = 0; + break; + case X509_cert_ca: + case X509_cert_root_ca: + case X509_cert_crl_sign: + is_cacert = 1; + break; + default: error_print(); return -1; } - if (x509_cert_get_exts(cert, certlen, &exts, &extslen) != 1) { + if (is_cacert) { error_print(); return -1; } - if (x509_exts_get_ext_by_oid(exts, extslen, OID_ce_subject_alt_name, &critical, &val, &vlen) != 1) { + if (x509_cert_get_exts(cert, certlen, &exts, &extslen) != 1 + || x509_exts_get_ext_by_oid(exts, extslen, OID_ce_subject_alt_name, &critical, &val, &vlen) != 1) { error_print(); return -1; } @@ -443,153 +448,122 @@ int x509_cert_check_subject(const uint8_t *cert, size_t certlen, int cert_type) return 1; } -static int x509_name_string_char_from_bytes(int tag, const uint8_t **in, size_t *inlen, uint32_t *ch) +static int x509_name_string_char_from_bytes(int tag, uint32_t *ch, const uint8_t **in, size_t *inlen) { - int ret = 1; - const uint8_t *p; - size_t len; + int ret; if (!in || !*in || !inlen || !ch) { error_print(); return -1; } - p = *in; - len = *inlen; - - if (len == 0) { - ret = 0; - } else { - switch (tag) { - case ASN1_TAG_TeletexString: - *ch = p[0]; - p++; - len--; - break; - case ASN1_TAG_PrintableString: - if (asn1_printable_string_next_code_point(*in, *inlen, &p, ch) != 1) { - error_print(); - return -1; - } - len = *inlen - (size_t)(p - *in); - break; - case ASN1_TAG_IA5String: - if (asn1_ia5_string_next_code_point(*in, *inlen, &p, ch) != 1) { - error_print(); - return -1; - } - len = *inlen - (size_t)(p - *in); - break; - case ASN1_TAG_UTF8String: - if (asn1_utf8_string_next_code_point(*in, *inlen, &p, ch) != 1) { - error_print(); - return -1; - } - len = *inlen - (size_t)(p - *in); - break; - case ASN1_TAG_BMPString: - if (asn1_bmp_string_next_code_point(*in, *inlen, &p, ch) != 1) { - error_print(); - return -1; - } - len = *inlen - (size_t)(p - *in); - break; - case ASN1_TAG_UniversalString: - if (asn1_universal_string_next_code_point(*in, *inlen, &p, ch) != 1) { - error_print(); - return -1; - } - len = *inlen - (size_t)(p - *in); - break; - default: - ret = 0; - break; - } - } - - if (ret == 1) { - *in = p; - *inlen = len; - } - return ret; -} - -static int x509_name_string_next_normalized_code_point(int tag, - const uint8_t *str, size_t len, const uint8_t **ptr, uint32_t *code_point) -{ - int ret; - const uint8_t *p; - const uint8_t *q; - const uint8_t *end; - size_t qlen; - uint32_t ch; - - if (!ptr || !code_point || (!str && len)) { - error_print(); - return -1; - } - if (!str) { - if (*ptr) { - error_print(); - return -1; - } + if (*inlen == 0) { return 0; } - end = str + len; - p = *ptr ? *ptr : str; - if (p < str || p > end) { + switch (tag) { + case ASN1_TAG_TeletexString: + *ch = *(*in)++; + (*inlen)--; + ret = 1; + break; + case ASN1_TAG_PrintableString: + if ((ret = asn1_printable_string_code_point_from_bytes(ch, in, inlen)) < 0) { + error_print(); + return -1; + } + break; + case ASN1_TAG_IA5String: + if ((ret = asn1_ia5_string_code_point_from_bytes(ch, in, inlen)) < 0) { + error_print(); + return -1; + } + break; + case ASN1_TAG_UTF8String: + if ((ret = asn1_utf8_string_code_point_from_bytes(ch, in, inlen)) < 0) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if ((ret = asn1_bmp_string_code_point_from_bytes(ch, in, inlen)) < 0) { + error_print(); + return -1; + } + break; + case ASN1_TAG_UniversalString: + if ((ret = asn1_universal_string_code_point_from_bytes(ch, in, inlen)) < 0) { + error_print(); + return -1; + } + break; + default: error_print(); return -1; } - while (p < end) { - q = p; - qlen = (size_t)(end - q); - if ((ret = x509_name_string_char_from_bytes(tag, &q, &qlen, &ch)) != 1) { - if (ret == 0) error_print(); - return -1; - } - if ('A' <= ch && ch <= 'Z') { - ch += 'a' - 'A'; - } - if (ch != ' ') { - *code_point = ch; - *ptr = q; - return 1; - } + return ret; +} - /* Skip leading spaces and collapse repeated spaces. */ - while (q < end) { - const uint8_t *r = q; - size_t rlen = (size_t)(end - r); +static int x509_name_string_skip_spaces(int tag, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + uint32_t ch; - if ((ret = x509_name_string_char_from_bytes(tag, &r, &rlen, &ch)) != 1) { - if (ret == 0) error_print(); - return -1; - } - if ('A' <= ch && ch <= 'Z') { - ch += 'a' - 'A'; - } - if (ch != ' ') { - break; - } - q = r; - } - if (q == end) { - *ptr = end; - return 0; - } - if (p == str) { - p = q; - continue; - } - *code_point = ' '; - *ptr = q; - return 1; + if (!in || !*in || !inlen) { + error_print(); + return -1; } - *ptr = end; - return 0; + while (*inlen) { + p = *in; + len = *inlen; + if ((ret = x509_name_string_char_from_bytes(tag, &ch, &p, &len)) != 1) { + error_print(); + return -1; + } + if (ch != ' ') { + return 1; + } + *in = p; + *inlen = len; + } + return 1; +} + +static int x509_name_string_code_point_from_bytes(int tag, uint32_t *code_point, + const uint8_t **in, size_t *inlen) +{ + int ret; + uint32_t ch; + + if (!code_point || !in || !*in || !inlen) { + error_print(); + return -1; + } + if ((ret = x509_name_string_char_from_bytes(tag, &ch, in, inlen)) != 1) { + if (ret == 0) { + return 0; + } + error_print(); + return -1; + } + if ('A' <= ch && ch <= 'Z') { + ch += 'a' - 'A'; + } + if (ch == ' ') { + if (x509_name_string_skip_spaces(tag, in, inlen) != 1) { + error_print(); + return -1; + } + if (*inlen == 0) { + return 0; + } + ch = ' '; + } + *code_point = ch; + return 1; } static int x509_name_string_normalized_equ(int a_tag, const uint8_t *a, size_t alen, @@ -597,15 +571,30 @@ static int x509_name_string_normalized_equ(int a_tag, const uint8_t *a, size_t a { int a_ret; int b_ret; - const uint8_t *a_ptr = NULL; - const uint8_t *b_ptr = NULL; uint32_t a_ch; uint32_t b_ch; + if ((!a && alen) || (!b && blen)) { + error_print(); + return -1; + } + if (alen && x509_name_string_skip_spaces(a_tag, &a, &alen) != 1) { + error_print(); + return -1; + } + if (blen && x509_name_string_skip_spaces(b_tag, &b, &blen) != 1) { + error_print(); + return -1; + } + for (;;) { - a_ret = x509_name_string_next_normalized_code_point(a_tag, a, alen, &a_ptr, &a_ch); - b_ret = x509_name_string_next_normalized_code_point(b_tag, b, blen, &b_ptr, &b_ch); - if (a_ret < 0 || b_ret < 0) { + a_ret = x509_name_string_code_point_from_bytes(a_tag, &a_ch, &a, &alen); + if (a_ret < 0) { + error_print(); + return -1; + } + b_ret = x509_name_string_code_point_from_bytes(b_tag, &b_ch, &b, &blen); + if (b_ret < 0) { error_print(); return -1; } @@ -618,24 +607,6 @@ static int x509_name_string_normalized_equ(int a_tag, const uint8_t *a, size_t a } } -static int x509_name_string_tag(int tag) -{ - int ret = 0; - - switch (tag) { - case ASN1_TAG_TeletexString: - case ASN1_TAG_PrintableString: - case ASN1_TAG_UniversalString: - case ASN1_TAG_UTF8String: - case ASN1_TAG_BMPString: - case ASN1_TAG_IA5String: - ret = 1; - break; - default: - break; - } - return ret; -} /* * 这个 _ex 版本和 x509_attr_type_and_value_from_der() 的区别是: @@ -729,9 +700,12 @@ static int x509_attr_type_and_value_normalized_equ(const uint8_t *a, size_t alen } else if (a_val_der_len == b_val_der_len && memcmp(a_val_der, b_val_der, a_val_der_len) == 0) { ret = 1; - } else if (x509_name_string_tag(a_tag) && x509_name_string_tag(b_tag)) { + } else if (asn1_tag_is_cstring(a_tag) && asn1_tag_is_cstring(b_tag)) { ret = x509_name_string_normalized_equ(a_tag, a_val, a_val_len, b_tag, b_val, b_val_len); - if (ret < 0) error_print(); + if (ret < 0) { + error_print(); + return -1; + } } return ret; } @@ -760,6 +734,16 @@ end: return ret; } +/* + * 统计一个 RDN SET 中和给定 AttributeTypeAndValue 规范化相等的项数。 + * + * 例如同一个 RDN 允许包含多个 AVA: + * SET { + * commonName = "Alice", + * commonName = " ALICE " + * } + * 如果待匹配的 AVA 是 commonName = "alice",规范化比较会使 count == 2。 + */ static int x509_rdn_count_attr_type_and_value(const uint8_t *rdn, size_t rdnlen, const uint8_t *ava, size_t avalen, size_t *count) { @@ -846,7 +830,7 @@ end: int x509_name_normalized_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) { - int ret = 0; + int ret; const uint8_t *a_rdn; const uint8_t *b_rdn; size_t a_rdn_len; @@ -860,54 +844,39 @@ int x509_name_normalized_equ(const uint8_t *a, size_t alen, const uint8_t *b, si if (asn1_set_from_der(&a_rdn, &a_rdn_len, &a, &alen) != 1 || asn1_set_from_der(&b_rdn, &b_rdn_len, &b, &blen) != 1) { error_print(); - ret = -1; - goto end; + return -1; } ret = x509_rdn_normalized_equ(a_rdn, a_rdn_len, b_rdn, b_rdn_len); - if (ret != 1) { - goto end; - } - } - if (alen || blen) { - ret = 0; - } else { - ret = 1; - } -end: - return ret; -} - -int asn1_utf8_string_next_code_point(const uint8_t *str, size_t len, - const uint8_t **ptr, uint32_t *code_point) -{ - const uint8_t *p; - const uint8_t *end; - size_t rem; - uint32_t cp; - - if (!ptr || !code_point || (!str && len)) { - error_print(); - return -1; - } - if (!str) { - if (*ptr) { + if (ret < 0) { error_print(); return -1; } + if (ret == 0) { + return 0; + } + } + if (alen || blen) { return 0; } + return 1; +} - end = str + len; - p = *ptr ? *ptr : str; - if (p < str || p > end) { +int asn1_utf8_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen) +{ + const uint8_t *p; + size_t rem; + uint32_t cp; + + if (!code_point || !in || !*in || !inlen) { error_print(); return -1; } - if (p == end) { + if (*inlen == 0) { return 0; } - rem = (size_t)(end - p); + p = *in; + rem = *inlen; if (p[0] < 0x80) { cp = p[0]; p++; @@ -953,123 +922,83 @@ int asn1_utf8_string_next_code_point(const uint8_t *str, size_t len, } *code_point = cp; - *ptr = p; + *inlen -= (size_t)(p - *in); + *in = p; return 1; } -static int asn1_string_next_code_point_ptr(const uint8_t *str, size_t len, - const uint8_t **ptr, const uint8_t **p, size_t code_point_len) +int asn1_printable_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen) { - const uint8_t *end; - - if (!ptr || !p || !code_point_len || (!str && len)) { + if (!code_point || !in || !*in || !inlen) { error_print(); return -1; } - if (!str) { - if (*ptr) { - error_print(); - return -1; - } + if (*inlen == 0) { return 0; } - - end = str + len; - *p = *ptr ? *ptr : str; - if (*p < str || *p > end) { + if (asn1_string_is_printable_string((const char *)*in, 1) != 1) { error_print(); return -1; } - if (*p == end) { + *code_point = **in; + (*in)++; + (*inlen)--; + return 1; +} + +int asn1_ia5_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen) +{ + if (!code_point || !in || !*in || !inlen) { + error_print(); + return -1; + } + if (*inlen == 0) { return 0; } - if ((size_t)(end - *p) < code_point_len) { + if (asn1_string_is_ia5_string((const char *)*in, 1) != 1) { error_print(); return -1; } + *code_point = **in; + (*in)++; + (*inlen)--; return 1; } -int asn1_printable_string_next_code_point(const uint8_t *str, size_t len, - const uint8_t **ptr, uint32_t *code_point) +int asn1_bmp_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen) { - int ret; - const uint8_t *p; - - if (!code_point) { + if (!code_point || !in || !*in || !inlen) { error_print(); return -1; } - if ((ret = asn1_string_next_code_point_ptr(str, len, ptr, &p, 1)) != 1) { - if (ret < 0) error_print(); - return ret; + if (*inlen == 0) { + return 0; } - if (asn1_string_is_printable_string((const char *)p, 1) != 1) { + if (*inlen < 2 || *inlen % 2) { error_print(); return -1; } - *code_point = p[0]; - *ptr = p + 1; + *code_point = GETU16(*in); + *in += 2; + *inlen -= 2; return 1; } -int asn1_ia5_string_next_code_point(const uint8_t *str, size_t len, - const uint8_t **ptr, uint32_t *code_point) +int asn1_universal_string_code_point_from_bytes(uint32_t *code_point, const uint8_t **in, size_t *inlen) { - int ret; - const uint8_t *p; - - if (!code_point) { + if (!code_point || !in || !*in || !inlen) { error_print(); return -1; } - if ((ret = asn1_string_next_code_point_ptr(str, len, ptr, &p, 1)) != 1) { - if (ret < 0) error_print(); - return ret; + if (*inlen == 0) { + return 0; } - if (asn1_string_is_ia5_string((const char *)p, 1) != 1) { + if (*inlen < 4 || *inlen % 4) { error_print(); return -1; } - *code_point = p[0]; - *ptr = p + 1; - return 1; -} - -int asn1_bmp_string_next_code_point(const uint8_t *str, size_t len, - const uint8_t **ptr, uint32_t *code_point) -{ - int ret; - const uint8_t *p; - - if (!code_point || len % 2) { - error_print(); - return -1; - } - if ((ret = asn1_string_next_code_point_ptr(str, len, ptr, &p, 2)) != 1) { - if (ret < 0) error_print(); - return ret; - } - *code_point = GETU16(p); - *ptr = p + 2; - return 1; -} - -int asn1_universal_string_next_code_point(const uint8_t *str, size_t len, - const uint8_t **ptr, uint32_t *code_point) -{ - int ret; - const uint8_t *p; - - if (!code_point || len % 4) { - error_print(); - return -1; - } - if ((ret = asn1_string_next_code_point_ptr(str, len, ptr, &p, 4)) != 1) { - if (ret < 0) error_print(); - return ret; - } - *code_point = GETU32(p); - *ptr = p + 4; + *code_point = GETU32(*in); + *in += 4; + *inlen -= 4; return 1; } diff --git a/tests/asn1test.c b/tests/asn1test.c index 6be946df..129ecb83 100644 --- a/tests/asn1test.c +++ b/tests/asn1test.c @@ -541,7 +541,7 @@ static int test_asn1_utf8_string(void) return 1; } -static int test_asn1_string_next_code_point(void) +static int test_asn1_string_code_point_from_bytes(void) { const uint8_t utf8[] = { 0x41, 0xe4, 0xb8, 0xad, 0xf0, 0x9f, 0x98, 0x80 @@ -558,67 +558,79 @@ static int test_asn1_string_next_code_point(void) 0x00, 0x00, 0x4e, 0x2d, }; const uint8_t invalid_universal[] = { 0x00, 0x00, 0x00 }; - const uint8_t *p = NULL; + const uint8_t *p; + size_t len; uint32_t cp; - if (asn1_utf8_string_next_code_point(utf8, sizeof(utf8), &p, &cp) != 1 || cp != 0x41 - || asn1_utf8_string_next_code_point(utf8, sizeof(utf8), &p, &cp) != 1 || cp != 0x4e2d - || asn1_utf8_string_next_code_point(utf8, sizeof(utf8), &p, &cp) != 1 || cp != 0x1f600 - || asn1_utf8_string_next_code_point(utf8, sizeof(utf8), &p, &cp) != 0) { + p = utf8; + len = sizeof(utf8); + if (asn1_utf8_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x41 + || asn1_utf8_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x4e2d + || asn1_utf8_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x1f600 + || asn1_utf8_string_code_point_from_bytes(&cp, &p, &len) != 0) { error_print(); return -1; } - p = NULL; - if (asn1_utf8_string_next_code_point(invalid_utf8, sizeof(invalid_utf8), &p, &cp) != -1) { + p = invalid_utf8; + len = sizeof(invalid_utf8); + if (asn1_utf8_string_code_point_from_bytes(&cp, &p, &len) != -1) { error_print(); return -1; } - p = NULL; - if (asn1_printable_string_next_code_point(printable, sizeof(printable) - 1, &p, &cp) != 1 || cp != 'A' - || asn1_printable_string_next_code_point(printable, sizeof(printable) - 1, &p, &cp) != 1 || cp != 'z') { + p = printable; + len = sizeof(printable) - 1; + if (asn1_printable_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 'A' + || asn1_printable_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 'z') { error_print(); return -1; } - p = NULL; - if (asn1_printable_string_next_code_point(invalid_printable, sizeof(invalid_printable) - 1, &p, &cp) != -1) { + p = invalid_printable; + len = sizeof(invalid_printable) - 1; + if (asn1_printable_string_code_point_from_bytes(&cp, &p, &len) != -1) { error_print(); return -1; } - p = NULL; - if (asn1_ia5_string_next_code_point(ia5, sizeof(ia5) - 1, &p, &cp) != 1 || cp != 'a') { + p = ia5; + len = sizeof(ia5) - 1; + if (asn1_ia5_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 'a') { error_print(); return -1; } - p = NULL; - if (asn1_ia5_string_next_code_point(invalid_ia5, sizeof(invalid_ia5), &p, &cp) != -1) { + p = invalid_ia5; + len = sizeof(invalid_ia5); + if (asn1_ia5_string_code_point_from_bytes(&cp, &p, &len) != -1) { error_print(); return -1; } - p = NULL; - if (asn1_bmp_string_next_code_point(bmp, sizeof(bmp), &p, &cp) != 1 || cp != 0x41 - || asn1_bmp_string_next_code_point(bmp, sizeof(bmp), &p, &cp) != 1 || cp != 0x4e2d - || asn1_bmp_string_next_code_point(bmp, sizeof(bmp), &p, &cp) != 0) { + p = bmp; + len = sizeof(bmp); + if (asn1_bmp_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x41 + || asn1_bmp_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x4e2d + || asn1_bmp_string_code_point_from_bytes(&cp, &p, &len) != 0) { error_print(); return -1; } - p = NULL; - if (asn1_bmp_string_next_code_point(invalid_bmp, sizeof(invalid_bmp), &p, &cp) != -1) { + p = invalid_bmp; + len = sizeof(invalid_bmp); + if (asn1_bmp_string_code_point_from_bytes(&cp, &p, &len) != -1) { error_print(); return -1; } - p = NULL; - if (asn1_universal_string_next_code_point(universal, sizeof(universal), &p, &cp) != 1 || cp != 0x41 - || asn1_universal_string_next_code_point(universal, sizeof(universal), &p, &cp) != 1 || cp != 0x4e2d - || asn1_universal_string_next_code_point(universal, sizeof(universal), &p, &cp) != 0) { + p = universal; + len = sizeof(universal); + if (asn1_universal_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x41 + || asn1_universal_string_code_point_from_bytes(&cp, &p, &len) != 1 || cp != 0x4e2d + || asn1_universal_string_code_point_from_bytes(&cp, &p, &len) != 0) { error_print(); return -1; } - p = NULL; - if (asn1_universal_string_next_code_point(invalid_universal, sizeof(invalid_universal), &p, &cp) != -1) { + p = invalid_universal; + len = sizeof(invalid_universal); + if (asn1_universal_string_code_point_from_bytes(&cp, &p, &len) != -1) { error_print(); return -1; } @@ -935,7 +947,7 @@ int main(void) { if (test_asn1_tag() != 1) goto err; if (test_asn1_utf8_string() != 1) goto err; - if (test_asn1_string_next_code_point() != 1) goto err; + if (test_asn1_string_code_point_from_bytes() != 1) goto err; /* if (test_asn1_length() != 1) goto err; if (test_asn1_length_from_ber() != 1) goto err;