Update X509 cert

This commit is contained in:
Zhi Guan
2023-02-04 21:04:43 +08:00
parent 1fbdfeee59
commit 6a02a61c4f
16 changed files with 1081 additions and 1071 deletions

View File

@@ -20,24 +20,23 @@ gmssl certparse -in cacert.pem
gmssl sm2keygen -pass 1234 -out signkey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key signkey.pem -pass 1234 -out signreq.pem
gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem \
-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
-crl_http_uri http://github.com/guanzhi/GmSSL/raw/master/demos/certs/SubCA-1.crl
gmssl certparse -in signcert.pem
gmssl sm2keygen -pass 1234 -out enckey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN localhost -key enckey.pem -pass 1234 -out encreq.pem
gmssl reqsign -in encreq.pem -days 365 -key_usage keyEncipherment -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem \
-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
-crl_http_uri http://github.com/guanzhi/GmSSL/raw/master/demos/certs/SubCA-1.crl
gmssl certparse -in enccert.pem
cat signcert.pem > certs.pem
cat cacert.pem >> certs.pem
gmssl certverify -in certs.pem -cacert rootcacert.pem
gmssl certverify -in certs.pem -cacert rootcacert.pem #-check_crl
cat signcert.pem > dbl_certs.pem
cat enccert.pem >> dbl_certs.pem
cat cacert.pem >> dbl_certs.pem
gmssl certverify -double_certs -in dbl_certs.pem -cacert rootcacert.pem
gmssl certverify -double_certs -in dbl_certs.pem -cacert rootcacert.pem #-check_crl

View File

