mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-19 19:33:38 +08:00
Update X509 cert chain verify
This commit is contained in:
@@ -118,6 +118,7 @@ set(src
|
||||
src/x509_alg.c
|
||||
src/x509_cer.c
|
||||
src/x509_ext.c
|
||||
src/x509_vrf.c
|
||||
src/x509_req.c
|
||||
src/x509_crl.c
|
||||
src/x509_new.c
|
||||
@@ -191,6 +192,7 @@ set(tests
|
||||
x509_alg
|
||||
x509_str
|
||||
x509_ext
|
||||
x509_vrf
|
||||
x509_req
|
||||
x509_crl
|
||||
x509_key
|
||||
@@ -818,7 +820,7 @@ endif()
|
||||
#
|
||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1087")
|
||||
set(CPACK_PACKAGE_VERSION "3.2.0-dev.1088")
|
||||
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.1087"
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.2.0-dev.1088"
|
||||
|
||||
int gmssl_version_num(void);
|
||||
const char *gmssl_version_str(void);
|
||||
|
||||
@@ -1833,7 +1833,6 @@ int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type,
|
||||
size_t extslen;
|
||||
int sig_algor;
|
||||
|
||||
|
||||
if (x509_cert_get_details(cert, certlen,
|
||||
&version, // version
|
||||
&serial, &serial_len, // serial
|
||||
@@ -1871,12 +1870,12 @@ int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check issuer and subject not empty
|
||||
// check issuer and subject name requirements
|
||||
if (x509_name_check(issuer, issuer_len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_name_check(subject, subject_len) != 1) {
|
||||
if (x509_cert_check_subject(cert, certlen, cert_type) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
218
src/x509_vrf.c
Normal file
218
src/x509_vrf.c
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/asn1.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/x509_ext.h>
|
||||
#include <gmssl/x509_cer.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static int x509_general_name_check(int choice, const uint8_t *d, size_t dlen)
|
||||
{
|
||||
const uint8_t *p;
|
||||
size_t len;
|
||||
const uint8_t *q;
|
||||
size_t qlen;
|
||||
uint32_t nodes[32];
|
||||
size_t nodes_cnt;
|
||||
int tag;
|
||||
int ret;
|
||||
|
||||
if (!d || !dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (choice) {
|
||||
case X509_gn_other_name:
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1
|
||||
|| asn1_object_identifier_from_der(nodes, &nodes_cnt, &p, &len) != 1
|
||||
|| asn1_explicit_from_der(0, &q, &qlen, &p, &len) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (!qlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_rfc822_name:
|
||||
case X509_gn_dns_name:
|
||||
case X509_gn_uniform_resource_identifier:
|
||||
if (asn1_string_is_ia5_string((const char *)d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_x400_address:
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1
|
||||
|| !len) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_directory_name:
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1
|
||||
|| x509_name_check(p, len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_edi_party_name:
|
||||
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1
|
||||
|| asn1_length_is_zero(dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if ((ret = x509_explicit_directory_name_from_der(0, &tag, &q, &qlen, &p, &len)) < 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ret && x509_directory_name_check(tag, q, qlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_explicit_directory_name_from_der(1, &tag, &q, &qlen, &p, &len) != 1
|
||||
|| x509_directory_name_check(tag, q, qlen) != 1
|
||||
|| asn1_length_is_zero(len) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_ip_address:
|
||||
if (dlen != 4 && dlen != 16) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
case X509_gn_registered_id:
|
||||
if (asn1_object_identifier_from_octets(nodes, &nodes_cnt, d, dlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int x509_general_names_check(const uint8_t *d, size_t dlen)
|
||||
{
|
||||
int choice;
|
||||
const uint8_t *name;
|
||||
size_t namelen;
|
||||
|
||||
if (!d || !dlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (dlen) {
|
||||
if (x509_general_name_from_der(&choice, &name, &namelen, &d, &dlen) != 1
|
||||
|| x509_general_name_check(choice, name, namelen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int x509_cert_check_subject(const uint8_t *cert, size_t certlen, int cert_type)
|
||||
{
|
||||
int ret;
|
||||
int is_cacert;
|
||||
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) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
if (is_cacert) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (x509_cert_get_exts(cert, certlen, &exts, &extslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_exts_get_ext_by_oid(exts, extslen, OID_ce_subject_alt_name, &critical, &val, &vlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (critical != X509_critical) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (asn1_sequence_from_der(&gns, &gnslen, &val, &vlen) != 1
|
||||
|| asn1_length_is_zero(vlen) != 1
|
||||
|| x509_general_names_check(gns, gnslen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
132
tests/x509_vrftest.c
Normal file
132
tests/x509_vrftest.c
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2014-2026 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
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <gmssl/oid.h>
|
||||
#include <gmssl/x509_alg.h>
|
||||
#include <gmssl/x509_ext.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static int set_x509_name(uint8_t *name, size_t *namelen, size_t maxlen)
|
||||
{
|
||||
*namelen = 0;
|
||||
if (x509_name_add_country_name(name, namelen, maxlen, "CN") != 1
|
||||
|| x509_name_add_locality_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Haidian", strlen("Haidian")) != 1
|
||||
|| x509_name_add_state_or_province_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"Beijing", strlen("Beijing")) != 1
|
||||
|| x509_name_add_organization_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"PKU", strlen("PKU")) != 1
|
||||
|| x509_name_add_organizational_unit_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CS", strlen("CS")) != 1
|
||||
|| x509_name_add_common_name(name, namelen, maxlen, ASN1_TAG_PrintableString, (uint8_t *)"CA", strlen("CA")) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_x509_cert_check_subject(void)
|
||||
{
|
||||
int algor = OID_ec_public_key;
|
||||
int algor_param = OID_sm2;
|
||||
uint8_t serial[20] = { 0x01, 0x00 };
|
||||
uint8_t issuer[256];
|
||||
size_t issuer_len = 0;
|
||||
time_t not_before, not_after;
|
||||
uint8_t empty_subject[1] = {0};
|
||||
X509_KEY x509_key;
|
||||
uint8_t gns[256];
|
||||
size_t gnslen;
|
||||
uint8_t exts[512];
|
||||
size_t extslen;
|
||||
uint8_t cert[1024];
|
||||
uint8_t *p;
|
||||
size_t certlen;
|
||||
int path_len_constraint;
|
||||
|
||||
set_x509_name(issuer, &issuer_len, sizeof(issuer));
|
||||
time(¬_before);
|
||||
x509_validity_add_days(¬_after, not_before, 365);
|
||||
|
||||
if (x509_key_generate(&x509_key, algor, &algor_param, sizeof(algor_param)) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
gnslen = 0;
|
||||
extslen = 0;
|
||||
p = cert;
|
||||
certlen = 0;
|
||||
if (x509_general_names_add_dns_name(gns, &gnslen, sizeof(gns), "www.example.com") != 1
|
||||
|| x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts),
|
||||
X509_critical, gns, gnslen) != 1
|
||||
|| x509_cert_sign_to_der(
|
||||
X509_version_v3,
|
||||
serial, sizeof(serial),
|
||||
OID_sm2sign_with_sm3,
|
||||
issuer, issuer_len,
|
||||
not_before, not_after,
|
||||
empty_subject, 0,
|
||||
&x509_key,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
exts, extslen,
|
||||
&x509_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID),
|
||||
&p, &certlen) != 1
|
||||
|| x509_cert_check_subject(cert, certlen, 0) != 1
|
||||
|| x509_cert_check(cert, certlen, X509_cert_server_auth, &path_len_constraint) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
gnslen = 0;
|
||||
extslen = 0;
|
||||
p = cert;
|
||||
certlen = 0;
|
||||
if (x509_general_names_add_dns_name(gns, &gnslen, sizeof(gns), "www.example.com") != 1
|
||||
|| x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts),
|
||||
X509_non_critical, gns, gnslen) != 1
|
||||
|| x509_cert_sign_to_der(
|
||||
X509_version_v3,
|
||||
serial, sizeof(serial),
|
||||
OID_sm2sign_with_sm3,
|
||||
issuer, issuer_len,
|
||||
not_before, not_after,
|
||||
empty_subject, 0,
|
||||
&x509_key,
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
exts, extslen,
|
||||
&x509_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID),
|
||||
&p, &certlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (x509_cert_check_subject(cert, certlen, 0) == 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if (test_x509_cert_check_subject() != 1) goto err;
|
||||
|
||||
printf("%s all tests passed\n", __FILE__);
|
||||
return 0;
|
||||
err:
|
||||
error_print();
|
||||
return 1;
|
||||
}
|
||||
Reference in New Issue
Block a user