From 97d08c956a58284d25554bdba1ccb387928efd67 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Mon, 6 Feb 2023 11:48:33 +0800 Subject: [PATCH] Update X509 --- include/gmssl/x509.h | 2 + include/gmssl/x509_ext.h | 1 + include/gmssl/x509_str.h | 36 -------- src/cms.c | 1 - src/x509_cer.c | 39 ++++++++- src/x509_crl.c | 155 ---------------------------------- src/x509_ext.c | 84 ++++++------------- src/x509_str.c | 177 ++++++++++++++++++++++++++++++++++----- tests/x509_exttest.c | 1 - tests/x509_strtest.c | 1 - 10 files changed, 222 insertions(+), 275 deletions(-) delete mode 100644 include/gmssl/x509_str.h diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index e7797f2d..d9e34726 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -104,6 +104,8 @@ int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen); int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen); int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); +int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen); /* diff --git a/include/gmssl/x509_ext.h b/include/gmssl/x509_ext.h index a36fff5d..6f04ca1a 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -386,6 +386,7 @@ BasicConstraints ::= SEQUENCE { cA BOOLEAN DEFAULT FALSE, pathLenConstraint INTEGER (0..MAX) OPTIONAL } */ +#define X509_MAX_PATH_LEN_CONSTRAINT 6 int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen); int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t **in, size_t *inlen); int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type); diff --git a/include/gmssl/x509_str.h b/include/gmssl/x509_str.h deleted file mode 100644 index f1c205fb..00000000 --- a/include/gmssl/x509_str.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the License); you may - * not use this file except in compliance with the License. - * - * http://www.apache.org/licenses/LICENSE-2.0 - */ - - -#ifndef GMSSL_X509_STR_H -#define GMSSL_X509_STR_H - - -#include -#include -#include -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - - -int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); -int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen); - - - -#ifdef __cplusplus -} -#endif -#endif diff --git a/src/cms.c b/src/cms.c index 1fb3ad17..e625d192 100644 --- a/src/cms.c +++ b/src/cms.c @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include diff --git a/src/x509_cer.c b/src/x509_cer.c index fbb49990..c77ef0b2 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -268,8 +267,6 @@ int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) { - int ret; - if (dlen == 0) { return 0; } @@ -318,6 +315,41 @@ int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int return asn1_string_print(fp, fmt, ind, label, tag, d, dlen); } +int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + int ret; + size_t len = 0; + + if ((ret = x509_directory_name_to_der(tag, d, dlen, NULL, &len)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_explicit_header_to_der(index, len, out, outlen) != 1 + || x509_directory_name_to_der(tag, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *p; + size_t len; + + if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_directory_name_from_der(tag, d, dlen, &p, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + return 1; +} + static const struct { int oid; int is_printable_string_only; @@ -1223,7 +1255,6 @@ static int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, { const uint8_t *p; size_t len; - int val; format_print(fp, fmt, ind, "%s\n", label); ind += 4; diff --git a/src/x509_crl.c b/src/x509_crl.c index 8ce42619..8cab5ddf 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -1209,9 +1209,6 @@ int x509_crl_exts_check(const uint8_t *d, size_t dlen) int critical; const uint8_t *val; size_t vlen; - int tag; - const uint8_t *p; - size_t len; while (dlen) { if (x509_crl_ext_from_der_ex(&oid, nodes, &nodes_cnt, &critical, &val, &vlen, &d, &dlen) != 1) { @@ -1359,7 +1356,6 @@ err: static int x509_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - int val; const uint8_t *p; size_t len; @@ -1700,154 +1696,3 @@ int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t } return 1; } - -int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen) -{ - int ret = -1; - char *uristr = NULL; - uint8_t *buf = NULL; - size_t buflen; - const uint8_t *p; - - if (!(uristr = strndup(uri, urilen))) { - error_print(); - return -1; - } - if (http_get(uristr, NULL, &buflen, 0) < 0) { - error_print(); - goto end; - } - if (!buflen) { - error_print(); - goto end; - } - if (!(buf = malloc(buflen))) { - error_print(); - goto end; - } - if (http_get(uristr, buf, &buflen, buflen) != 1) { - error_print(); - goto end; - } - p = buf; - if (x509_crl_from_der((const uint8_t **)crl, crl_len, &p, &buflen) != 1) { - error_print(); - goto end; - } - buf = NULL; - ret = 1; -end: - if (uristr) free(uristr); - if (buf) free(buf); - return ret; -} - -int x509_crl_new_from_cert(uint8_t **crl, size_t *crl_len, const uint8_t *cert, size_t certlen) -{ - int ret; - const uint8_t *exts; - size_t extslen; - - int critical; - const uint8_t *val; - size_t vlen; - - const char *uri; - size_t urilen; - int reason; - const uint8_t *crl_issuer; - size_t crl_issuer_len; - - if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if ((ret = x509_exts_get_ext_by_oid(exts, extslen, - OID_ce_crl_distribution_points, &critical, &val, &vlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_uri_as_distribution_points_from_der(&uri, &urilen, - &reason, &crl_issuer, &crl_issuer_len, &val, &vlen) != 1 - || asn1_length_is_zero(vlen) != 1) { - error_print(); - return -1; - } - if (!uri) { - *crl = NULL; - *crl_len = 0; - return 0; - } - if (x509_crl_new_from_uri(crl, crl_len, uri, urilen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_cert_check_crl(const uint8_t *cert, size_t certlen, const uint8_t *cacert, size_t cacertlen, - const char *ca_signer_id, size_t ca_signer_id_len) -{ - int ret = -1; - uint8_t *crl = NULL; - size_t crl_len = 0; - const uint8_t *crl_issuer; - size_t crl_issuer_len; - - const uint8_t *issuer; - size_t issuer_len; - const uint8_t *serial; - size_t serial_len; - - time_t revoke_date; - const uint8_t *crl_entry_exts; - size_t crl_entry_exts_len; - - // download CRL and do basic validation - if (x509_crl_new_from_cert(&crl, &crl_len, cert, certlen) != 1) { - error_print(); - return -1; - } - if (x509_crl_check(crl, crl_len, time(NULL)) != 1) { - error_print(); - goto end; - } - - if (x509_cert_get_issuer_and_serial_number(cert, certlen, &issuer, &issuer_len, &serial, &serial_len) != 1) { - error_print(); - goto end; - } - - // make sure CRL's issuer is the certificate issuer - if (x509_crl_get_issuer(crl, crl_len, &crl_issuer, &crl_issuer_len) != 1) { - error_print(); - goto end; - } - if (x509_name_equ(issuer, issuer_len, crl_issuer, crl_issuer_len) != 1) { - error_print(); - goto end; - } - - // verify CRL - if (x509_crl_verify_by_ca_cert(crl, crl_len, cacert, cacertlen, ca_signer_id, ca_signer_id_len) != 1) { - error_print(); - goto end; - } - - // check if the certificate in the CRL - if ((ret = x509_crl_find_revoked_cert_by_serial_number(crl, crl_len, serial, serial_len, - &revoke_date, &crl_entry_exts, &crl_entry_exts_len)) < 0) { - error_print(); - goto end; - } - if (ret == 1) { - ret = -1; - error_print(); - goto end; - } - ret = 1; - -end: - if (crl) free(crl); - return ret; -} diff --git a/src/x509_ext.c b/src/x509_ext.c index 841d5be7..5aa2700f 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -326,9 +325,10 @@ int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int c return 0; } if (!bits) { - // TODO: 检查是否在合法范围内 - error_print(); - return -1; + if (x509_key_usage_check(bits, -1) != 1) { + error_print(); + return -1; + } } exts += *extslen; @@ -663,41 +663,6 @@ err: return -1; } -int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) -{ - int ret; - size_t len = 0; - - if ((ret = x509_directory_name_to_der(tag, d, dlen, NULL, &len)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (asn1_explicit_header_to_der(index, len, out, outlen) != 1 - || x509_directory_name_to_der(tag, d, dlen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen) -{ - int ret; - const uint8_t *p; - size_t len; - - if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - if (x509_directory_name_from_der(tag, d, dlen, &p, &len) != 1 - || asn1_length_is_zero(len) != 1) { - error_print(); - return -1; - } - return 1; -} - int x509_edi_party_name_to_der( int assigner_choice, const uint8_t *assigner, size_t assigner_len, int party_name_choice, const uint8_t *party_name, size_t party_name_len, @@ -1177,7 +1142,17 @@ int x509_key_usage_from_name(int *flag, const char *name) int x509_key_usage_check(int bits, int cert_type) { + if (bits == -1) { + return 0; + } + if (!bits) { + error_print(); + return -1; + } + switch (cert_type) { + case -1: + break; case X509_cert_server_auth: case X509_cert_client_auth: if (!(bits & X509_KU_DIGITAL_SIGNATURE) @@ -1230,7 +1205,6 @@ int x509_key_usage_check(int bits, int cert_type) //return -1; // comment to print warning } break; - default: error_print(); return -1; @@ -1344,7 +1318,7 @@ int x509_notice_reference_to_der( int x509_notice_reference_from_der( int *org_tag, const uint8_t **org, size_t *org_len, - int notice_numbers[X509_MAX_NOTICE_NUMBERS], size_t *notice_numbers_cnt, size_t max_notice_numbers, //FIXME: max_notice_numbers 还没检查 + int *notice_numbers, size_t *notice_numbers_cnt, size_t max_notice_numbers, const uint8_t **in, size_t *inlen) { int ret; @@ -1357,7 +1331,7 @@ int x509_notice_reference_from_der( return ret; } if (x509_display_text_from_der(org_tag, org, org_len, &d, &dlen) != 1 - || asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, X509_MAX_NOTICE_NUMBERS, &d, &dlen) != 1 + || asn1_sequence_of_int_from_der(notice_numbers, notice_numbers_cnt, max_notice_numbers, &d, &dlen) != 1 || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; @@ -1416,7 +1390,7 @@ int x509_user_notice_to_der( int x509_user_notice_from_der( int *notice_ref_org_tag, const uint8_t **notice_ref_org, size_t *notice_ref_org_len, - int *notice_ref_notice_numbers, size_t *notice_ref_notice_numbers_cnt, size_t max_notice_ref_notice_numbers, // FIXME: max_notice_ref_notice_numbers + int *notice_ref_notice_numbers, size_t *notice_ref_notice_numbers_cnt, size_t max_notice_ref_notice_numbers, int *explicit_text_tag, const uint8_t **explicit_text, size_t *explicit_text_len, const uint8_t **in, size_t *inlen) { @@ -1459,7 +1433,6 @@ err: return -1; } -// 是否要针对oid = cps的IA5String做一个方便的接口呢?毕竟oid 只有两个可选项 int x509_policy_qualifier_info_to_der( int oid, const uint8_t *qualifier, size_t qualifier_len, @@ -1842,7 +1815,6 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t * return 1; } -// 这个函数原型可能要改一下 int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type) { /* @@ -1864,7 +1836,7 @@ int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type) error_print(); return -1; } - if (path_len_cons < 0 || path_len_cons > 6) { + if (path_len_cons < 0 || path_len_cons > X509_MAX_PATH_LEN_CONSTRAINT) { error_print(); return -1; } @@ -1891,7 +1863,7 @@ int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err; if (ret) format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(val)); - else format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(0)); // 特殊对待,无论cA值是否编码均输出结果 + //else format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(0)); if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err; if (ret) format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val); if (asn1_length_is_zero(dlen) != 1) goto err; @@ -2108,8 +2080,8 @@ int x509_policy_constraints_from_der( int x509_policy_constraints_check(const uint8_t *a, size_t alen) { + error_print(); return -1; - } int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -2184,7 +2156,6 @@ int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, con return 1; } -// 这个函数原型可能也要改一下 int x509_ext_key_usage_check(const int *oids, size_t oids_cnt, int cert_type) { int ret = -1; @@ -2290,9 +2261,13 @@ int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, { int ret; int tag = ASN1_TAG_EXPLICIT(X509_full_name); - if ((ret = x509_uri_as_general_names_to_der_ex(tag, uri, urilen, out, outlen)) != 1) { - if (ret < 0) error_print(); // 检查一下,是否有必要支持返回0 - return ret; + + if (urilen == 0) { + return 0; + } + if (x509_uri_as_general_names_to_der_ex(tag, uri, urilen, out, outlen) != 1) { + error_print(); + return -1; } return 1; } @@ -2879,8 +2854,6 @@ int x509_authority_info_access_from_der( int ret; const uint8_t *d; size_t dlen; - const uint8_t *ad; - size_t adlen; if (!ca_issuers_uri || !ca_issuers_urilen || !ocsp_uri || !ocsp_urilen || !in || !(*in) || !inlen) { error_print(); @@ -2974,6 +2947,3 @@ int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t m } return 1; } - - - diff --git a/src/x509_str.c b/src/x509_str.c index beb5a558..d3b669d3 100644 --- a/src/x509_str.c +++ b/src/x509_str.c @@ -17,34 +17,17 @@ #include #include #include -#include #include +#include +#include #include #include #include +#include #include #include -/* -DirectoryString ::= CHOICE { - teletexString TeletexString (SIZE (1..MAX)), - printableString PrintableString (SIZE (1..MAX)), - universalString UniversalString (SIZE (1..MAX)), - utf8String UTF8String (SIZE (1..MAX)), - bmpString BMPString (SIZE (1..MAX)) } - -BMPString has zeros! - "Cert" in BMPStirng is 00 43 00 65 00 72 00 74 - -RDN 中很多值都是这个类型,但是有特定的长度限制,因此这个函数应该增加一个长度限制选项。 -*/ - - - - - - int x509_cert_new_from_file(uint8_t **out, size_t *outlen, const char *file) { int ret = -1; @@ -145,3 +128,157 @@ int x509_req_new_from_file(uint8_t **req, size_t *reqlen, const char *file) fclose(fp); return 1; } + +int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen) +{ + int ret = -1; + char *uristr = NULL; + uint8_t *buf = NULL; + size_t buflen; + const uint8_t *p; + + if (!(uristr = malloc(urilen + 1))) { + error_print(); + return -1; + } + memcpy(uristr, uri, urilen); + uristr[urilen] = 0; + + if (http_get(uristr, NULL, &buflen, 0) < 0) { + error_print(); + goto end; + } + if (!buflen) { + error_print(); + goto end; + } + if (!(buf = malloc(buflen))) { + error_print(); + goto end; + } + if (http_get(uristr, buf, &buflen, buflen) != 1) { + error_print(); + goto end; + } + p = buf; + if (x509_crl_from_der((const uint8_t **)crl, crl_len, &p, &buflen) != 1) { + error_print(); + goto end; + } + buf = NULL; + ret = 1; +end: + if (uristr) free(uristr); + if (buf) free(buf); + return ret; +} + +int x509_crl_new_from_cert(uint8_t **crl, size_t *crl_len, const uint8_t *cert, size_t certlen) +{ + int ret; + const uint8_t *exts; + size_t extslen; + + int critical; + const uint8_t *val; + size_t vlen; + + const char *uri; + size_t urilen; + int reason; + const uint8_t *crl_issuer; + size_t crl_issuer_len; + + if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if ((ret = x509_exts_get_ext_by_oid(exts, extslen, + OID_ce_crl_distribution_points, &critical, &val, &vlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_uri_as_distribution_points_from_der(&uri, &urilen, + &reason, &crl_issuer, &crl_issuer_len, &val, &vlen) != 1 + || asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + if (!uri) { + *crl = NULL; + *crl_len = 0; + return 0; + } + if (x509_crl_new_from_uri(crl, crl_len, uri, urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_cert_check_crl(const uint8_t *cert, size_t certlen, const uint8_t *cacert, size_t cacertlen, + const char *ca_signer_id, size_t ca_signer_id_len) +{ + int ret = -1; + uint8_t *crl = NULL; + size_t crl_len = 0; + const uint8_t *crl_issuer; + size_t crl_issuer_len; + + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + + time_t revoke_date; + const uint8_t *crl_entry_exts; + size_t crl_entry_exts_len; + + // download CRL and do basic validation + if (x509_crl_new_from_cert(&crl, &crl_len, cert, certlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_check(crl, crl_len, time(NULL)) != 1) { + error_print(); + goto end; + } + + if (x509_cert_get_issuer_and_serial_number(cert, certlen, &issuer, &issuer_len, &serial, &serial_len) != 1) { + error_print(); + goto end; + } + + // make sure CRL's issuer is the certificate issuer + if (x509_crl_get_issuer(crl, crl_len, &crl_issuer, &crl_issuer_len) != 1) { + error_print(); + goto end; + } + if (x509_name_equ(issuer, issuer_len, crl_issuer, crl_issuer_len) != 1) { + error_print(); + goto end; + } + + // verify CRL + if (x509_crl_verify_by_ca_cert(crl, crl_len, cacert, cacertlen, ca_signer_id, ca_signer_id_len) != 1) { + error_print(); + goto end; + } + + // check if the certificate in the CRL + if ((ret = x509_crl_find_revoked_cert_by_serial_number(crl, crl_len, serial, serial_len, + &revoke_date, &crl_entry_exts, &crl_entry_exts_len)) < 0) { + error_print(); + goto end; + } + if (ret == 1) { + ret = -1; + error_print(); + goto end; + } + ret = 1; + +end: + if (crl) free(crl); + return ret; +} diff --git a/tests/x509_exttest.c b/tests/x509_exttest.c index a202b58d..47d6188b 100644 --- a/tests/x509_exttest.c +++ b/tests/x509_exttest.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/tests/x509_strtest.c b/tests/x509_strtest.c index 535c9b87..898ad4e2 100644 --- a/tests/x509_strtest.c +++ b/tests/x509_strtest.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include