mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-27 15:43:42 +08:00
Update X509 basic constraints
This commit is contained in:
@@ -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.1097")
|
||||
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1098")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
include(CPack)
|
||||
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
|
||||
|
||||
#define GMSSL_VERSION_NUM 30200
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1097"
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1098"
|
||||
|
||||
int gmssl_version_num(void);
|
||||
const char *gmssl_version_str(void);
|
||||
|
||||
@@ -301,6 +301,10 @@ int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *ca
|
||||
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);
|
||||
int x509_cert_chain_find_root_ca_cert(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *rootcacerts, size_t rootcacertslen,
|
||||
const uint8_t **rootcacert, size_t *rootcacertlen,
|
||||
const char *signer_id, size_t signer_id_len);
|
||||
|
||||
int x509_cert_get_details(const uint8_t *a, size_t alen,
|
||||
int *version,
|
||||
@@ -379,6 +383,8 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type
|
||||
const uint8_t *rootcerts, size_t rootcertslen, int depth, int *verify_result);
|
||||
int x509_certs_check_name_constraints(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *rootcacert, size_t rootcacertlen);
|
||||
int x509_certs_check_basic_constraints(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *rootcacert, size_t rootcacertlen);
|
||||
int x509_certs_get_subjects(const uint8_t *certs, size_t certslen, uint8_t *names, size_t *nameslen);
|
||||
int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
|
||||
|
||||
|
||||
251
src/x509_vrf.c
251
src/x509_vrf.c
@@ -1941,3 +1941,254 @@ int x509_certs_check_name_constraints(const uint8_t *cert_chain, size_t cert_cha
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int x509_cert_get_basic_constraints(const uint8_t *cert, size_t certlen,
|
||||
int *critical, int *ca, int *path_len_constraint)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *exts;
|
||||
size_t extslen;
|
||||
const uint8_t *val;
|
||||
size_t vlen;
|
||||
|
||||
if (!cert || !certlen || !critical || !ca || !path_len_constraint) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*critical = -1;
|
||||
*ca = -1;
|
||||
*path_len_constraint = -1;
|
||||
|
||||
if ((ret = x509_cert_get_exts(cert, certlen, &exts, &extslen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if ((ret = x509_exts_get_ext_by_oid(exts, extslen, OID_ce_basic_constraints,
|
||||
critical, &val, &vlen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (x509_basic_constraints_from_der(ca, path_len_constraint, &val, &vlen) != 1
|
||||
|| asn1_length_is_zero(vlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int x509_cert_check_basic_constraints_by_type(const uint8_t *cert, size_t certlen,
|
||||
int cert_type, int *path_len_constraint)
|
||||
{
|
||||
int has_basic_constraints;
|
||||
int is_ca;
|
||||
int critical;
|
||||
int ca;
|
||||
|
||||
if (!cert || !certlen || !path_len_constraint) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*path_len_constraint = -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_ca = 0;
|
||||
break;
|
||||
case X509_cert_ca:
|
||||
case X509_cert_root_ca:
|
||||
case X509_cert_crl_sign:
|
||||
is_ca = 1;
|
||||
break;
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((has_basic_constraints = x509_cert_get_basic_constraints(cert, certlen,
|
||||
&critical, &ca, path_len_constraint)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!has_basic_constraints) {
|
||||
if (is_ca) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (x509_ext_check_critical(OID_ce_basic_constraints, is_ca, critical) != 1
|
||||
|| x509_basic_constraints_check(ca, *path_len_constraint, cert_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int x509_certs_count_non_self_issued_ca_certs(const uint8_t *cert_chain,
|
||||
size_t cert_chain_len, size_t *count)
|
||||
{
|
||||
int ret;
|
||||
int is_first_cert = 1;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
|
||||
if (!cert_chain || !cert_chain_len || !count) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*count = 0;
|
||||
|
||||
while (cert_chain_len) {
|
||||
if (x509_cert_from_der(&cert, &certlen, &cert_chain, &cert_chain_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (is_first_cert) {
|
||||
is_first_cert = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
pathLenConstraint 统计的是当前 CA 之下的非 self-issued 中间 CA 数量。
|
||||
链中第一张证书是实体证书,不计入;self-issued CA 也不计入。
|
||||
*/
|
||||
if ((ret = x509_cert_is_self_issued(cert, certlen)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
(*count)++;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_certs_check_basic_constraints(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *rootcacert, size_t rootcacertlen)
|
||||
{
|
||||
const uint8_t *chain;
|
||||
size_t chain_len;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
size_t checked_certs_len;
|
||||
size_t path_len;
|
||||
int path_len_constraint;
|
||||
|
||||
if (!cert_chain || !cert_chain_len
|
||||
|| (!rootcacert && rootcacertlen)
|
||||
|| (rootcacert && !rootcacertlen)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
chain = cert_chain;
|
||||
chain_len = cert_chain_len;
|
||||
|
||||
if (x509_cert_from_der(&cert, &certlen, &chain, &chain_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_check_basic_constraints_by_type(cert, certlen,
|
||||
X509_cert_server_auth, &path_len_constraint) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
checked_certs_len = certlen;
|
||||
|
||||
while (chain_len) {
|
||||
if (x509_cert_from_der(&cert, &certlen, &chain, &chain_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_check_basic_constraints_by_type(cert, certlen,
|
||||
X509_cert_ca, &path_len_constraint) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_count_non_self_issued_ca_certs(cert_chain,
|
||||
checked_certs_len, &path_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (path_len_constraint >= 0 && path_len > (size_t)path_len_constraint) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
checked_certs_len += certlen;
|
||||
}
|
||||
|
||||
if (rootcacert) {
|
||||
if (x509_cert_check_basic_constraints_by_type(rootcacert, rootcacertlen,
|
||||
X509_cert_root_ca, &path_len_constraint) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_certs_count_non_self_issued_ca_certs(cert_chain,
|
||||
cert_chain_len, &path_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (path_len_constraint >= 0 && path_len > (size_t)path_len_constraint) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_cert_chain_find_root_ca_cert(const uint8_t *cert_chain, size_t cert_chain_len,
|
||||
const uint8_t *rootcacerts, size_t rootcacertslen,
|
||||
const uint8_t **rootcacert, size_t *rootcacertlen,
|
||||
const char *signer_id, size_t signer_id_len)
|
||||
{
|
||||
int ret;
|
||||
const uint8_t *cert;
|
||||
size_t certlen;
|
||||
const uint8_t *cacert;
|
||||
size_t cacertlen;
|
||||
int found_root = 0;
|
||||
|
||||
if (!cert_chain || !cert_chain_len
|
||||
|| (!rootcacerts && rootcacertslen)
|
||||
|| !rootcacert || !rootcacertlen
|
||||
|| (!signer_id && signer_id_len)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
*rootcacert = NULL;
|
||||
*rootcacertlen = 0;
|
||||
|
||||
if (x509_certs_get_last(cert_chain, cert_chain_len, &cert, &certlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (rootcacertslen) {
|
||||
if (x509_cert_from_der(&cacert, &cacertlen, &rootcacerts, &rootcacertslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = x509_cert_is_signed_by_root_ca_cert(cert, certlen, cacert, cacertlen,
|
||||
signer_id, signer_id_len)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret) {
|
||||
*rootcacert = cacert;
|
||||
*rootcacertlen = cacertlen;
|
||||
found_root = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return found_root;
|
||||
}
|
||||
|
||||
@@ -268,6 +268,11 @@ static int test_x509_cert_is_signed_by_root_ca_cert(void)
|
||||
size_t leaf_len;
|
||||
uint8_t leaf_wrong_aki_issuer[2048];
|
||||
size_t leaf_wrong_aki_issuer_len;
|
||||
uint8_t rootcacerts[8192];
|
||||
size_t rootcacertslen;
|
||||
uint8_t *p;
|
||||
const uint8_t *found_root;
|
||||
size_t found_root_len;
|
||||
|
||||
if (set_x509_name_cn(root_name, &root_name_len, sizeof(root_name), "Root CA") != 1
|
||||
|| set_x509_name_cn(other_name, &other_name_len, sizeof(other_name), "Other Root CA") != 1
|
||||
@@ -332,6 +337,35 @@ static int test_x509_cert_is_signed_by_root_ca_cert(void)
|
||||
return -1;
|
||||
}
|
||||
|
||||
found_root = good_root;
|
||||
found_root_len = good_root_len;
|
||||
if (x509_cert_chain_find_root_ca_cert(leaf, leaf_len,
|
||||
wrong_name_root, wrong_name_root_len,
|
||||
&found_root, &found_root_len,
|
||||
SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 0
|
||||
|| found_root != NULL
|
||||
|| found_root_len != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
p = rootcacerts;
|
||||
rootcacertslen = 0;
|
||||
if (x509_cert_to_der(wrong_name_root, wrong_name_root_len, &p, &rootcacertslen) != 1
|
||||
|| x509_cert_to_der(good_root, good_root_len, &p, &rootcacertslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_chain_find_root_ca_cert(leaf, leaf_len,
|
||||
rootcacerts, rootcacertslen,
|
||||
&found_root, &found_root_len,
|
||||
SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1
|
||||
|| found_root_len != good_root_len
|
||||
|| memcmp(found_root, good_root, good_root_len) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user