Update X509 and certgen tool

This commit is contained in:
Zhi Guan
2023-01-28 22:00:22 +08:00
parent c4c11ffe6b
commit ec7700c17c
16 changed files with 761 additions and 196 deletions

View File

@@ -158,6 +158,7 @@ set(tests
tls
tls13
http
http_crl
)

View File

@@ -2,7 +2,14 @@
gmssl sm2keygen -pass 1234 -out rootcakey.pem
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 -key rootcakey.pem -pass 1234 -out rootcacert.pem -key_usage keyCertSign -key_usage cRLSign -crl_uri http://pku.edu.cn/ca.crl -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \
-key rootcakey.pem -pass 1234 \
-out rootcacert.pem \
-ca -path_len_constraints 6 \
-key_usage keyCertSign -key_usage cRLSign \
-crl_http_uri http://pku.edu.cn/ca.crl -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn
gmssl certparse -in rootcacert.pem
gmssl sm2keygen -pass 1234 -out cakey.pem

View File

@@ -279,6 +279,10 @@ int x509_signed_from_der(
int *signature_algor,
const uint8_t **sig, size_t *siglen,
const uint8_t **in, size_t *inlen);
int x509_signed_verify(const uint8_t *a, size_t alen, const SM2_KEY *pub_key,
const char *signer_id, size_t signer_id_len);
int x509_signed_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen,
const char *signer_id, size_t signer_id_len);
int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
@@ -297,10 +301,6 @@ int x509_cert_sign(
const uint8_t *exts, size_t exts_len,
const SM2_KEY *sign_key,
const char *signer_id, size_t signer_id_len);
int x509_cert_verify(const uint8_t *a, size_t alen, const SM2_KEY *pub_key,
const char *signer_id, size_t signer_id_len);
int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen,
const char *signer_id, size_t signer_id_len);
int x509_cert_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen);
int x509_cert_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen);
@@ -310,6 +310,9 @@ int x509_cert_from_pem_by_index(uint8_t *a, size_t *alen, size_t maxlen, int ind
int x509_cert_from_pem_by_subject(uint8_t *a, size_t *alen, size_t maxlen, const uint8_t *name, size_t namelen, FILE *fp);
int x509_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen);
int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen,
const char *signer_id, size_t signer_id_len);
int x509_cert_get_details(const uint8_t *a, size_t alen,
int *version,
const uint8_t **serial_number, size_t *serial_number_len,

View File

@@ -173,6 +173,8 @@ int x509_crl_exts_add_authority_key_identifier(
const uint8_t *keyid, size_t keyid_len,
const uint8_t *issuer, size_t issuer_len,
const uint8_t *serial, size_t serial_len);
int x509_crl_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen,
const SM2_KEY *public_key);
int x509_crl_exts_add_issuer_alt_name(
uint8_t *exts, size_t *extslen, size_t maxlen,
int critical,
@@ -277,7 +279,7 @@ int x509_crl_from_der_ex(
const uint8_t **exts, size_t *exts_len,
int *sig_alg, const uint8_t **sig, size_t *siglen,
const uint8_t **in, size_t *inlen);
int x509_crl_validate(const uint8_t *a, size_t alen, time_t now, const uint8_t *ca_subject, size_t ca_subject_len);
int x509_crl_validate(const uint8_t *a, size_t alen, time_t now);
int x509_crl_verify(const uint8_t *a, size_t alen,
const SM2_KEY *sign_pub_key, const char *signer_id, size_t signer_id_len);
int x509_crl_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen,

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
@@ -33,21 +33,21 @@ enum {
/*
Extensions:
1. AuthorityKeyIdentifier SEQUENCE AuthorityKeyIdentifier
2. SubjectKeyIdentifier OCTET STRING
3. KeyUsage BIT STRING
1. AuthorityKeyIdentifier SEQUENCE AuthorityKeyIdentifier MUST non-critical
2. SubjectKeyIdentifier OCTET STRING MUST non-critical
3. KeyUsage BIT STRING SHOULD critical
4. CertificatePolicies SEQUENCE OF SEQUENCE CertificatePolicies
5. PolicyMappings SEQUENCE OF SEQUENCE PolicyMappings
6. SubjectAltName SEQUENCE OF SEQUENCE GeneralNames
7. IssuerAltName SEQUENCE OF SEQUENCE GeneralNames
8. SubjectDirectoryAttributes SEQUENCE OF SEQUENCE Attributes
9. BasicConstraints SEQUENCE BasicConstraints
5. PolicyMappings SEQUENCE OF SEQUENCE PolicyMappings SHOULD critical
6. SubjectAltName SEQUENCE OF SEQUENCE GeneralNames SHOULD non-critical
7. IssuerAltName SEQUENCE OF SEQUENCE GeneralNames SHOULD non-critical
8. SubjectDirectoryAttributes SEQUENCE OF SEQUENCE Attributes MUST non-critical
9. BasicConstraints SEQUENCE BasicConstraints CA: MUST critical, End-entity: MAY critical or non-critical
10. NameConstraints SEQUENCE NameConstraints
11. PolicyConstraints SEQUENCE PolicyConstraints
12. ExtKeyUsageSyntax SEQUENCE OF OBJECT IDENTIFIER
11. PolicyConstraints SEQUENCE PolicyConstraints MUST critical
12. ExtKeyUsageSyntax SEQUENCE OF OBJECT IDENTIFIER MAY critical or non-critical
13. CRLDistributionPoints SEQUENCE OF SEQUENCE DistributionPoints
14. InhibitAnyPolicy INTEGER
15. FreshestCRL SEQUENCE OF SEQUENCE DistributionPoints
14. InhibitAnyPolicy INTEGER MUST critical
15. FreshestCRL SEQUENCE OF SEQUENCE DistributionPoints MUST non-critical
*/
int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, int critical,
@@ -57,6 +57,7 @@ int x509_exts_add_authority_key_identifier(uint8_t *exts, size_t *extslen, size_
int x509_exts_add_default_authority_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen,
const SM2_KEY *public_key);
int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen);
int x509_exts_add_subject_key_identifier_ex(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const SM2_KEY *subject_key);
int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int bits);
int x509_exts_add_certificate_policies(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen);
int x509_exts_add_policy_mappings(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen);

