Update CRL related

to be continue ...
This commit is contained in:
Zhi Guan
2023-01-17 00:43:36 +08:00
parent e3a0f73e0e
commit dc80fea1f6
8 changed files with 513 additions and 66 deletions

View File

@@ -278,8 +278,9 @@ int asn1_generalized_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, s
#define asn1_implicit_generalized_time_to_der(i,tv,out,outlen) asn1_generalized_time_to_der_ex(ASN1_TAG_IMPLICIT(i),tv,out,outlen)
#define asn1_implicit_generalized_time_from_der(i,tv,in,inlen) asn1_generalized_time_from_der_ex(ASN1_TAG_IMPLICIT(i),tv,in,inlen)
#define asn1_sequence_to_der(d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen)
#define asn1_sequence_from_der(d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen)
// BasicConstraints might be an empty sequence in entity certificates
#define asn1_sequence_to_der(d,dlen,out,outlen) asn1_type_to_der(ASN1_TAG_SEQUENCE,d,dlen,out,outlen)
#define asn1_sequence_from_der(d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_SEQUENCE,d,dlen,in,inlen)
#define asn1_implicit_sequence_to_der(i,d,dlen,out,outlen) asn1_nonempty_type_to_der(ASN1_TAG_EXPLICIT(i),d,dlen,out,outlen)
#define asn1_implicit_sequence_from_der(i,d,dlen,in,inlen) asn1_nonempty_type_from_der(ASN1_TAG_EXPLICIT(i),d,dlen,in,inlen)
@@ -305,6 +306,7 @@ int asn1_header_to_der(int tag, size_t dlen, uint8_t **out, size_t *outlen);
#define asn1_octet_string_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_OCTET_STRING,dlen,out,outlen)
#define asn1_sequence_header_to_der_ex(tag,dlen,out,outlen) asn1_header_to_der(tag,dlen,out,outlen)
#define asn1_sequence_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_SEQUENCE,dlen,out,outlen)
#define asn1_implicit_sequence_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen)

View File

@@ -85,9 +85,11 @@ enum {
OID_ce_freshest_crl,
OID_netscape_cert_type,
OID_netscape_cert_comment,
OID_cert_authority_info_access,
OID_ct_precertificate_scts,
OID_ad_ca_issuers,
OID_ad_ocsp,
// CRL Extensions
//OID_ce_authority_key_identifier,
//OID_ce_issuer_alt_name,

View File

@@ -67,6 +67,9 @@ int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, i
int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen);
int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int skip_certs);
int x509_exts_add_freshest_crl(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen);
int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t maxlen, int critical,
const char *crt_uri, size_t crt_urilen, // crt_uri is the URI (http://examaple.com/subCA.crt) of DER-encoded CA cert
const char *ocsp_uri, size_t ocsp_urilen);
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);
@@ -466,6 +469,10 @@ DistributionPointName ::= CHOICE {
fullName [0] IMPLICIT GeneralNames, -- SEQUENCE OF
nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } -- SET OF
*/
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_uri_as_explicit_distribution_point_name_to_der(int index, const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_distribution_point_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label,const uint8_t *a, size_t alen);
@@ -480,6 +487,10 @@ DistributionPoint ::= SEQUENCE {
reasons [1] IMPLICIT ReasonFlags OPTIONAL,
cRLIssuer [2] IMPLICIT GeneralNames OPTIONAL }
*/
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_distribution_points_to_der(const char *http_uri, size_t http_urilen,
const char *ldap_uri, size_t ldap_urilen, uint8_t **out, size_t *outlen);
int x509_distribution_point_to_der(
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
@@ -497,8 +508,7 @@ int x509_distribution_points_add_distribution_point(uint8_t *d, size_t *dlen, si
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len);
int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
#define x509_distribution_points_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen)
#define x509_distribution_points_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen)
/*
CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
@@ -544,6 +554,37 @@ int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label,
int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
int *path_len_constraints);
/*
AuthorityInfoAccessSyntax ::= SEQUENCE OF AccessDescription
AccessDescription ::= SEQUENCE {
accessMethod OBJECT IDENTIFIER,
accessLocation GeneralName }
accessMethods:
OID_ad_ca_issuers
OID_ad_ocsp
*/
const char *x509_access_method_name(int oid);
int x509_access_method_from_name(const char *name);
int x509_access_method_to_der(int oid, uint8_t **out, size_t *outlen);
int x509_access_method_from_der(int *oid, const uint8_t **in, size_t *inlen);
int x509_access_description_to_der(int oid, const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_access_description_from_der(int *oid, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen);
int x509_access_description_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
int x509_authority_info_access_to_der(
const char *crt_uri, size_t crt_urilen,
const char *ocsp_uri, size_t ocsp_urilen,
uint8_t **out, size_t *outlen);
int x509_authority_info_access_from_der(
const char **crt_uri, size_t *crt_urilen,
const char **ocsp_uri, size_t *ocsp_urilen,
const uint8_t **in, size_t *inlen);
int x509_authority_info_access_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
#ifdef __cplusplus
}
#endif

View File

@@ -826,6 +826,7 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
case OID_ce_freshest_crl: return x509_freshest_crl_print(fp, fmt, ind, name, p, len);
case OID_netscape_cert_type: return x509_netscape_cert_type_print(fp, fmt, ind, name, ival);
case OID_netscape_cert_comment: return format_string(fp, fmt, ind, name, p, len);
case OID_pe_authority_info_access: return x509_authority_info_access_print(fp, fmt, ind, name, p, len);
default: format_bytes(fp, fmt, ind, "extnValue", p, len);
}
return 1;