@@ -70,6 +70,8 @@ Time ::= CHOICE {
utcTime UTCTime,
generalTime GeneralizedTime }
*/
#define X509_MAX_UTC_TIME 2524607999 // "20491231235959Z"
#define X509_MAX_GENERALIZED_TIME 253402300799 // "99991231235959Z"
int x509_time_to_der(time_t a, uint8_t **out, size_t *outlen);
int x509_time_from_der(time_t *a, const uint8_t **in, size_t *inlen);
@@ -84,9 +86,26 @@ Validity ::= SEQUENCE {
int x509_validity_add_days(time_t *not_after, time_t not_before, int days);
int x509_validity_to_der(time_t not_before, time_t not_after, uint8_t **out, size_t *outlen);
int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t **in, size_t *inlen);
int x509_validity_validate(time_t not_before, time_t not_after, time_t now, int max_secs);
int x509_validity_check(time_t not_before, time_t not_after, time_t now, int max_secs);
int x509_validity_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
/*
DirectoryString or DirectoryName
DirectoryName ::= CHOICE {
teletexString TeletexString (SIZE (1..MAX)),
printableString PrintableString (SIZE (1..MAX)),
universalString UniversalString (SIZE (1..MAX)),
utf8String UTF8String (SIZE (1..MAX)),
bmpString BMPString (SIZE (1..MAX)),
}
*/
int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen);
int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen);
int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen);
/*
AttributeTypeAndValue ::= SEQUENCE {
type OBJECT IDENTIFIER,
@@ -130,7 +149,7 @@ RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue
*/
int x509_rdn_to_der(int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t mlen, uint8_t **out, size_t *outlen);
int x509_rdn_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, const uint8_t **more, size_t *mlen, const uint8_t **in, size_t *inlen);
int x509_rdn_validate(const uint8_t *d, size_t dlen);
int x509_rdn_check(const uint8_t *d, size_t dlen);
int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
/*
@@ -156,12 +175,12 @@ int x509_name_add_common_name(uint8_t *d, size_t *dlen, size_t maxlen, int tag,
int x509_name_add_domain_component(uint8_t *d, size_t *dlen, size_t maxlen, const char *val, size_t vlen); // val: IA5String
int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen,
const char *country, const char *state, const char *locality,
const char country[2], const char *state, const char *locality,
const char *org, const char *org_unit, const char *common_name);
#define x509_name_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen)
#define x509_name_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen)
int x509_name_validate(const uint8_t *d, size_t dlen);
int x509_name_check(const uint8_t *d, size_t dlen);
int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen);
int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen);
@@ -200,10 +219,6 @@ int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, cons
#define x509_exts_to_der(d,dlen,out,outlen) x509_explicit_exts_to_der(3,d,dlen,out,outlen)
#define x509_exts_from_der(d,dlen,in,inlen) x509_explicit_exts_from_der(3,d,dlen,in,inlen)
int x509_exts_get_count(const uint8_t *d, size_t dlen, size_t *cnt);
int x509_exts_get_ext_by_index(const uint8_t *d, size_t dlen, int index,
int *oid, uint32_t *nodes, size_t *nodes_cnt, int *critical,
const uint8_t **val, size_t *vlen);
int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid,
int *critical, const uint8_t **val, size_t *vlen);
int x509_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
@@ -284,9 +299,23 @@ int x509_signed_verify(const uint8_t *a, size_t alen, const SM2_KEY *pub_key,
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);
//int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
// x509_cert functions
int x509_cert_sign_to_der(
int version,
const uint8_t *serial, size_t serial_len,
int signature_algor,
const uint8_t *issuer, size_t issuer_len,
time_t not_before, time_t not_after,
const uint8_t *subject, size_t subject_len,
const SM2_KEY *subject_public_key,
const uint8_t *issuer_unique_id, size_t issuer_unique_id_len,
const uint8_t *subject_unique_id, size_t subject_unique_id_len,
const uint8_t *exts, size_t exts_len,
const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len,
uint8_t **out, size_t *outlen);
/*
int x509_cert_sign(
uint8_t *cert, size_t *certlen, size_t maxlen,
int version,
@@ -301,12 +330,12 @@ 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_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);
int x509_cert_to_pem(const uint8_t *a, size_t alen, FILE *fp);
int x509_cert_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp);
int x509_cert_from_pem_by_index(uint8_t *a, size_t *alen, size_t maxlen, int index, FILE *fp);
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);
@@ -326,7 +355,7 @@ int x509_cert_get_details(const uint8_t *a, size_t alen,
const uint8_t **extensions, size_t *extensions_len,
int *signature_algor,
const uint8_t **signature, size_t *signature_len);
int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraints);
int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraints);
/*

View File

@@ -219,7 +219,7 @@ const char *x509_key_usage_name(int flag);
int x509_key_usage_from_name(int *flag, const char *name);
#define x509_key_usage_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen)
#define x509_key_usage_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen)
int x509_key_usage_validate(int bits, int cert_type);
int x509_key_usage_check(int bits, int cert_type);
int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits);
/*
@@ -372,7 +372,7 @@ BasicConstraints ::= SEQUENCE {
*/
int x509_basic_constraints_to_der(int ca, int path_len_cons, uint8_t **out, size_t *outlen);
int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t **in, size_t *inlen);
int x509_basic_constraints_validate(int ca, int path_len_cons, int cert_type);
int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type);
int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
/*
@@ -446,7 +446,7 @@ KeyPurposeId:
#define X509_MAX_KEY_PURPOSES 7
int x509_ext_key_usage_to_der(const int *oids, size_t oids_cnt, uint8_t **out, size_t *outlen);
int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, const uint8_t **in, size_t *inlen);
int x509_ext_key_usage_validate(const int *oids, size_t oids_cnt, int cert_type);
int x509_ext_key_usage_check(const int *oids, size_t oids_cnt, int cert_type);
int x509_ext_key_usage_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
/*
@@ -482,6 +482,11 @@ DistributionPointName ::= CHOICE {
fullName [0] IMPLICIT GeneralNames, -- SEQUENCE OF
nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } -- SET OF
*/
enum {
X509_full_name = 0,
X509_name_relative_to_crl_issuer = 1,
};
int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, 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_uri_as_distribution_point_name_from_der(const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen);
@@ -557,7 +562,7 @@ NetscapeCertComment ::= IA5String
*/
int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits);
int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type,
int *path_len_constraints);
/*

View File

@@ -24,25 +24,9 @@
extern "C" {
#endif
/*
DirectoryString or DirectoryName
DirectoryName ::= CHOICE {
teletexString TeletexString (SIZE (1..MAX)),
printableString PrintableString (SIZE (1..MAX)),
universalString UniversalString (SIZE (1..MAX)),
utf8String UTF8String (SIZE (1..MAX)),
bmpString BMPString (SIZE (1..MAX)),
}
*/
int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen);
int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen);
int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen);
/*
DisplayText ::= CHOICE {

View File

@@ -217,15 +217,21 @@ int asn1_length_from_der(size_t *len, const uint8_t **in, size_t *inlen)
return 1;
}
// not in-use
// asn1_data_to_der do not check the validity of data
int asn1_data_to_der(const uint8_t *data, size_t datalen, uint8_t **out, size_t *outlen)
{
if (!data || !datalen || !outlen) {
if (!outlen) {
error_print();
return -1;
}
if (datalen == 0) {
return 0;
}
if (out && *out) {
if (!data) {
error_print();
return -1;
}
memcpy(*out, data, datalen);
*out += datalen;
}
@@ -323,13 +329,9 @@ int asn1_type_from_der(int tag, const uint8_t **d, size_t *dlen, const uint8_t *
}
// data
if (*dlen == 0) {
*d = NULL;
} else {
*d = *in;
*in += *dlen;
*inlen -= *dlen;
}
*d = *in;
*in += *dlen;
*inlen -= *dlen;
return 1;
}
@@ -385,13 +387,9 @@ int asn1_any_type_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint
return -1;
}
if (*dlen == 0) {
*d = NULL;
} else {
*d = *in;
*in += *dlen;
*inlen -= *dlen;
}
*d = *in;
*in += *dlen;
*inlen -= *dlen;
return 1;
}

View File

@@ -288,6 +288,7 @@ int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sigbuf
}
if ((ret = sm2_do_verify(key, dgst, &sig)) != 1) {
if (ret < 0) error_print();
else error_print();
return ret;
}
return 1;
@@ -405,7 +406,7 @@ int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_
error_print();
return -1;
}
ctx->key = *key;
ctx->key = *key; //FIXME: only copy public_key
sm3_init(&ctx->sm3_ctx);
if (id) {
@@ -444,6 +445,7 @@ int sm2_verify_finish(SM2_SIGN_CTX *ctx, const uint8_t *sig, size_t siglen)
sm3_finish(&ctx->sm3_ctx, dgst);
if ((ret = sm2_verify(&ctx->key, dgst, sig, siglen)) != 1) {
if (ret < 0) error_print();
else error_print();
return ret;
}
return 1;

File diff suppressed because it is too large Load Diff

View File

@@ -40,6 +40,7 @@ static const char *x509_crl_reason_names[] = {
static const size_t x509_crl_reason_names_count =
sizeof(x509_crl_reason_names)/sizeof(x509_crl_reason_names[0]);
// 这个函数也不应该有错误的输入值
const char *x509_crl_reason_name(int reason)
{
if (reason < 0 || reason >= x509_crl_reason_names_count) {
@@ -49,6 +50,8 @@ const char *x509_crl_reason_name(int reason)
return x509_crl_reason_names[reason];
}
// 这个函数由于需要用在判断中最好不要打印错误值。并且有可能这个name是一个我们不识别的值因此返回0
// 不识别的name还是应该返回-1更合适
int x509_crl_reason_from_name(int *reason, const char *name)
{
int i;
@@ -197,7 +200,7 @@ int x509_crl_reason_ext_to_der(int critical, int reason, uint8_t **out, size_t *
uint8_t *p = val;
size_t vlen = 0;
if (reason < 0) {
if (reason == -1) {
return 0;
}
if (x509_crl_reason_to_der(reason, &p, &vlen) != 1
@@ -216,7 +219,7 @@ int x509_invalidity_date_ext_to_der(int critical, time_t date, uint8_t **out, si
uint8_t *p = val;
size_t vlen = 0;
if (date < 0) {
if (date == -1) {
return 0;
}
if (asn1_generalized_time_to_der(date, &p, &vlen) != 1
@@ -235,7 +238,7 @@ int x509_cert_issuer_ext_to_der(int critical, const uint8_t *d, size_t dlen, uin
uint8_t *p = val;
size_t vlen = 0;
if (!d) {
if (dlen == 0) {
return 0;
}
if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1
@@ -369,7 +372,7 @@ int x509_crl_entry_exts_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (reason == -1 && invalid_date == -1 && !cert_issuer) {
if (reason == -1 && invalid_date == -1 && cert_issuer_len == 0) {
return 0;
}
if (x509_crl_reason_ext_to_der(-1, reason, NULL, &len) < 0
@@ -482,6 +485,9 @@ int x509_revoked_cert_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (serial_len == 0 && revoke_date == -1 && crl_entry_exts_len == 0) {
return 0;
}
if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1
|| asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1
|| asn1_sequence_to_der(crl_entry_exts, crl_entry_exts_len, NULL, &len) < 0
@@ -501,6 +507,10 @@ int x509_revoked_cert_to_der_ex(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (serial_len ==0 && revoke_date == -1
&& reason == -1 && invalid_date == -1 && cert_issuer_len == 0) {
return 0;
}
if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1
|| asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1
|| x509_crl_entry_exts_to_der(reason, invalid_date, cert_issuer, cert_issuer_len, NULL, &len) < 0
@@ -744,6 +754,14 @@ int x509_issuing_distribution_point_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (dist_point_uri_len == 0
&& only_contains_user_certs == -1
&& only_contains_ca_certs == -1
&& only_some_reasons == -1
&& indirect_crl == -1
&& only_contains_attr_certs == -1) {
return 0;
}
if (x509_uri_as_explicit_distribution_point_name_to_der(0, dist_point_uri, dist_point_uri_len, NULL, &len) < 0
|| asn1_implicit_boolean_to_der(1, only_contains_user_certs, NULL, &len) < 0
|| asn1_implicit_boolean_to_der(2, only_contains_ca_certs, NULL, &len) < 0
@@ -870,6 +888,10 @@ int x509_crl_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (vlen == 0) {
return 0;
}
if (x509_crl_ext_id_to_der(oid, NULL, &len) != 1
|| asn1_boolean_to_der(critical, NULL, &len) < 0
|| asn1_octet_string_to_der(val, vlen, NULL, &len) != 1
@@ -1538,14 +1560,10 @@ int x509_crl_get_details(const uint8_t *a, size_t alen,
struct {
int version;
int sig_alg;
const uint8_t *issuer;
size_t issuer_len;
time_t this_update;
time_t next_update;
const uint8_t *revoked_certs;
size_t revoked_certs_len;
const uint8_t *exts;
size_t exts_len;
const uint8_t *issuer; size_t issuer_len;
time_t this_update; time_t next_update;
const uint8_t *revoked_certs; size_t revoked_certs_len;
const uint8_t *exts; size_t exts_len;
} tbs;
if (x509_tbs_crl_from_der(
@@ -1842,5 +1860,3 @@ end:
if (crl) free(crl);
return ret;
}

View File

@@ -24,12 +24,34 @@
#include <gmssl/error.h>
int x509_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (vlen == 0) {
return 0;
}
if (x509_ext_id_to_der(oid, NULL, &len) != 1
|| asn1_boolean_to_der(critical, NULL, &len) < 0
|| asn1_octet_string_to_der(val, vlen, 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_octet_string_to_der(val, vlen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_ext_to_der_ex(int oid, int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
size_t vlen = 0;
size_t len = 0;
if (dlen == 0) {
return 0;
}
if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1) {
error_print();
return -1;
@@ -51,6 +73,123 @@ int x509_ext_to_der_ex(int oid, int critical, const uint8_t *d, size_t dlen, uin
return 1;
}
int x509_ext_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt,
int *critical, const uint8_t **val, size_t *vlen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *d;
size_t dlen;
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (x509_ext_id_from_der(oid, nodes, nodes_cnt, &d, &dlen) != 1
|| asn1_boolean_from_der(critical, &d, &dlen) < 0
|| asn1_octet_string_from_der(val, vlen, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
int ret, oid, critical;
uint32_t nodes[32];
size_t nodes_cnt;
const uint8_t *val;
size_t vlen;
const uint8_t *p;
size_t len;
int ival;
const char *name;
if (label) {
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
}
if (x509_ext_id_from_der(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err;
asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_ext_id_name(oid), nodes, nodes_cnt);
if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err;
if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical));
if (asn1_octet_string_from_der(&val, &vlen, &d, &dlen) != 1) goto err;
switch (oid) {
case OID_ce_subject_key_identifier:
if (asn1_octet_string_from_der(&p, &len, &val, &vlen) != 1) {
error_print();
return -1;
}
break;
case OID_ce_key_usage:
case OID_netscape_cert_type:
if (asn1_bits_from_der(&ival, &val, &vlen) != 1) {
error_print();
return -1;
}
break;
case OID_ce_inhibit_any_policy:
if (asn1_int_from_der(&ival, &val, &vlen) != 1) {
error_print();
return -1;
}
break;
case OID_netscape_cert_comment:
if (asn1_ia5_string_from_der((const char **)&p, &len, &val, &vlen) != 1) {
error_print();
return -1;
}
break;
case OID_ct_precertificate_scts:
case OID_undef:
p = val;
len = vlen;
vlen = 0;
break;
default:
if (asn1_sequence_from_der(&p, &len, &val, &vlen) != 1) {
error_print();
return -1;
}
}
if (asn1_length_is_zero(vlen) != 1) {
error_print();
return -1;
}
name = x509_ext_id_name(oid);
switch (oid) {
case OID_ce_authority_key_identifier: return x509_authority_key_identifier_print(fp, fmt, ind, name, p, len);
case OID_ce_subject_key_identifier: return format_bytes(fp, fmt, ind, name, p, len);
case OID_ce_key_usage: return x509_key_usage_print(fp, fmt, ind, name, ival);
case OID_ce_certificate_policies: return x509_certificate_policies_print(fp, fmt, ind, name, p, len);
case OID_ce_policy_mappings: return x509_policy_mappings_print(fp, fmt, ind, name, p, len);
case OID_ce_subject_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len);
case OID_ce_issuer_alt_name: return x509_general_names_print(fp, fmt, ind, name, p, len);
case OID_ce_subject_directory_attributes: return x509_attributes_print(fp, fmt, ind, name, p, len);
case OID_ce_basic_constraints: return x509_basic_constraints_print(fp, fmt, ind, name, p, len);
case OID_ce_name_constraints: return x509_name_constraints_print(fp, fmt, ind, name, p, len);
case OID_ce_policy_constraints: return x509_policy_constraints_print(fp, fmt, ind, name, p, len);
case OID_ce_ext_key_usage: return x509_ext_key_usage_print(fp, fmt, ind, name, p, len);
case OID_ce_crl_distribution_points: return x509_crl_distribution_points_print(fp, fmt, ind, name, p, len);
case OID_ce_inhibit_any_policy: format_print(fp, fmt, ind, "%s: %d\n", name, ival);
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;
err:
error_print();
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)
{
@@ -374,24 +513,76 @@ int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxl
return 1;
}
// 是否支持输入为空这样返回0我感觉这是一个比较高层的API可能被应用直接调用还是做严格检查比较好
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 oid = OID_ce_freshest_crl;
return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen);
if (x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_exts_get_ext_by_oid(const uint8_t *d, size_t dlen, int oid,
int *critical, const uint8_t **val, size_t *vlen)
{
int ext_id;
uint32_t nodes[32];
size_t nodes_cnt;
while (dlen) {
if (x509_ext_from_der(&ext_id, nodes, &nodes_cnt, critical, val, vlen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (ext_id == oid) {
return 1;
}
}
*critical = -1;
*val = NULL;
*vlen = 0;
return 0;
}
int x509_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
const uint8_t *p;
size_t len;
if (label) {
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_ext_print(fp, fmt, ind, "Extension", p, len);
}
return 1;
}
// GeneralName
int x509_other_name_to_der(
const uint32_t *type_nodes, size_t type_nodes_cnt,
const uint8_t *value, size_t value_len,
const uint8_t *value_a, size_t value_alen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (type_nodes_cnt == 0 && value_alen == 0) {
return 0;
}
if (asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, NULL, &len) != 1
|| asn1_explicit_to_der(0, value, value_len, NULL, &len) != 1
|| asn1_explicit_to_der(0, value_a, value_alen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| asn1_object_identifier_to_der(type_nodes, type_nodes_cnt, out, outlen) != 1
|| asn1_explicit_to_der(0, value, value_len, out, outlen) != 1) {
|| asn1_explicit_to_der(0, value_a, value_alen, out, outlen) != 1) {
error_print();
return -1;
}
@@ -447,6 +638,10 @@ int x509_edi_party_name_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (assigner_len == 0 && party_name_len == 0) {
return 0;
}
if (x509_explicit_directory_name_to_der(0, assigner_choice, assigner, assigner_len, NULL, &len) < 0
|| x509_explicit_directory_name_to_der(1, party_name_choice, party_name, party_name_len, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
@@ -505,6 +700,10 @@ int x509_general_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t
{
int ret;
if (dlen == 0) {
return 0;
}
switch (choice) {
case X509_gn_rfc822_name:
case X509_gn_dns_name:
@@ -681,7 +880,6 @@ int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t ma
int x509_general_names_get_next(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen)
{
if (!gns || !gns_len) {
error_print();
return -1;
@@ -707,6 +905,9 @@ int x509_general_names_get_next(const uint8_t *gns, size_t gns_len, const uint8_
return 1;
}
}
*d = NULL;
*dlen = 0;
return 0;
}
@@ -728,24 +929,13 @@ int x509_general_names_get_first(const uint8_t *gns, size_t gns_len, const uint8
return ret;
}
/*
DistributionPointName ::= CHOICE {
fullName [0] GeneralNames,
nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
本来GeneralNames是一个SEQUENCE OF本来这个类型编码的时候应该是80开头的
*/
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
int choice = X509_gn_uniform_resource_identifier;
size_t len = 0;
if (!uri || !urilen) {
if (!urilen) {
return 0;
}
if (x509_general_name_to_der(choice, (uint8_t *)uri, urilen, NULL, &len) != 1
@@ -767,6 +957,10 @@ int x509_uri_as_general_names_from_der_ex(int tag, const uint8_t **uri, size_t *
if ((ret = asn1_type_from_der(tag, &d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
else {
*uri = NULL;
*urilen = 0;
}
return ret;
}
if (x509_general_names_get_first(d, dlen, NULL, choice, uri, urilen) < 0) {
@@ -802,6 +996,9 @@ int x509_authority_key_identifier_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (keyid_len == 0 && issuer_len == 0 && serial_len == 0) {
return 0;
}
if (asn1_implicit_octet_string_to_der(0, keyid, keyid_len, NULL, &len) < 0
|| asn1_implicit_sequence_to_der(1, issuer, issuer_len, NULL, &len) < 0
|| asn1_implicit_integer_to_der(2, serial, serial_len, NULL, &len) < 0
@@ -839,38 +1036,6 @@ int x509_authority_key_identifier_from_der(
return 1;
}
int x509_authority_key_identifier_validate(const uint8_t *a, size_t alen)
{
const uint8_t *keyid;
size_t keyid_len;
const uint8_t *issuer;
size_t issuer_len;
const uint8_t *serial;
size_t serial_len;
if (x509_authority_key_identifier_from_der(
&keyid, &keyid_len,
&issuer, &issuer_len,
&serial, &serial_len, &a, &alen) != 1
|| asn1_length_is_zero(alen) != 1) {
error_print();
return -1;
}
if (!keyid && !issuer && !serial) {
error_print();
return -1;
}
if (issuer) {
/*
if (asn1_general_names_validate(issuer, issuer_len) != 1) {
error_print();
return -1;
}
*/
}
return 1;
}
int x509_authority_key_identifier_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
int ret;
@@ -939,7 +1104,7 @@ int x509_key_usage_from_name(int *flag, const char *name)
return -1;
}
int x509_key_usage_validate(int bits, int cert_type)
int x509_key_usage_check(int bits, int cert_type)
{
switch (cert_type) {
case X509_cert_server_auth:
@@ -1005,7 +1170,8 @@ int x509_key_usage_validate(int bits, int cert_type)
int x509_key_usage_print(FILE *fp, int fmt, int ind, const char *label, int bits)
{
return asn1_bits_print(fp, fmt, ind, label, x509_key_usages, x509_key_usages_count, bits);
(void)asn1_bits_print(fp, fmt, ind, label, x509_key_usages, x509_key_usages_count, bits);
return 1;
}
int x509_notice_reference_to_der(
@@ -1014,6 +1180,10 @@ int x509_notice_reference_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (org_len == 0 && notice_numbers_cnt == 0) {
return 0;
}
if (x509_display_text_to_der(org_tag, org, org_len, NULL, &len) != 1
|| asn1_sequence_of_int_to_der(notice_numbers, notice_numbers_cnt, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
@@ -1075,6 +1245,11 @@ int x509_user_notice_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (notice_ref_org_len == 0
&& notice_ref_notice_numbers_cnt == 0
&& explicit_text_len == 0) {
return 0;
}
if (x509_notice_reference_to_der(
notice_ref_org_tag, notice_ref_org, notice_ref_org_len,
notice_ref_notice_numbers, notice_ref_notice_numbers_cnt,
@@ -1144,6 +1319,9 @@ int x509_policy_qualifier_info_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (qualifier_len == 0) {
return 0;
}
if (x509_qualifier_id_to_der(oid, NULL, &len) != 1
|| asn1_any_to_der(qualifier, qualifier_len, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
@@ -1284,7 +1462,7 @@ int x509_certificate_policies_add_policy_information(uint8_t *d, size_t *dlen, s
return -1;
}
int x509_certificate_polices_validate(const uint8_t *d, size_t dlen)
int x509_certificate_polices_check(const uint8_t *d, size_t dlen)
{
error_print();
return -1;
@@ -1314,6 +1492,10 @@ int x509_policy_mapping_to_der(
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (issuer_policy_nodes_cnt == 0
&& subject_policy_nodes_cnt == 0) {
return 0;
}
if (x509_cert_policy_id_to_der(issuer_policy_oid,
issuer_policy_nodes, issuer_policy_nodes_cnt, NULL, &len) != 1
|| x509_cert_policy_id_to_der(subject_policy_oid,
@@ -1373,16 +1555,6 @@ err:
return -1;
}
int x509_policy_mapping_validate(const uint8_t *a, size_t alen)
{
return -1;
}
int x509_policy_mappings_validate(const uint8_t *d, size_t dlen)
{
return -1;
}
int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
const uint8_t *p;
@@ -1401,7 +1573,6 @@ int x509_policy_mappings_print(FILE *fp, int fmt, int ind, const char *label, co
return 1;
}
int x509_attribute_to_der(
const uint32_t *nodes, size_t nodes_cnt,
const uint8_t *values, size_t values_len,
@@ -1527,7 +1698,7 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t *
// 这个函数原型可能要改一下
int x509_basic_constraints_validate(int ca, int path_len_cons, int cert_type)
int x509_basic_constraints_check(int ca, int path_len_cons, int cert_type)
{
/*
entity_cert:
@@ -1782,7 +1953,7 @@ int x509_policy_constraints_from_der(
return 1;
}
int x509_policy_constraints_validate(const uint8_t *a, size_t alen)
int x509_policy_constraints_check(const uint8_t *a, size_t alen)
{
return -1;
@@ -1861,7 +2032,7 @@ int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, con
}
// 这个函数原型可能也要改一下
int x509_ext_key_usage_validate(const int *oids, size_t oids_cnt, int cert_type)
int x509_ext_key_usage_check(const int *oids, size_t oids_cnt, int cert_type)
{
int ret = -1;
size_t i;
@@ -1911,35 +2082,6 @@ 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_reason_flags[] = {
"unused",
"keyCompromise",
@@ -1990,33 +2132,13 @@ int x509_revoke_reason_flags_print(FILE *fp, int fmt, int ind, const char *label
return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reason_flags, x509_revoke_reason_flags_count, bits);
}
/*
Example CRLDistributionPoints extension
1 DistributionPoint in CRLDistributionPoints
distributionPoint choice: fullName
2 GeneralName in fullName(GeneralNames), same CRL with different URI
Extension
extnID: CRLDistributionPoints (2.5.29.31)
CRLDistributionPoints
DistributionPoint
distributionPoint
fullName
GeneralName
URI: http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
GeneralName
URI: http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
*/
int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
int ret;
if ((ret = x509_uri_as_general_names_to_der_ex(ASN1_TAG_EXPLICIT(0), uri, urilen, out, outlen)) != 1) {
if (ret < 0) error_print();
int tag = ASN1_TAG_EXPLICIT(X509_full_name);
if ((ret = x509_uri_as_general_names_to_der_ex(tag, uri, urilen, out, outlen)) != 1) {
if (ret < 0) error_print(); // 检查一下是否有必要支持返回0
return ret;
}
return 1;
@@ -2033,12 +2155,11 @@ int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t
return ret;
}
switch (tag) {
case ASN1_TAG_EXPLICIT(0):
*choice = 0;
// 此时返回的值是GeneralNames的d,dlen因此这个返回值不能用general_names_from来解析
case ASN1_TAG_EXPLICIT(X509_full_name):
*choice = X509_full_name;
break;
case ASN1_TAG_EXPLICIT(1):
*choice = 1;
case ASN1_TAG_EXPLICIT(X509_name_relative_to_crl_issuer):
*choice = X509_name_relative_to_crl_issuer;
break;
default:
error_print();
@@ -2051,15 +2172,15 @@ int x509_uri_as_distribution_point_name_from_der(const char **uri, size_t *urile
const uint8_t **in, size_t *inlen)
{
int ret;
int choice;
const uint8_t *d;
size_t dlen;
int choice;
if ((ret = x509_distribution_point_name_from_der(&choice, &d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (choice == 0) {
if (choice == X509_full_name) {
if (x509_general_names_get_first(d, dlen, NULL, choice, (const uint8_t **)uri, urilen) < 0) {
error_print();
return -1;
@@ -2096,7 +2217,7 @@ int x509_uri_as_explicit_distribution_point_name_to_der(int index,
{
size_t len = 0;
if (!uri || !urilen) {
if (!urilen) {
return 0;
}
if (x509_uri_as_distribution_point_name_to_der(uri, urilen, NULL, &len) != 1
@@ -2132,10 +2253,6 @@ 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 (!uri || !urilen) {
return 0;
}
if (x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, NULL, &len) != 1
|| x509_revoke_reason_flags_to_der(reasons, NULL, &len) < 0
|| x509_general_names_to_der(crl_issuer, crl_issuer_len, NULL, &len) < 0
@@ -2161,7 +2278,7 @@ int x509_uri_as_distribution_point_from_der(const char **uri, size_t *urilen,
if (ret < 0) error_print();
return ret;
}
if (x509_uri_as_explicit_distribution_point_name_from_der(0, uri, urilen, &d, &dlen) != 1
if (x509_uri_as_explicit_distribution_point_name_from_der(0, uri, urilen, &d, &dlen) < 0
|| x509_revoke_reason_flags_from_der(reasons, &d, &dlen) < 0
|| x509_general_names_from_der(crl_issuer, crl_issuer_len, &d, &dlen) < 0
|| asn1_length_is_zero(dlen) != 1) {
@@ -2201,47 +2318,15 @@ int x509_uri_as_distribution_points_to_der(const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_distribution_point_to_der(uri, urilen,
reasons, crl_issuer, crl_issuer_len, NULL, &len) < 0
if (x509_uri_as_distribution_point_to_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_distribution_point_to_der(uri, urilen,
reasons, crl_issuer, crl_issuer_len, out, outlen) < 0) {
|| x509_uri_as_distribution_point_to_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
/*
DistributionPoints :== SEQUENCE OF DistributionPoint
80 Len -- DistributionPoints header
80 Len DistributionPoint 1 header
80 EXPLICIT(0)
DistributionPointName
80 len d,dln GeneralNames
06 len URI
01 len d,dlen ReasonFlags
82 len, d,dlen GeneralNames
80 Len DistributionPoint 2 header
80 Len DistributionPoint 3 header
*/
int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen,
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen)
@@ -2254,19 +2339,20 @@ int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen,
if (ret < 0) error_print();
return ret;
}
*uri = NULL;
*urilen = 0;
while (dlen) {
if (x509_uri_as_distribution_point_from_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, &d, &dlen) != 1) {
error_print();
return -1;
}
if (*uri) {
if (*uri != NULL) {
return 1;
}
}
*uri = NULL;
*urilen = 0;
*reasons = -1;
*crl_issuer = NULL;
*crl_issuer_len = 0;
return 1;
}
@@ -2306,7 +2392,7 @@ int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label,
sizeof(netscape_cert_types)/sizeof(netscape_cert_types[0]), bits);
}
int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
int x509_exts_check(const uint8_t *exts, size_t extslen, int cert_type,
int *path_len_constraint)
{
int oid;
@@ -2366,7 +2452,7 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
// conforming CAs SHOULD mark this extension as critical.
}
if (asn1_bits_from_der(&key_usage, &val, &vlen) != 1
|| x509_key_usage_validate(key_usage, cert_type) != 1) {
|| x509_key_usage_check(key_usage, cert_type) != 1) {
error_print();
return -1;
}
@@ -2396,7 +2482,7 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
case OID_ce_basic_constraints:
if (x509_basic_constraints_from_der(&ca, &path_len, &val, &vlen) != 1
|| x509_basic_constraints_validate(ca, path_len, cert_type) != 1) {
|| x509_basic_constraints_check(ca, path_len, cert_type) != 1) {
error_print();
return -1;
}
@@ -2407,7 +2493,7 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type,
case OID_ce_ext_key_usage:
if (x509_ext_key_usage_from_der(ext_key_usages, &ext_key_usages_cnt,
sizeof(ext_key_usages)/sizeof(ext_key_usages[0]), &val, &vlen) != 1
|| x509_ext_key_usage_validate(ext_key_usages, ext_key_usages_cnt, cert_type) != 1) {
|| x509_ext_key_usage_check(ext_key_usages, ext_key_usages_cnt, cert_type) != 1) {
error_print();
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
@@ -18,7 +18,12 @@
#include <gmssl/pem.h>
#include <gmssl/asn1.h>
#include <gmssl/x509_str.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
#include <gmssl/file.h>
#include <errno.h>
#include <sys/stat.h>
/*
DirectoryString ::= CHOICE {
@@ -35,88 +40,7 @@ RDN 中很多值都是这个类型,但是有特定的长度限制,因此这
*/
int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen)
{
switch (tag) {
case ASN1_TAG_TeletexString:
case ASN1_TAG_PrintableString:
case ASN1_TAG_UniversalString:
case ASN1_TAG_UTF8String:
if (d && strnlen((char *)d, dlen) != dlen) {
error_print();
return -1;
}
break;
case ASN1_TAG_BMPString:
if (d && dlen % 2) {
error_print();
return -1;
}
break;
default:
error_print();
return -1;
}
return 1;
}
int x509_directory_name_check_ex(int tag, const uint8_t *d, size_t dlen, size_t minlen, size_t maxlen)
{
if (x509_directory_name_check(tag, d, dlen) != 1) {
error_print();
return -1;
}
if (dlen < minlen || dlen > maxlen) {
printf("%s %d: dlen = %zu, minlen = %zu, maxlne = %zu\n", __FILE__, __LINE__, dlen, minlen, maxlen);
error_print();
return -1;
}
return 1;
}
int x509_directory_name_to_der(int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
int ret;
if (x509_directory_name_check(tag, d, dlen) != 1) {
error_print();
return -1;
}
if ((ret = asn1_type_to_der(tag, d, dlen, out, outlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
int x509_directory_name_from_der(int *tag, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
{
int ret;
if ((ret = asn1_tag_from_der_readonly(tag, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
switch (*tag) {
case ASN1_TAG_TeletexString:
case ASN1_TAG_PrintableString:
case ASN1_TAG_UniversalString:
case ASN1_TAG_UTF8String:
case ASN1_TAG_BMPString:
break;
default:
return 0;
}
if ((ret = asn1_any_type_from_der(tag, d, dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (x509_directory_name_check(*tag, *d, *dlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_explicit_directory_name_to_der(int index, int tag, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen)
{
@@ -153,11 +77,6 @@ int x509_explicit_directory_name_from_der(int index, int *tag, const uint8_t **d
return 1;
}
int x509_directory_name_print(FILE *fp, int fmt, int ind, const char *label, int tag, const uint8_t *d, size_t dlen)
{
return asn1_string_print(fp, fmt, ind, label, tag, d, dlen);
}
int x509_display_text_check(int tag, const uint8_t *d, size_t dlen)
{
switch (tag) {
@@ -233,3 +152,62 @@ int x509_display_text_print(FILE *fp, int fmt, int ind, const char *label, int t
{
return asn1_string_print(fp, fmt, ind, label, tag, d, dlen);
}
int x509_cert_new_from_file(uint8_t **out, size_t *outlen, const char *file)
{
int ret = -1;
FILE *fp = NULL;
size_t fsize;
uint8_t *buf = NULL;
size_t buflen;
if (!(fp = fopen(file, "r"))
|| file_size(fp, &fsize) != 1
|| (buflen = (fsize * 3)/4 + 1) < 0
|| (buf = malloc((fsize * 3)/4 + 1)) == NULL) {
error_print();
goto end;
}
if (x509_cert_from_pem(buf, outlen, buflen, fp) != 1) {
error_print();
goto end;
}
*out = buf;
buf = NULL;
ret = 1;
end:
if (fp) fclose(fp);
if (buf) free(buf);
return ret;
}
int x509_certs_new_from_file(uint8_t **out, size_t *outlen, const char *file)
{
int ret = -1;
FILE *fp = NULL;
size_t fsize;
uint8_t *buf = NULL;
size_t buflen;
if (!(fp = fopen(file, "r"))
|| file_size(fp, &fsize) != 1
|| (buflen = (fsize * 3)/4 + 1) < 0
|| (buf = malloc((fsize * 3)/4 + 1)) == NULL) {
error_print();
goto end;
}
if (x509_certs_from_pem(buf, outlen, buflen, fp) != 1) {
error_print();
goto end;
}
*out = buf;
buf = NULL;
ret = 1;
end:
if (fp) fclose(fp);
if (buf) free(buf);
return ret;
}

View File

@@ -607,6 +607,34 @@ static int test_asn1_time(void)
return 1;
}
static int test_asn1_time_limits(void)
{
char *tests[] = {
"20491231235959Z",
"20500101000000Z",
"99991231235959Z",
};
size_t i;
time_t tv[sizeof(tests)/sizeof(tests[0])];
char str[16] = {0};
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
if (asn1_time_from_str(0, &tv[i], tests[i]) != 1) {
error_print();
return -1;
}
fprintf(stderr, " %s: %lld\n", tests[i], (long long)tv[i]);
}
if (tv[0] + 1 != tv[1]) {
error_print();
return -1;
}
printf("%s() ok\n", __FUNCTION__);
return 1;
}
static int test_asn1_utc_time(void)
{
time_t tests[] = {
@@ -790,6 +818,7 @@ int main(void)
if (test_asn1_utf8_string() != 1) goto err;
if (test_asn1_ia5_string() != 1) goto err;
if (test_asn1_time() != 1) goto err;
if (test_asn1_time_limits() != 1) goto err;
if (test_asn1_utc_time() != 1) goto err;
if (test_asn1_generalized_time() != 1) goto err;
if (test_asn1_from_der_null_args() != 1) goto err;

View File

@@ -372,7 +372,8 @@ static int test_cms_signer_info_sign(void)
size_t namelen;
time_t not_before, not_after;
uint8_t certs[1024];
size_t certslen;
size_t certslen = 0;
uint8_t *pcerts = certs;
SM3_CTX sm3_ctx;
@@ -389,14 +390,15 @@ static int test_cms_signer_info_sign(void)
|| x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1
|| time(&not_before) == -1
|| x509_validity_add_days(&not_after, not_before, 365) != 1
|| x509_cert_sign(certs, &certslen, sizeof(certs),
|| x509_cert_sign_to_der(
X509_version_v3, serial_buf, sizeof(serial_buf),
OID_sm2sign_with_sm3,
name, namelen,
not_before, not_after,
name, namelen,
&sm2_key, NULL, 0, NULL, 0, NULL, 0,
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&pcerts, &certslen) != 1) {
error_print();
return -1;
}
@@ -571,8 +573,7 @@ static int test_cms_signed_data(void)
time(&not_before);
x509_validity_add_days(&not_after, not_before, 365);
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
if (x509_cert_sign_to_der(
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
@@ -583,7 +584,8 @@ static int test_cms_signed_data(void)
NULL, 0,
NULL, 0,
NULL, 0,
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&p, &certlen) != 1) {
error_print();
return -1;
}
@@ -775,13 +777,11 @@ int test_cms_enveloped_data(void)
p = certs;
certslen = 0;
maxlen = sizeof(certs);
if (sm2_key_generate(&sm2_key1) != 1
|| rand_bytes(serial1, sizeof(serial1)) != 1
|| x509_name_set(name1, &name1_len, sizeof(name1), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1
|| x509_cert_sign(
p, &len, maxlen,
|| x509_cert_sign_to_der(
X509_version_v3,
serial1, sizeof(serial1),
OID_sm2sign_with_sm3,
@@ -789,19 +789,16 @@ int test_cms_enveloped_data(void)
not_before, not_after,
name1, name1_len,
&sm2_key1, NULL, 0, NULL, 0, NULL, 0,
&sm2_key1, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
&sm2_key1, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&p, &certslen) != 1) {
error_print();
return -1;
}
p += len;
certslen += len;
maxlen -= len;
if (sm2_key_generate(&sm2_key2) != 1
|| rand_bytes(serial2, sizeof(serial2)) != 1
|| x509_name_set(name2, &name2_len, sizeof(name2), "CN", "Beijing", "Haidian", "PKU", "CS", "Bob") != 1
|| x509_cert_sign(
p, &len, maxlen,
|| x509_cert_sign_to_der(
X509_version_v3,
serial2, sizeof(serial2),
OID_sm2sign_with_sm3,
@@ -809,13 +806,11 @@ int test_cms_enveloped_data(void)
not_before, not_after,
name2, name2_len,
&sm2_key2, NULL, 0, NULL, 0, NULL, 0,
&sm2_key2, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
&sm2_key2, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&p, &certslen) != 1) {
error_print();
return -1;
}
p += len;
certslen += len;
maxlen -= len;
rand_bytes(key, sizeof(key));
rand_bytes(iv, sizeof(iv));
@@ -899,7 +894,7 @@ static int test_cms_key_agreement_info(void)
uint8_t serial[20];
time_t not_before, not_after;
uint8_t cert[2048];
size_t certlen;
size_t certlen = 0;
uint8_t buf[4096];
uint8_t *p;
@@ -915,13 +910,13 @@ static int test_cms_key_agreement_info(void)
const uint8_t *id;
size_t idlen;
p = cert;
if (sm2_key_generate(&sm2_key) != 1
|| rand_bytes(serial, sizeof(serial)) != 1
|| x509_name_set(name, &namelen, sizeof(name), "CN", "Beijing", "Haidian", "PKU", "CS", "Alice") != 1
|| time(&not_before) == - 1
|| x509_validity_add_days(&not_after, not_before, 365) != 1
|| x509_cert_sign(
cert, &certlen, sizeof(cert),
|| x509_cert_sign_to_der(
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
@@ -929,7 +924,8 @@ static int test_cms_key_agreement_info(void)
not_before, not_after,
name, namelen,
&sm2_key, NULL, 0, NULL, 0, NULL, 0,
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&p, &certlen) != 1) {
error_print();
return -1;
}

View File

@@ -779,7 +779,8 @@ static int test_x509_exts(void)
static int test_x509_cert_with_exts(void)
{
uint8_t cert[1024];
size_t certlen;
size_t certlen = 0;
uint8_t *p = cert;
uint8_t serial[20];
uint8_t name[256];
size_t namelen;
@@ -810,8 +811,7 @@ static int test_x509_cert_with_exts(void)
return -1;
}
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
if (x509_cert_sign_to_der(
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
@@ -823,10 +823,16 @@ static int test_x509_cert_with_exts(void)
uniq_id, sizeof(uniq_id),
exts, extslen,
&sm2_key,
SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID),
&p, &certlen) != 1) {
error_print();
return -1;
}
if (certlen > sizeof(cert)) {
error_print();
return -1;
}
x509_cert_print(stderr, 0, 0, "Certificate", cert, certlen);

View File

@@ -326,8 +326,7 @@ static int test_x509_cert(void)
set_x509_name(subject, &subject_len, sizeof(subject));
sm2_key_generate(&sm2_key);
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
if (x509_cert_sign_to_der(
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
@@ -338,7 +337,8 @@ static int test_x509_cert(void)
NULL, 0,
NULL, 0,
NULL, 0,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID),
&p, &certlen) != 1) {
error_print();
return -1;
}

View File

@@ -159,10 +159,11 @@ int certgen_main(int argc, char **argv)
char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t signer_id_len = 0;
uint8_t cert[4096];
size_t certlen;
uint8_t *cert = NULL;
size_t certlen = 0;
FILE *outfp = stdout;
char *outfile = NULL;
uint8_t *p;
// Extensions
uint8_t exts[4096];
@@ -500,8 +501,7 @@ bad:
}
}
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
if (x509_cert_sign_to_der(
X509_version_v3,
serial, serial_len,
OID_sm2sign_with_sm3,
@@ -512,7 +512,30 @@ bad:
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, signer_id, signer_id_len) != 1) {
&sm2_key, signer_id, signer_id_len,
NULL, &certlen) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
if (!(cert = malloc(certlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
p = cert;
certlen = 0;
if (x509_cert_sign_to_der(
X509_version_v3,
serial, serial_len,
OID_sm2sign_with_sm3,
name, namelen,
not_before, not_after,
name, namelen,
&sm2_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, signer_id, signer_id_len,
&p, &certlen) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
@@ -524,6 +547,7 @@ bad:
end:
gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
if (cert) free(cert);
if (keyfp) fclose(keyfp);
if (outfile && outfp) fclose(outfp);
return ret;

View File

@@ -185,8 +185,9 @@ int reqsign_main(int argc, char **argv)
// Output
char *outfile = NULL;
FILE *outfp = stdout;
uint8_t cert[4096];
size_t certlen;
uint8_t *cert = NULL;
size_t certlen = 0;
uint8_t *p;
// Extensions
uint8_t exts[4096];
@@ -559,8 +560,7 @@ bad:
}
}
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
if (x509_cert_sign_to_der(
X509_version_v3,
serial, serial_len,
OID_sm2sign_with_sm3,
@@ -571,10 +571,34 @@ bad:
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, signer_id, signer_id_len) != 1) {
&sm2_key, signer_id, signer_id_len,
NULL, &certlen) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
if (!(cert = malloc(certlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
p = cert;
certlen = 0;
if (x509_cert_sign_to_der(
X509_version_v3,
serial, serial_len,
OID_sm2sign_with_sm3,
issuer, issuer_len,
not_before, not_after,
subject, subject_len,
&subject_public_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, signer_id, signer_id_len,
&p, &certlen) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {
fprintf(stderr, "%s: output certificate failed\n", prog);
goto end;
@@ -582,6 +606,7 @@ bad:
ret = 0;
end:
gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
if (cert) free(cert);
if (keyfp) fclose(keyfp);
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);