View File

@@ -1176,7 +1176,7 @@ const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t i
{
size_t i;
if (!infos || !infos_cnt || oid <= 0) {
if (!infos || !infos_cnt || oid < 0) {
error_print();
return NULL;
}

View File

@@ -114,7 +114,7 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
tls_socket_t sock;
char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)];
int getlen;
char response[512];
char response[1024];
uint8_t *p;
size_t len;
size_t left;
@@ -150,13 +150,17 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
error_print();
goto end;
}
if ((len = recv(sock, response, sizeof(response), 0)) <= 0) {
if ((len = recv(sock, response, sizeof(response) - 1, 0)) <= 0) {
error_print();
goto end;
}
// process response header and retrieve left
if (http_parse_response(response, len, &p, contentlen, &left) != 1) {
response[len] = 0;
fprintf(stderr, "Response:\n%s\n", response);
error_print();
goto end;
}

View File

@@ -1188,7 +1188,7 @@ int x509_cert_sign(
return 1;
}
int x509_cert_verify(const uint8_t *a, size_t alen,
int x509_signed_verify(const uint8_t *a, size_t alen,
const SM2_KEY *pub_key, const char *signer_id, size_t signer_id_len)
{
int ret;
@@ -1199,7 +1199,7 @@ int x509_cert_verify(const uint8_t *a, size_t alen,
size_t siglen;
SM2_SIGN_CTX verify_ctx;
if (x509_certificate_from_der(&tbs, &tbslen, &sig_alg, &sig, &siglen, &a, &alen) != 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;
@@ -1218,8 +1218,7 @@ int x509_cert_verify(const uint8_t *a, size_t alen,
return ret;
}
// TODO: return an extra error code
int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen,
int x509_signed_verify_by_ca_cert(const uint8_t *a, size_t alen,
const uint8_t *cacert, size_t cacertlen,
const char *signer_id, size_t signer_id_len)
{
@@ -1227,7 +1226,7 @@ int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen,
SM2_KEY public_key;
if (x509_cert_get_subject_public_key(cacert, cacertlen, &public_key) != 1
|| (ret = x509_cert_verify(a, alen, &public_key, signer_id, signer_id_len)) < 0) {
|| (ret = x509_signed_verify(a, alen, &public_key, signer_id, signer_id_len)) < 0) {
error_print();
return -1;
}
@@ -1235,6 +1234,17 @@ int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen,
return ret;
}
int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen,
const uint8_t *cacert, size_t cacertlen,
const char *signer_id, size_t signer_id_len)
{
if (x509_signed_verify_by_ca_cert(a, alen, cacert, cacertlen, signer_id, signer_id_len) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_cert_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen)
{
return asn1_any_to_der(a, alen, out, outlen);

View File

@@ -775,13 +775,14 @@ int x509_issuing_distribution_point_from_der(
int ret;
const uint8_t *d;
size_t dlen;
const uint8_t *a;
size_t alen;
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
/*
if (x509_explicit_distribution_point_name_from_der(0, dist_point_choice, dist_point, dist_point_len, &d, &dlen) < 0
if (asn1_explicit_from_der(0, &a, &alen, &d, &dlen) < 0
|| asn1_implicit_boolean_from_der(1, only_contains_user_certs, &d, &dlen) < 0
|| asn1_implicit_boolean_from_der(2, only_contains_ca_certs, &d, &dlen) < 0
|| asn1_implicit_bits_from_der(3, only_some_reasons, &d, &dlen) < 0
@@ -791,7 +792,11 @@ int x509_issuing_distribution_point_from_der(
error_print();
return -1;
}
*/
if (x509_distribution_point_name_from_der(dist_point_choice, dist_point, dist_point_len, &a, &alen) != 1
|| asn1_length_is_zero(alen) != 1) {
error_print();
return -1;
}
return 1;
}
@@ -812,8 +817,8 @@ int x509_issuing_distribution_point_print(FILE *fp, int fmt, int ind, const char
if ((ret = asn1_implicit_boolean_from_der(2, &val, &d, &dlen)) < 0) goto end;
if (!ret) val = 0;
format_print(fp, fmt, ind, "onlyContainsCACerts: %s\n", asn1_boolean_name(val));
if ((ret = x509_implicit_crl_reason_from_der(3, &val, &d, &dlen)) < 0) goto end;
if (ret) format_print(fp, fmt, ind, "onlySomeReasons: %s\n", x509_crl_reason_name(val));
if ((ret = asn1_implicit_bits_from_der(3, &val, &d, &dlen)) < 0) goto end;
if (ret) x509_revoke_reasons_print(fp, fmt, ind, "onlySomeReasons", val);
if ((ret = asn1_implicit_boolean_from_der(4, &val, &d, &dlen)) < 0) goto end;
if (!ret) val = 0;
format_print(fp, fmt, ind, "indirectCRL: %s\n", asn1_boolean_name(val));
@@ -984,6 +989,16 @@ int x509_crl_exts_add_authority_key_identifier(
return 1;
}
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;
}
return 1;
}
int x509_crl_exts_add_issuer_alt_name(
uint8_t *exts, size_t *extslen, size_t maxlen,
int critical,
@@ -1005,11 +1020,15 @@ int x509_crl_exts_add_crl_number_ex(
uint8_t *p = val;
size_t vlen = 0;
if (num < 0) {
return 0;
}
exts += *extslen;
if (asn1_int_to_der(num, &p, &vlen) != 1
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|| x509_crl_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|| asn1_length_le(curlen, maxlen) != 1
|| x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) {
|| x509_crl_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) {
error_print();
return -1;
}
@@ -1021,9 +1040,11 @@ int x509_crl_exts_add_crl_number(
int critical, int num)
{
int oid = OID_ce_crl_number;
if (x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num) != 1) {
error_print();
return -1;
int ret;
if ((ret = x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
@@ -1034,9 +1055,11 @@ int x509_crl_exts_add_delta_crl_indicator(
int num)
{
int oid = OID_ce_delta_crl_indicator;
if (x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num) != 1) {
error_print();
return -1;
int ret;
if ((ret = x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
@@ -1054,25 +1077,32 @@ int x509_crl_exts_add_issuing_distribution_point(
int oid = OID_ce_issuing_distribution_point;
size_t curlen = *extslen;
uint8_t val[512];
uint8_t *p = val;
size_t vlen = 0;
uint8_t *p = val;
size_t len = 0;
exts += *extslen;
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, &curlen) != 1
|| asn1_length_le(curlen, maxlen) != 1
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, &exts, extslen) != 1) {
only_contains_attr_certs, &p, &vlen) != 1) {
error_print();
return -1;
}
exts += *extslen;
if (x509_crl_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
|| asn1_length_le(curlen, maxlen) != 1
|| x509_crl_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) {
error_print();
return -1;
}
@@ -1470,21 +1500,24 @@ int x509_crl_from_der_ex(
return 1;
}
int x509_crl_verify(const uint8_t *a, size_t alen,
const SM2_KEY *pub_key, const char *signer_id, size_t signer_id_len)
{
// change x509_cert_verify to x509_verify
if (x509_cert_verify(a, alen, pub_key, signer_id, signer_id_len) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_crl_verify_by_ca_cert(const uint8_t *a, size_t alen,
const uint8_t *cert, size_t certlen, const char *signer_id, size_t signer_id_len)
{
if (x509_cert_verify_by_ca_cert(a, alen, cert, certlen, signer_id, signer_id_len) != 1) {
const uint8_t *crl_issuer;
size_t crl_issuer_len;
const uint8_t *ca_subject;
size_t ca_subject_len;
if (x509_crl_get_issuer(a, alen, &crl_issuer, &crl_issuer_len) != 1
|| x509_cert_get_subject(cert, certlen, &ca_subject, &ca_subject_len) != 1) {
error_print();
return -1;
}
if (x509_name_equ(crl_issuer, crl_issuer_len, ca_subject, ca_subject_len) != 1) {
error_print();
return -1;
}
if (x509_signed_verify_by_ca_cert(a, alen, cert, certlen, signer_id, signer_id_len) != 1) {
error_print();
return -1;
}
@@ -1542,7 +1575,7 @@ int x509_crl_get_details(const uint8_t *a, size_t alen,
return 1;
}
int x509_crl_validate(const uint8_t *a, size_t alen, time_t now, const uint8_t *ca_subject, size_t ca_subject_len)
int x509_crl_validate(const uint8_t *a, size_t alen, time_t now)
{
int version;
int inner_sig_alg;
@@ -1568,10 +1601,6 @@ int x509_crl_validate(const uint8_t *a, size_t alen, time_t now, const uint8_t *
error_print();
return -1;
}
if (issuer_len != ca_subject_len || memcmp(issuer, ca_subject, ca_subject_len) != 0) {
error_print();
return -1;
}
// this_update <= now < next_update
if (now < this_update) {
error_print();

View File

@@ -25,24 +25,41 @@
int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen,
int oid, int critical, const uint8_t *d, size_t dlen)
int x509_ext_to_der_ex(int oid, int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
uint8_t *val = NULL;
uint8_t *p = val;
size_t curlen = *extslen;
size_t vlen = 0;
size_t len = 0;
if (!(val = malloc(32 + dlen))) {
if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1) {
error_print();
return -1;
}
if (x509_ext_id_to_der(oid, NULL, &len) != 1
|| asn1_boolean_to_der(critical, NULL, &len) < 0
|| asn1_tag_to_der(ASN1_TAG_OCTET_STRING, NULL, &len) != 1
|| asn1_length_to_der(vlen, NULL, &len) != 1
|| asn1_sequence_to_der(d, dlen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_ext_id_to_der(oid, out, outlen) != 1
|| asn1_boolean_to_der(critical, out, outlen) < 0
|| asn1_tag_to_der(ASN1_TAG_OCTET_STRING, out, outlen) != 1
|| asn1_length_to_der(vlen, out, outlen) != 1
|| asn1_sequence_to_der(d, dlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_exts_add_sequence(uint8_t *exts, size_t *extslen, size_t maxlen,
int oid, int critical, const uint8_t *d, size_t dlen)
{
size_t curlen = *extslen;
exts += *extslen;
if (asn1_sequence_to_der(d, dlen, &p, &vlen) != 1
|| x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1
if (x509_ext_to_der_ex(oid, critical, d, dlen, NULL, &curlen) != 1
|| asn1_length_le(curlen, maxlen) != 1
|| x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) {
|| x509_ext_to_der_ex(oid, critical, d, dlen, &exts, extslen) != 1) {
error_print();
return -1;
}
@@ -127,6 +144,22 @@ int x509_exts_add_subject_key_identifier(uint8_t *exts, size_t *extslen, size_t
return 1;
}
int x509_exts_add_subject_key_identifier_ex(uint8_t *exts, size_t *extslen, size_t maxlen,
int critical, const SM2_KEY *subject_key)
{
uint8_t buf[65];
uint8_t id[32];
sm2_point_to_uncompressed_octets(&subject_key->public_key, buf);
sm3_digest(buf, sizeof(buf), id);
if (x509_exts_add_subject_key_identifier(exts, extslen, maxlen, critical, id, 32) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_exts_add_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int bits)
{
int oid = OID_ce_key_usage;
@@ -1944,14 +1977,15 @@ int x509_distribution_points_to_der(const char *http_uri, size_t http_urilen,
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
{
int ret;
int tag;
if ((ret = asn1_implicit_from_der(*choice, d, dlen, in, inlen)) != 1) {
if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return -1;
}
switch (*choice) {
case 0:
case 1:
switch (tag) {
case ASN1_TAG_EXPLICIT(0):
case ASN1_TAG_EXPLICIT(1):
break;
default:
error_print();

57
tests/http_crltest.c Normal file
View File

@@ -0,0 +1,57 @@
/*
* Copyright 2014-2023 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_oid.h>
#include <gmssl/x509_crl.h>
#include <gmssl/x509_ext.h>
#include <gmssl/x509.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
static int test_x509_crl_new_from_uri(void)
{
char *tests[] = {
"http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl", // from bing.com entity-cert
"http://crl3.digicert.com/Omniroot2025.crl", // from bing.com mid-CA cert
"http://crl.globalsign.com/gsrsaovsslca2018.crl", // from baidu.com entity cert
"http://crl.globalsign.com/root-r3.crl", // from baidu.com mid-CA cert
"http://crl.globalsign.com/gs/gsorganizationvalsha2g2.crl", // from taobao.com entity cert
};
size_t i;
uint8_t *crl = NULL;
size_t crl_len;
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
if (x509_crl_new_from_uri(&crl, &crl_len, tests[i], strlen(tests[i])) != 1) {
error_print();
return -1;
}
x509_crl_print(stderr, 0, 0, "CRL", crl, crl_len);
fprintf(stderr, "\n\n");
free(crl);
crl = NULL;
}
return 1;
}
int main(void)
{
if (test_x509_crl_new_from_uri() != 1) { error_print(); return -1; }
printf("%s all tests passed\n", __FILE__);
return 1;
}

View File

@@ -307,34 +307,127 @@ static int test_x509_crl_ext_id(void)
return 1;
}
static int test_x509_issuing_distribution_point(void)
{
char *dist_point_uri = "http://www.example.com/crl.crl";
int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE;
uint8_t buf[512];
uint8_t *p = buf;
const uint8_t *cp = buf;
size_t len = 0;
const uint8_t *d;
size_t dlen;
if (x509_issuing_distribution_point_to_der(
dist_point_uri, strlen(dist_point_uri),
ASN1_TRUE,
ASN1_TRUE,
reason_flags,
ASN1_TRUE,
ASN1_TRUE, &p, &len) != 1) {
error_print();
return -1;
}
if (asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1
|| asn1_length_is_zero(len) != 1) {
error_print();
return -1;
}
x509_issuing_distribution_point_print(stderr, 0, 0, "IssuingDistributionPoint", d, dlen);
printf("%s() ok\n", __FUNCTION__);
return 1;
}
static int test_x509_issuing_distribution_point_from_der(void)
{
char *uri = "http://www.example.com/crl.crl";
int flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE;
uint8_t buf[512];
uint8_t *p = buf;
const uint8_t *cp = buf;
size_t len = 0;
int dist_point_choice;
const uint8_t *dist_point;
size_t dist_point_len;
int only_contains_user_certs;
int only_contains_ca_certs;
int only_some_reasons;
int indirect_crl;
int only_contains_attr_certs;
if (x509_issuing_distribution_point_to_der(
uri, strlen(uri),
ASN1_TRUE,
ASN1_FALSE,
flags,
-1,
ASN1_FALSE, &p, &len) != 1) {
error_print();
return -1;
}
if (x509_issuing_distribution_point_from_der(
&dist_point_choice, &dist_point, &dist_point_len,
&only_contains_user_certs,
&only_contains_ca_certs,
&only_some_reasons,
&indirect_crl,
&only_contains_attr_certs, &cp, &len) != 1
|| asn1_length_is_zero(len) != 1) {
error_print();
return -1;
}
printf("%s() ok\n", __FUNCTION__);
return 1;
}
static int test_x509_crl_exts(void)
{
/*
uint8_t exts[1024];
size_t extslen = 0;
uint8_t key_id[32];
uint8_t issuer[128];
size_t issuer_len = 0;
uint8_t serial[20];
char *http_uri = "http://www.example.com/crl.crl";
char *ldap_uri = "ldap://www.example.com/ldap";
char *ca_issuers_uri = "http://www.example.com/ca.crt";
char *ocsp_uri = "http://www.example.com/ocsp";
char *dist_point_uri = "http://www.example.com/crl.crl";
int reason_flags = X509_RF_KEY_COMPROMISE|X509_RF_CA_COMPROMISE;
if (0
|| x509_crl_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts),
X509_non_critical, key_id, sizeof(key_id), issuer, sizeof(issuer), serial, sizeof(serial)) != 1
if (rand_bytes(key_id, sizeof(key_id)) != 1
|| x509_general_names_add_uniform_resource_identifier(issuer, &issuer_len, sizeof(issuer), "http://www.example.com") != 1
|| rand_bytes(serial, sizeof(serial)) != 1) {
error_print();
return -1;
}
if (x509_crl_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts),
-1, key_id, sizeof(key_id), issuer, issuer_len, serial, sizeof(serial)) != 1
|| x509_crl_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts),
X509_non_critical, issuer_alt_name, sizeof(issuer_alt_name)) != 1
X509_non_critical, issuer, issuer_len) != 1
|| x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts),
X509_non_critical, 112) != 1
|| x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts),
X509_non_critical, 113) != 1
X509_critical, 113) != 1
|| x509_crl_exts_add_issuing_distribution_point(exts, &extslen, sizeof(exts),
X509_non_critical, dist_point_uri, strlen(dist_point_uri),
ASN1_FALSE, ASN1_FALSE, -1, ASN1_FALSE, ASN1_FALSE) != 1
X509_critical, dist_point_uri, strlen(dist_point_uri),
ASN1_FALSE, ASN1_FALSE, reason_flags, ASN1_FALSE, ASN1_FALSE) != 1
|| x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts),
X509_non_critical, http_uri, strlen(http_uri), ldap_uri, strlen(ldap_uri)) != 1
|| x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts),
X509_non_critical, ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1) {
X509_non_critical, ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1
) {
error_print();
return -1;
}
x509_crl_exts_print(stderr, 0, 0, "CRLExtensions", exts, extslen);
*/
return 1;
}
@@ -345,14 +438,23 @@ static int test_x509_cert_revoke(void)
return 1;
}
/*
http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
http://crl3.digicert.com/Omniroot2025.crl
*/
int main(void)
{
if (test_x509_crl_reason() != 1) goto err;
if (test_x509_crl_entry_ext() != 1) goto err;
if (test_x509_crl_entry_exts() != 1) goto err;
if (test_x509_revoked_cert() != 1) goto err;
// if (test_vector_gen_uri_as_general_names() != 1) goto err;
if (test_vector_gen_uri_as_general_names() != 1) goto err;
if (test_x509_crl_ext_id() != 1) goto err;
if (test_x509_issuing_distribution_point() != 1) goto err;
if (test_x509_issuing_distribution_point_from_der() != 1) goto err;
if (test_x509_crl_exts() != 1) goto err;
printf("%s all tests passed\n", __FILE__);
return 0;
err:

View File

@@ -345,11 +345,14 @@ static int test_x509_cert(void)
format_bytes(stderr, 0, 4, "cert", cert, certlen);
x509_cert_print(stderr, 0, 4, "Certificate", cert, certlen);
/*
// TODO: use the same cert to verify?
if (x509_cert_verify(cert, certlen, &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
error_print();
return -1;
}
printf("x509_cert_verify() success\n");
*/
test_x509_cert_get(cert, certlen);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2023 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.
@@ -17,15 +17,92 @@
#include <gmssl/pkcs8.h>
#include <gmssl/error.h>
#include <gmssl/x509.h>
#include <gmssl/x509_oid.h>
#include <gmssl/x509_ext.h>
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num "
"-key file [-pass pass] "
"-crl_uri uri"
"-ca_issuers_uri uri -ocsp_uri uri"
"[-key_usage str]* [-ocsp uri] [-out file]";
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str"
" -days num"
" -key file -pass pass"
" [-gen_authority_key_id]"
" [-gen_subject_key_id]"
" [-key_usage str]*"
" [-subject_dns_name str]*"
" [-issuer_dns_name str]*"
" [-ca -path_len_constraints num]"
" [-ext_key_usage str]*"
" [-crl_http_uri uri] [-crl_ldap_uri uri]"
" [-inhibit_any_policy num]"
" [-ca_issuers_uri uri] [-ocsp_uri uri uri]"
" [-out file]";
static char *usage =
"Options\n"
"\n"
" -serial_len num Serial number length in bytes\n"
" -days num Validity peroid in days\n"
" -key file Private key file in PEM format\n"
" -pass pass Password for decrypting private key file\n"
" -out file Output certificate file in PEM format\n"
"\n"
" Subject and Issuer options\n"
"\n"
" -C str Country\n"
" -ST str State or province name\n"
" -L str Locality\n"
" -O str Organization\n"
" -OU str Organizational unit\n"
" -CN str Common name\n"
"\n"
" Extension options\n"
"\n"
" -gen_authority_key_id Generate AuthorityKeyIdentifier extension use SM3\n"
" -gen_subject_key_id Generate SubjectKeyIdentifier extension use SM3\n"
" -key_usage str Add KeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" digitalSignature\n"
" nonRepudiation\n"
" keyEncipherment\n"
" dataEncipherment\n"
" keyAgreement\n"
" keyCertSign\n"
" cRLSign\n"
" encipherOnly\n"
" decipherOnly\n"
" -subject_dns_name str Add DNS name to SubjectAltName extension\n"
" this option can be called multi-times\n"
" -issuer_dns_name str Add DNS name to IssuerAltName extension\n"
" this option can be called multi-times\n"
" -ca Set cA of BasicConstaints extension\n"
" -path_len_constraints num Set pathLenConstaints of BasicConstaints extension\n"
" -ext_key_usage str Set ExtKeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" anyExtendedKeyUsage\n"
" serverAuth\n"
" clientAuth\n"
" codeSigning\n"
" emailProtection\n"
" timeStamping\n"
" OCSPSigning\n"
" -crl_http_uri uri Set HTTP URI of CRL of CRLDistributionPoints extension\n"
" -crl_ldap_uri uri Set LDAP URI of CRL of CRLDistributionPoints extension\n"
" -inhibit_any_policy num Set skipCerts number of InhibitAnyPolicy extension\n"
" -ca_issuers_uri uri Set URI of the CA certificate in DER-encoding o FreshestCRL extension\n"
" -ocsp_uri uri Set OCSP URI of FreshestCRL extension\n"
"\n"
"Examples\n"
"\n"
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n"
" -key rootcakey.pem -pass P@ssw0rd \\\n"
" -ca -path_len_constraints 6 \\\n"
" -key_usage keyCertSign -key_usage cRLSign \\\n"
" -crl_http_uri http://pku.edu.cn/ca.crl \\\n"
" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n"
" -out rootcacert.pem\n"
"\n";
static int ext_key_usage_set(int *usages, const char *usage_name)
@@ -43,48 +120,100 @@ int certgen_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *str;
// SerialNumber
uint8_t serial[20];
int serial_len = 12;
// Issuer, Subject
uint8_t name[256];
size_t namelen;
char *country = NULL;
char *state = NULL;
char *locality = NULL;
char *org = NULL;
char *org_unit = NULL;
char *common_name = NULL;
int days = 0;
int key_usage = 0;
char *ocsp = NULL;
char *crl_uri = NULL;
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
uint8_t serial[12];
uint8_t name[256];
size_t namelen;
// Validity
int days = 0;
time_t not_before;
time_t not_after;
uint8_t exts[512];
size_t extslen = 0;
// Private Key
char *keyfile = NULL;
char *pass = NULL;
FILE *keyfp = NULL;
SM2_KEY sm2_key;
uint8_t cert[1024];
uint8_t cert[4096];
size_t certlen;
FILE *outfp = stdout;
char *outfile = NULL;
// Extensions
uint8_t exts[4096];
size_t extslen = 0;
// AuthorityKeyIdentifier
int gen_authority_key_id = 0;
// SubjectKeyIdentifier
int gen_subject_key_id = 0;
// KeyUsage
int key_usage = 0;
// SubjectAltName
uint8_t subject_alt_name[2048];
size_t subject_alt_name_len = 0;
// IssuerAltName
uint8_t issuer_alt_name[512];
size_t issuer_alt_name_len = 0;
// BasicConstraints
int ca = -1;
int path_len_constraints = -1;
// ExtKeyUsageSyntax
int ext_key_usages[12];
size_t ext_key_usages_cnt = 0;
// CRLDistributionPoints
char *crl_http_uri = NULL;
char *crl_ldap_uri = NULL;
// InhibitAnyPolicy
int inhibit_any_policy = -1;
// FreshestCRL
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
fprintf(stderr, "usage: gmssl %s %s\n", prog, options);
return 1;
}
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
printf("usage: gmssl %s %s\n\n", prog, options);
printf(usage, prog);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-serial_len")) {
if (--argc < 1) goto bad;
serial_len = atoi(*(++argv));
if (serial_len <= 0 || serial_len > sizeof(serial)) {
fprintf(stderr, "%s: invalid '-serial_len' value, need a number less than %zu\n", prog, sizeof(serial));
goto end;
}
} else if (!strcmp(*argv, "-CN")) {
if (--argc < 1) goto bad;
common_name = *(++argv);
@@ -97,6 +226,10 @@ int certgen_main(int argc, char **argv)
} else if (!strcmp(*argv, "-C")) {
if (--argc < 1) goto bad;
country = *(++argv);
if (strlen(country) != 2) {
fprintf(stderr, "%s: invalid '-C' value, need 2-char country name such as 'CN', 'US'\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ST")) {
if (--argc < 1) goto bad;
state = *(++argv);
@@ -107,26 +240,10 @@ int certgen_main(int argc, char **argv)
if (--argc < 1) goto bad;
days = atoi(*(++argv));
if (days <= 0) {
fprintf(stderr, "%s: invalid '-days' value\n", prog);
fprintf(stderr, "%s: invalid `-days` value, need a positive number\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-key_usage")) {
char *usage;
if (--argc < 1) goto bad;
usage = *(++argv);
if (ext_key_usage_set(&key_usage, usage) != 1) {
fprintf(stderr, "%s: invalid -key_usage value '%s'\n", prog, usage);
goto end;
}
} else if (!strcmp(*argv, "-crl_uri")) {
if (--argc < 1) goto bad;
crl_uri = *(++argv);
} else if (!strcmp(*argv, "-ca_issuers_uri")) {
if (--argc < 1) goto bad;
ca_issuers_uri = *(++argv);
} else if (!strcmp(*argv, "-ocsp_uri")) {
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
keyfile = *(++argv);
@@ -134,9 +251,78 @@ int certgen_main(int argc, char **argv)
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-pass")) {
if (--argc < 1) goto bad;
pass = *(++argv);
} else if (!strcmp(*argv, "-gen_authority_key_id")) {
gen_authority_key_id = 1;
} else if (!strcmp(*argv, "-gen_subject_key_id")) {
gen_subject_key_id = 1;
} else if (!strcmp(*argv, "-key_usage")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (ext_key_usage_set(&key_usage, str) != 1) {
fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, str);
goto end;
}
} else if (!strcmp(*argv, "-subject_dns_name")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_general_names_add_dns_name(
subject_alt_name, &subject_alt_name_len, sizeof(subject_alt_name), str) != 1) {
fprintf(stderr, "%s: inner error on processing `-subject_dns_name`\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-issuer_dns_name")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_general_names_add_dns_name(
issuer_alt_name, &issuer_alt_name_len, sizeof(issuer_alt_name), str) != 1) {
fprintf(stderr, "%s: inner error on processing `-issuer_dns_name`\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ca")) {
ca = 1;
} else if (!strcmp(*argv, "-path_len_constraints")) {
if (--argc < 1) goto bad;
path_len_constraints = atoi(*(++argv));
if (path_len_constraints <= 0) {
fprintf(stderr, "%s: invalid `-path_len_constraints` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ext_key_usage")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_key_purpose_from_name(str) <= 0) {
fprintf(stderr, "%s: invalid `-ext_key_usage` value '%s'\n", prog, str);
goto end;
}
if (ext_key_usages_cnt >= sizeof(ext_key_usages)/sizeof(ext_key_usages[0])) {
fprintf(stderr, "%s: too much `-ext_key_usage` options\n", prog);
goto end;
}
ext_key_usages[ext_key_usages_cnt++] = x509_key_purpose_from_name(str);
} else if (!strcmp(*argv, "-crl_http_uri")) {
if (--argc < 1) goto bad;
crl_http_uri = *(++argv);
} else if (!strcmp(*argv, "-crl_ldap_uri")) {
if (--argc < 1) goto bad;
crl_ldap_uri = *(++argv);
} else if (!strcmp(*argv, "-inhibit_any_policy")) {
if (--argc < 1) goto bad;
inhibit_any_policy = atoi(*(++argv));
if (inhibit_any_policy < 0) {
fprintf(stderr, "%s: invalid `-inhibit_any_policy` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ca_issuers_uri")) {
if (--argc < 1) goto bad;
ca_issuers_uri = *(++argv);
} else if (!strcmp(*argv, "-ocsp_uri")) {
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
outfile = *(++argv);
@@ -148,7 +334,7 @@ int certgen_main(int argc, char **argv)
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
fprintf(stderr, "%s: `%s` value missing\n", prog, *argv);
goto end;
}
@@ -157,71 +343,137 @@ bad:
}
if (!common_name) {
fprintf(stderr, "%s: '-CN' option required\n", prog);
fprintf(stderr, "%s: option `-CN` required\n", prog);
goto end;
}
if (!days) {
fprintf(stderr, "%s: '-days' option required\n", prog);
fprintf(stderr, "%s: option `-days` required\n", prog);
goto end;
}
if (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
fprintf(stderr, "%s: option `-key` required\n", prog);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
fprintf(stderr, "%s: option `-pass` required\n", prog);
goto end;
}
if (!key_usage) {
fprintf(stderr, "%s: '-key_usage' option required\n", prog);
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
fprintf(stderr, "%s: load private key failed\n", prog);
goto end;
}
if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 1, key_usage) != 1
|| x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), 1, 1, -1) != 1
|| x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
// Serial
if (rand_bytes(serial, sizeof(serial)) != 1) {
fprintf(stderr, "%s: RNG error\n", prog);
goto end;
}
if (crl_uri) {
if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), 0,
crl_uri, strlen(crl_uri), NULL, 0) != 1) {
// Issuer, Subject
if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) {
fprintf(stderr, "%s: set Issuer/Subject Name error\n", prog);
goto end;
}
// Validity
time(&not_before);
if (x509_validity_add_days(&not_after, not_before, days) != 1) {
fprintf(stderr, "%s: set Validity failure\n", prog);
goto end;
}
// Extensions
if (gen_authority_key_id) {
if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) {
fprintf(stderr, "%s: set AuthorityKeyIdentifier extension failure\n", prog);
goto end;
}
}
if (gen_subject_key_id) {
if (x509_exts_add_subject_key_identifier_ex(exts, &extslen, sizeof(exts), -1, &sm2_key) != 1) {
fprintf(stderr, "%s: set SubjectKeyIdentifier extension failure\n", prog);
goto end;
}
}
if (key_usage) {
if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) {
fprintf(stderr, "%s: set KeyUsage extension failure\n", prog);
goto end;
}
}
// no CertificatePolicies
// no PolicyMappings
if (subject_alt_name_len) {
if (x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts),
-1, subject_alt_name, subject_alt_name_len) != 1) {
fprintf(stderr, "%s: set SubjectAltName extension failure\n", prog);
goto end;
}
}
if (issuer_alt_name_len) {
if (x509_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts),
-1, issuer_alt_name, issuer_alt_name_len) != 1) {
fprintf(stderr, "%s: set IssuerAltName extension failure\n", prog);
goto end;
}
}
// no SubjectDirectoryAttributes
if (path_len_constraints) {
if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts),
X509_critical, ca, path_len_constraints) != 1) {
fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog);
goto end;
}
}
// no NameConstraints
// no PolicyConstraints
if (ext_key_usages_cnt) {
if (x509_exts_add_ext_key_usage(exts, &extslen, sizeof(exts),
-1, ext_key_usages, ext_key_usages_cnt) != 1) {
fprintf(stderr, "%s: set ExtKeyUsage extension failure\n", prog);
goto end;
}
}
if (crl_http_uri || crl_ldap_uri) {
if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts),
-1,
crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0,
crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) {
fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog);
error_print();
return -1;
}
}
if (inhibit_any_policy >= 0) {
if (x509_exts_add_inhibit_any_policy(exts, &extslen, sizeof(exts),
X509_critical, inhibit_any_policy) != 1) {
fprintf(stderr, "%s: set InhibitAnyPolicy extension failure\n", prog);
goto end;
}
}
if (ca_issuers_uri || ocsp_uri) {
if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0,
ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1) {
fprintf(stderr, "%s: error\n", prog);
ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0,
ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) {
fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog);
goto end;
}
}
time(&not_before);
if (rand_bytes(serial, sizeof(serial)) != 1
|| x509_name_set(name, &namelen, sizeof(name),
country, state, locality, org, org_unit, common_name) != 1
|| x509_validity_add_days(&not_after, not_before, days) != 1
|| x509_cert_sign(
cert, &certlen, sizeof(cert),
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
name, namelen,
not_before, not_after,
name, namelen,
&sm2_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
name, namelen,
not_before, not_after,
name, namelen,
&sm2_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {

View File

@@ -14,15 +14,31 @@
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/x509_ext.h>
#include <gmssl/x509_crl.h>
#include <gmssl/file.h>
static const char *options =
"-in RevokedCertificate.der"
" -key pem -pass str -cert pem"
" [-next_update timestamp] "
" [-out crl.der]";
static const char *usage = "-in revoked_certs.der -key pem -pass str -cacert pem [-next_update time] "
"[-gen_authority_key_id] [-crl_num num] [-delta_crl_indicator num] [-ca_issuers_uri uri] [-ocsp_uri uri] [-out crl.der]";
static void print_options(const char *prog)
{
printf("Options\n");
printf("\n");
printf(" -in revoked_certs.der To be revoked certificate list\n");
printf(" This input file format is DER-encoding of SEQUENCE OF RevokedCertificate\n");
printf(" revoked_certs.der can be generated by `gmssl certrevoke`\n");
printf("\n");
printf(" -key pkcs8.pem The issuer private key.\n");
printf("\n");
printf(" -cacert cert.pem The issuer certificate.\n");
printf("\n");
printf(" -next_update time Optional CRL attribute.\n");
printf("\n");
printf(" -out crl.der Output CRL in DER-encoding\n");
}
int crlgen_main(int argc, char **argv)
{
@@ -44,6 +60,16 @@ int crlgen_main(int argc, char **argv)
size_t issuer_len;
time_t next_update = -1;
uint8_t exts[512];
size_t extslen = 0;
int gen_authority_key_id = 0;
int crl_num = -1;
int delta_crl_indicator = -1;
char *http_uri = NULL;
char *ldap_uri = NULL;
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
uint8_t outbuf[64 * 1024];
uint8_t *out = outbuf;
size_t outlen = 0;
@@ -53,7 +79,9 @@ int crlgen_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
printf("usage: %s %s\n", prog, usage);
printf("\n");
print_options(prog);
goto end;
} else if (!strcmp(*argv, "-in")) {
@@ -87,7 +115,29 @@ int crlgen_main(int argc, char **argv)
}
} else if (!strcmp(*argv, "-next_update")) {
if (--argc < 1) goto bad;
next_update = atoi(*(++argv));
if (asn1_time_from_str(0, &next_update, *(++argv)) != 1) {
fprintf(stderr, "%s: invalid time format for '-next_update', should be 'YYYYMMDDHHMMSSZ'\n", prog);
goto bad;
}
} else if (!strcmp(*argv, "-gen_authority_key_id")) {
gen_authority_key_id = 1;
} else if (!strcmp(*argv, "-crl_num")) {
if (--argc < 1) goto bad;
crl_num = atoi(*(++argv));
} else if (!strcmp(*argv, "-delta_crl_indicator")) {
if (--argc < 1) goto bad;
delta_crl_indicator = atoi(*(++argv));
} else if (!strcmp(*argv, "-http_uri")) {
if (--argc < 1) goto bad;
http_uri = *(++argv);
} else if (!strcmp(*argv, "-ldap_uri")) {
if (--argc < 1) goto bad;
ldap_uri = *(++argv);
} else if (!strcmp(*argv, "-ca_issuers_uri")) {
ca_issuers_uri = *(++argv);
} else if (!strcmp(*argv, "-ocsp_uri")) {
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
goto end;
@@ -121,7 +171,7 @@ bad:
if (!revoked_certs || !revoked_certs_len) {
fprintf(stderr, "usage: %s %s\n", prog, options);
fprintf(stderr, "usage: %s %s\n", prog, usage);
goto end;
}
@@ -134,13 +184,41 @@ bad:
goto end;
}
if (gen_authority_key_id) {
if (x509_crl_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sign_key) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
}
if (x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), -1, crl_num) < 0
|| x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), X509_critical, delta_crl_indicator) < 0) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
if (ca_issuers_uri || ocsp_uri) {
if (x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), -1,
ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0,
ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
}
if (http_uri || ldap_uri) {
if (x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), -1,
http_uri, http_uri ? strlen(http_uri) : 0,
ldap_uri, ldap_uri ? strlen(ldap_uri) : 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
}
if (x509_crl_sign_to_der(
X509_version_v2,
OID_sm2sign_with_sm3,
issuer, issuer_len,
time(NULL), next_update,
revoked_certs, revoked_certs_len,
NULL, 0,
extslen ? exts : NULL, extslen,
&sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&out, &outlen) != 1) {

View File

@@ -104,7 +104,6 @@ bad:
fprintf(stderr, "%s: read CRL failure\n", prog);
goto end;
}
if (x509_crl_get_issuer(crl, crllen, &subject, &subject_len) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
@@ -113,6 +112,10 @@ bad:
fprintf(stderr, "%s: read certificate failure\n", prog);
goto end;
}
if (x509_crl_validate(crl, crllen, time(NULL)) != 1) {
fprintf(stderr, "%s: invalid CRL data or format\n", prog);
goto end;
}
if ((rv = x509_crl_verify_by_ca_cert(crl, crllen, cacert, cacertlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID))) < 0) {
fprintf(stderr, "%s: verification inner error\n", prog);
goto end;
@@ -127,24 +130,3 @@ end:
if (in) free(in);
return ret;
}