View File

@@ -525,6 +525,7 @@ int x509_issuing_distribution_point_to_der(
int only_contains_attr_certs,
uint8_t **out, size_t *outlen)
{
/*
size_t len = 0;
if (x509_explicit_distribution_point_name_to_der(0, dist_point_choice, dist_point, dist_point_len, NULL, &len) < 0
|| asn1_implicit_boolean_to_der(1, only_contains_user_certs, NULL, &len) < 0
@@ -542,6 +543,7 @@ int x509_issuing_distribution_point_to_der(
error_print();
return -1;
}
*/
return 1;
}
@@ -554,6 +556,7 @@ int x509_issuing_distribution_point_from_der(
int *only_contains_attr_certs,
const uint8_t **in, size_t *inlen)
{
/*
int ret;
const uint8_t *d;
size_t dlen;
@@ -572,6 +575,7 @@ int x509_issuing_distribution_point_from_der(
error_print();
return -1;
}
*/
return 1;
}

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
@@ -288,6 +288,13 @@ int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t
int critical, const uint8_t *d, size_t dlen)
{
int oid = OID_ce_crl_distribution_points;
// The extension SHOULD be non-critical, but this profile
// RECOMMENDS support for this extension by CAs and applications.
if (critical) {
error_print();
return -1;
}
return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen);
}
@@ -438,11 +445,23 @@ err:
return -1;
}
// GeneralName CHOICE 中有的是基本类型有的是SEQUENCE在设置标签时是否有区别
// 这里是否支持OPTIONAL??
int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
return asn1_implicit_to_der(choice, d, dlen, out, outlen);
switch (choice) {
case X509_gn_rfc822_name:
case X509_gn_dns_name:
case X509_gn_uniform_resource_identifier:
case X509_gn_ip_address:
if (asn1_implicit_to_der(choice, d, dlen, out, outlen) != 1) {
error_print();
return -1;
}
default:
error_print();
return -1;
}
return 1;
}
int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
@@ -1284,6 +1303,11 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t *
if (ret < 0) error_print();
return ret;
}
if (!d || !dlen) {
*ca = -1;
*path_len_cons = -1;
return 1;
}
if (asn1_boolean_from_der(ca, &d, &dlen) < 0
|| asn1_int_from_der(path_len_cons, &d, &dlen) < 0
|| asn1_length_is_zero(dlen) != 1) {
@@ -1294,18 +1318,32 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t *
error_print();
return -1;
}
if (*ca < 0) *ca = 0;
// from_der() MUST NOT set default value to *ca
return 1;
}
int x509_basic_constraints_validate(int ca, int path_len_cons, int cert_type)
{
/*
entity_cert:
ca = -1 or 0
path_len_constraints = -1
first_ca_cert:
ca = 1
path_len_constraints = 0
middle_ca_cert:
ca = 1
path_len_constraints = -1 or > 0
root_ca_cert:
ca = 1
path_len_constraints = -1 or > 0 (=0 might be ok?)
*/
if (cert_type == X509_cert_ca) {
if (ca != 1) {
error_print();
return -1;
}
if (path_len_cons < 0 || path_len_cons > 6) {
if (path_len_cons < 0 || path_len_cons > 6) {
error_print();
return -1;
}
@@ -1325,6 +1363,11 @@ int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label,
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
// BasicConstraints might be an empty sequence in entity certificates
if (!d || !dlen) {
return 1;
}
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值是否编码均输出结果
@@ -1656,6 +1699,35 @@ int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, cons
return 1;
}
/*
CRL Distribution Points
* 假设证书的cRLIssuer和issuer一致即签发证书的CA也签发了证书所属的CRL
不支持可选的cRLIssuer编码解码时忽略cRLIssuer
编解、解码时均要求DistributionPoint中包含distributionPoint
* 如果证书扩展中不包含reasons那么在CRL中必须包含完整的reasons。
证书扩展中包含reasons逻辑上意味由不同的CRL包含因不同原因注销的证书RFC不推荐这种方式
* 编码时最多支持2个DistributionPoint分别用于HTTP和LDAP的URI
即DistributionPointName CHOICE GeneralNames其中只有一个GeneralName CHOICE uri
* 解码时对每个解析成功的DistributionPoint的uri进行判断
最多返回一个http和一个ldap其他协议的uri被忽略
* RFC要求每个DistributionPoint中至少包含一个HTTP或LDAP uri
* 解码时不支持DistributionPointName为nameRelativeToCRLIssuer
解码时DistributionPointName为(GeneralNames)fullName时只返回第一个CHOICE为uri的GeneralName
* 当uri为HTTP时CRL文件为DER编码
* 当uri为LDAP时
如 ldap://ldap.example.com/cn=example%20CA,dc=example,dc=com?certificateRevocationList;binary
如 ldap:///cn=example%20CA,dc=example,dc=com?certificateRevocationList;binary
必须包含 DN, certificateRevocationList 应包含host部分
*/
static const char *x509_revoke_reasons[] = {
"unused",
"keyCompromise",
@@ -1706,20 +1778,68 @@ int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int
return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reasons, x509_revoke_reasons_count, bits);
}
int x509_distribution_point_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
switch (choice) {
case 0:
case 1:
if (asn1_implicit_to_der(choice, d, dlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
default:
int choice = X509_gn_uniform_resource_identifier;
size_t len = 0;
if (x509_general_name_to_der(choice, (uint8_t *)uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der_ex(tag, len, out, outlen) != 1
|| x509_general_name_to_der(choice, (uint8_t *)uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
if (x509_uri_as_general_names_to_der_ex(ASN1_TAG_EXPLICIT(0), uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_explicit_distribution_point_name_to_der(int index,
const char *uri, size_t urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (x509_uri_as_distribution_point_name_to_der(uri, urilen, NULL, &len) != 1
|| asn1_explicit_header_to_der(index, len, out, outlen) != 1
|| x509_uri_as_distribution_point_name_to_der(uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_distribution_points_to_der(const char *http_uri, size_t http_urilen,
const char *ldap_uri, size_t ldap_urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (x509_uri_as_distribution_point_to_der(http_uri, http_urilen, NULL, &len) < 0
|| x509_uri_as_distribution_point_to_der(ldap_uri, ldap_urilen, NULL, &len) < 0
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_distribution_point_to_der(http_uri, http_urilen, out, outlen) < 0
|| x509_uri_as_distribution_point_to_der(ldap_uri, ldap_urilen, out, outlen) < 0) {
error_print();
return -1;
}
return 1;
}
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
@@ -1741,20 +1861,6 @@ int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t
return 1;
}
int x509_explicit_distribution_point_name_to_der(int index, int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
// 注意要能够解决d == NULL的情况
error_print();
return -1;
}
int x509_explicit_distribution_point_name_from_der(int index, int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
{
// 注意要能够解决d == NULL的情况
error_print();
return -1;
}
int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
{
int tag;
@@ -1783,6 +1889,7 @@ int x509_distribution_point_to_der(
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
uint8_t **out, size_t *outlen)
{
/*
size_t len = 0;
if (x509_explicit_distribution_point_name_to_der(0, dist_point_choice, dist_point, dist_point_len, NULL, &len) < 0
|| asn1_implicit_bits_to_der(1, reasons, NULL, &len) < 0
@@ -1794,6 +1901,7 @@ int x509_distribution_point_to_der(
error_print();
return -1;
}
*/
return 1;
}
@@ -1802,6 +1910,7 @@ int x509_distribution_point_from_der(
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen)
{
/*
int ret;
const uint8_t *d;
size_t dlen;
@@ -1817,6 +1926,7 @@ int x509_distribution_point_from_der(
error_print();
return -1;
}
*/
return 1;
}
@@ -1845,34 +1955,6 @@ err:
return -1;
}
/*
extnID: CRLDistributionPoints (2.5.29.31)
DistributionPoint
distributionPoint
fullName
GeneralName
URI: http://www.rootca.gov.cn/Civil_Servant_arl/Civil_Servant_ARL.crl
DistributionPoint
distributionPoint
fullName
GeneralName
URI: ldap://ldap.rootca.gov.cn:390/CN=Civil_Servant_ARL,OU=ARL,O=NRCAC,C=CN
*/
int x509_distribution_points_add_url(uint8_t *d, size_t *dlen, size_t maxlen, const char *url)
{
return 0;
}
int x509_distribution_points_add_distribution_point(uint8_t *d, size_t *dlen, size_t maxlen,
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len)
{
error_print();
return -1;
}
int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
const uint8_t *p;
@@ -1992,4 +2074,304 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
return 1;
}
// AuthorityInfoAccess Extension
static uint32_t oid_ad_ocsp[] = { oid_ad,1 };
static uint32_t oid_ad_ca_issuers[] = { oid_ad,2 };
#define cnt(oid) (sizeof(oid)/sizeof((oid)[0]))
static const ASN1_OID_INFO access_methods[] = {
{ OID_ad_ocsp, "OCSP", oid_ad_ocsp, oid_cnt(oid_ad_ocsp) },
{ OID_ad_ca_issuers, "CAIssuers", oid_ad_ca_issuers, oid_cnt(oid_ad_ca_issuers) },
};
const char *x509_access_method_name(int oid)
{
const ASN1_OID_INFO *info;
if (!(info = asn1_oid_info_from_oid(access_methods, cnt(access_methods), oid))) {
error_print();
return NULL;
}
return info->name;
}
int x509_access_method_from_name(const char *name)
{
const ASN1_OID_INFO *info;
if (!(info = asn1_oid_info_from_name(access_methods, cnt(access_methods), name))) {
error_print();
return OID_undef;
}
return info->oid;
}
int x509_access_method_to_der(int oid, uint8_t **out, size_t *outlen)
{
const ASN1_OID_INFO *info;
if (!(info = asn1_oid_info_from_oid(access_methods, cnt(access_methods), oid))) {
error_print();
return -1;
}
if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_access_method_from_der(int *oid, const uint8_t **in, size_t *inlen)
{
int ret;
const ASN1_OID_INFO *info;
uint32_t nodes[32];
size_t nodes_cnt;
if ((ret = asn1_oid_info_from_der_ex(&info, nodes, &nodes_cnt, access_methods, cnt(access_methods), in, inlen)) != 1) {
if (ret < 0) error_print();
else *oid = -1;
return ret;
}
*oid = info->oid;
return 1;
}
// currently AccessDescription not support values of SubjectInfoAccess extension
int x509_access_description_to_der(int oid, const char *uri, size_t urilen, uint8_t **out, size_t *outlen)
{
const int uri_choice = X509_gn_uniform_resource_identifier;
size_t len = 0;
if (oid != OID_ad_ocsp && oid != OID_ad_ca_issuers) {
error_print();
return -1;
}
if (!uri || !urilen) {
error_print();
return -1;
}
if (x509_access_method_to_der(oid, NULL, &len) != 1
|| x509_general_name_to_der(uri_choice, (const uint8_t *)uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_access_method_to_der(oid, out, outlen) != 1
|| x509_general_name_to_der(uri_choice, (const uint8_t *)uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_access_description_from_der(int *oid, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *d;
size_t dlen;
int uri_choice;
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
else {
*oid = -1;
*uri = NULL;
*urilen = 0;
}
return ret;
}
if (x509_access_method_from_der(oid, &d, &dlen) != 1
|| x509_general_name_from_der(&uri_choice, (const uint8_t **)uri, urilen, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
if (uri_choice != X509_gn_uniform_resource_identifier) {
error_print();
return -1;
}
if (*uri == NULL || *urilen == 0) {
error_print();
return -1;
}
return 1;
}
int x509_access_description_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
int oid;
int choice;
const uint8_t *p;
size_t len;
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
if (x509_access_method_from_der(&oid, &d, &dlen) != 1) {
error_print();
return -1;
}
format_print(fp, fmt, ind, "accessMethod: %s\n", x509_access_method_name(oid));
if (x509_general_name_from_der(&choice, &p, &len, &d, &dlen) != 1) {
error_print();
return -1;
}
x509_general_name_print(fp, fmt, ind, "GeneralName", choice, p, len);
if (dlen) {
error_print();
return -1;
}
return 1;
}
int x509_authority_info_access_to_der(
const char *crt_uri, size_t crt_urilen,
const char *ocsp_uri, size_t ocsp_urilen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (crt_uri && crt_urilen) {
if (x509_access_description_to_der(OID_ad_ca_issuers, crt_uri, crt_urilen, NULL, &len) != 1) {
error_print();
return -1;
}
}
if (ocsp_uri && ocsp_urilen) {
if (x509_access_description_to_der(OID_ad_ocsp, ocsp_uri, ocsp_urilen, NULL, &len) != 1) {
error_print();
return -1;
}
}
if (!len) {
error_print();
return -1;
}
if (asn1_sequence_header_to_der(len, out, outlen) != 1) {
error_print();
return -1;
}
if (crt_uri && crt_urilen) {
if (x509_access_description_to_der(OID_ad_ca_issuers, crt_uri, crt_urilen, out, outlen) != 1) {
error_print();
return -1;
}
}
if (ocsp_uri && ocsp_urilen) {
if (x509_access_description_to_der(OID_ad_ocsp, ocsp_uri, ocsp_urilen, out, outlen) != 1) {
error_print();
return -1;
}
}
return 1;
}
int x509_authority_info_access_from_der(
const char **crt_uri, size_t *crt_urilen,
const char **ocsp_uri, size_t *ocsp_urilen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *d;
size_t dlen;
const uint8_t *ad;
size_t adlen;
if (!crt_uri || !crt_urilen || !ocsp_uri || !ocsp_urilen || !in || !(*in) || !inlen) {
error_print();
return -1;
}
*crt_uri = NULL;
*crt_urilen = 0;
*ocsp_uri = NULL;
*ocsp_urilen = 0;
if ((ret = asn1_sequence_of_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
while (dlen) {
int oid;
const char *uri;
size_t urilen;
if (x509_access_description_from_der(&oid, &uri, &urilen, &d, &dlen) != 1) {
error_print();
return -1;
}
switch (oid) {
case OID_ad_ca_issuers:
if (*crt_uri) {
error_print();
return -1;
}
*crt_uri = uri;
*crt_urilen = urilen;
break;
case OID_ad_ocsp:
if (*ocsp_uri) {
error_print();
return -1;
}
*ocsp_uri = uri;
*ocsp_urilen = urilen;
break;
default:
error_print();
return -1;
}
}
return 1;
}
int x509_authority_info_access_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
const uint8_t *p;
size_t len;
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
while (dlen) {
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) {
error_print();
return -1;
}
x509_access_description_print(fp, fmt, ind, "AccessDescription", p, len);
}
return 1;
}
int x509_exts_add_authority_info_access(uint8_t *exts, size_t *extslen, size_t maxlen, int critical,
const char *crt_uri, size_t crt_urilen, const char *ocsp_uri, size_t ocsp_urilen)
{
int oid = OID_pe_authority_info_access;
size_t curlen = *extslen;
uint8_t val[256];
uint8_t *p = val;
size_t vlen = 0;
size_t len = 0;
// Conforming CAs MUST mark this extension as non-critical.
if (critical == 1) {
error_print();
return -1;
}
if (x509_authority_info_access_to_der(crt_uri, crt_urilen, ocsp_uri, ocsp_urilen, NULL, &len) != 1
|| asn1_length_le(len, sizeof(val)) != 1
|| x509_authority_info_access_to_der(crt_uri, crt_urilen, ocsp_uri, ocsp_urilen, &p, &vlen) != 1) {
error_print();
return -1;
}
exts += *extslen;
if (x509_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) {
error_print();
return -1;
}
return 1;
}

View File

@@ -134,7 +134,7 @@ static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; // crl_entry_ext
#define OID_CE_CNT sizeof(oid_ce_subject_directory_attributes)/sizeof(int)
static uint32_t oid_netscape_cert_type[] = { 2,16,840,1,113730,1,1 };
static uint32_t oid_netscape_cert_comment[] = { 2,16,840,1,113730,1,13 };
static uint32_t oid_cert_authority_info_access[] = { 1,3,6,1,5,5,7,1,1 };
static uint32_t oid_pe_authority_info_access[] = { 1,3,6,1,5,5,7,1,1 };
static uint32_t oid_ct_precertificate_scts[] = { 1,3,6,1,4,1,11129,2,4,2 };
static const ASN1_OID_INFO x509_ext_ids[] = {
@@ -158,7 +158,7 @@ static const ASN1_OID_INFO x509_ext_ids[] = {
{ OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, OID_CE_CNT },
{ OID_netscape_cert_type, "NetscapeCertType", oid_netscape_cert_type, sizeof(oid_netscape_cert_type)/sizeof(int) },
{ OID_netscape_cert_comment, "NetscapeCertComment", oid_netscape_cert_comment, sizeof(oid_netscape_cert_comment)/sizeof(int) },
{ OID_cert_authority_info_access, "CertificateAuthorityInformationAccess", oid_cert_authority_info_access, sizeof(oid_cert_authority_info_access)/sizeof(int) },
{ OID_pe_authority_info_access, "AuthorityInformationAccess", oid_pe_authority_info_access, sizeof(oid_pe_authority_info_access)/sizeof(int) },
{ OID_ct_precertificate_scts, "CT-PrecertificateSCTs", oid_ct_precertificate_scts, sizeof(oid_ct_precertificate_scts)/sizeof(int) },
};

View File

@@ -23,7 +23,7 @@
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num "
"-key file [-pass pass] "
"[-key_usage str]* [-out file]";
"[-key_usage str]* [-ocsp uri] [-crl uri] [-out file]";
static int ext_key_usage_set(int *usages, const char *usage_name)
@@ -49,6 +49,8 @@ int certgen_main(int argc, char **argv)
char *common_name = NULL;
int days = 0;
int key_usage = 0;
char *ocsp = NULL;
char *crl = NULL;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
@@ -112,6 +114,12 @@ int certgen_main(int argc, char **argv)
fprintf(stderr, "%s: invalid -key_usage value '%s'\n", prog, usage);
goto end;
}
} else if (!strcmp(*argv, "-ocsp")) {
if (--argc < 1) goto bad;
ocsp = *(++argv);
} else if (!strcmp(*argv, "-crl")) {
if (--argc < 1) goto bad;
crl = *(++argv);
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
keyfile = *(++argv);
@@ -173,6 +181,13 @@ bad:
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
if (ocsp) {
if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0,
ocsp, strlen(ocsp), crl, strlen(crl)) != 1) {
fprintf(stderr, "%s: error\n", prog);
goto end;
}
}
time(&not_before);
if (rand_bytes(serial, sizeof(serial)) != 1