From 6a02a61c4fbdba0f08a4b3a81becee5123313ee9 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Sat, 4 Feb 2023 21:04:43 +0800 Subject: [PATCH] Update X509 cert --- demos/certdemo.sh | 9 +- include/gmssl/x509.h | 51 +- include/gmssl/x509_ext.h | 13 +- include/gmssl/x509_str.h | 16 - src/asn1.c | 30 +- src/sm2_lib.c | 4 +- src/x509_cer.c | 1239 +++++++++++++++++--------------------- src/x509_crl.c | 44 +- src/x509_ext.c | 434 +++++++------ src/x509_str.c | 152 ++--- tests/asn1test.c | 29 + tests/cmstest.c | 42 +- tests/x509_exttest.c | 14 +- tests/x509test.c | 6 +- tools/certgen.c | 34 +- tools/reqsign.c | 35 +- 16 files changed, 1081 insertions(+), 1071 deletions(-) diff --git a/demos/certdemo.sh b/demos/certdemo.sh index 0b3d91ee..08b178fb 100755 --- a/demos/certdemo.sh +++ b/demos/certdemo.sh @@ -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 diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index ae3c29fa..e7797f2d 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -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); /* diff --git a/include/gmssl/x509_ext.h b/include/gmssl/x509_ext.h index 98805c31..164e5810 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -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); /* diff --git a/include/gmssl/x509_str.h b/include/gmssl/x509_str.h index ff8b1c9e..04e33f1f 100644 --- a/include/gmssl/x509_str.h +++ b/include/gmssl/x509_str.h @@ -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 { diff --git a/src/asn1.c b/src/asn1.c index 7334ae48..ac93fd9e 100644 --- a/src/asn1.c +++ b/src/asn1.c @@ -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; } diff --git a/src/sm2_lib.c b/src/sm2_lib.c index e198ca13..cd93c2ca 100644 --- a/src/sm2_lib.c +++ b/src/sm2_lib.c @@ -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; diff --git a/src/x509_cer.c b/src/x509_cer.c index 87d3376f..c8855f90 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -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 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ int x509_explicit_version_to_der(int index, int version, uint8_t **out, size_t * { size_t len = 0; - if (version < 0) { + if (version == -1) { return 0; } if (!x509_version_name(version)) { @@ -80,58 +81,56 @@ int x509_explicit_version_from_der(int index, int *version, const uint8_t **in, return 1; } -/* - from RFC 5280 section 4.1.2.5 - - CAs conforming to this profile MUST always encode certificate - validity dates through the year 2049 as UTCTime; certificate validity - dates in 2050 or later MUST be encoded as GeneralizedTime. - Conforming applications MUST be able to process validity dates that - are encoded in either UTCTime or GeneralizedTime. - - To indicate that a certificate has no well-defined expiration date, - the notAfter SHOULD be assigned the GeneralizedTime value of - 99991231235959Z. -*/ int x509_time_to_der(time_t tv, uint8_t **out, size_t *outlen) { - int ret; - static time_t utc_time_max = 0; + if (tv == -1) { + return 0; + } - if (!utc_time_max) { - if (asn1_time_from_str(0, &utc_time_max, "20500101000000Z") != 1) { + if (tv < -1 || tv > X509_MAX_GENERALIZED_TIME) { + error_print(); + return -1; + } + if (tv <= X509_MAX_UTC_TIME) { + if (asn1_utc_time_to_der(tv, out, outlen) != 1) { + error_print(); + return -1; + } + } else { + if (asn1_generalized_time_to_der(tv, out, outlen) !=1) { error_print(); return -1; } } - - if (tv < utc_time_max) { - if ((ret = asn1_utc_time_to_der(tv, out, outlen)) != 1) { - if (ret < 0) error_print(); - } - } else { - if ((ret = asn1_generalized_time_to_der(tv, out, outlen)) !=1) { - if (ret < 0) error_print(); - } - } - return ret; + return 1; } int x509_time_from_der(time_t *tv, const uint8_t **in, size_t *inlen) { int ret; + int tag; - if ((ret = asn1_utc_time_from_der(tv, in, inlen)) < 0) { - error_print(); - return -1; - } else if (ret) { - return 1; - } - - if ((ret = asn1_generalized_time_from_der(tv, in, inlen)) != 1) { + if ((ret = asn1_tag_from_der_readonly(&tag, in, inlen)) != 1) { if (ret < 0) error_print(); + else *tv = -1; return ret; } + switch (tag) { + case ASN1_TAG_UTCTime: + if (asn1_utc_time_from_der(tv, in, inlen) != 1) { + error_print(); + return -1; + } + break; + case ASN1_TAG_GeneralizedTime: + if (asn1_generalized_time_from_der(tv, in, inlen) != 1) { + error_print(); + return -1; + } + break; + default: + return 0; + } return 1; } @@ -168,6 +167,7 @@ int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); + else *not_before = *not_after = -1; return ret; } if (x509_time_from_der(not_before, &d, &dlen) != 1 @@ -183,7 +183,7 @@ int x509_validity_from_der(time_t *not_before, time_t *not_after, const uint8_t return 1; } -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) { if (!(not_before <= not_after)) { error_print(); @@ -218,6 +218,105 @@ err: return -1; } +int x509_directory_name_check(int tag, const uint8_t *d, size_t dlen) +{ + if (dlen == 0) { + return 0; + } + if (!d) { + error_print(); + return -1; + } + + switch (tag) { + case ASN1_TAG_TeletexString: + case ASN1_TAG_PrintableString: + case ASN1_TAG_UniversalString: + case ASN1_TAG_UTF8String: + if (strnlen((char *)d, dlen) != dlen) { + error_print(); + return -1; + } + break; + case ASN1_TAG_BMPString: + if (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) +{ + int ret; + + if ((ret = x509_directory_name_check(tag, d, dlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (dlen < minlen || dlen > 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 (dlen == 0) { + return 0; + } + if (x509_directory_name_check(tag, d, dlen) != 1) { + error_print(); + return -1; + } + if (asn1_type_to_der(tag, d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + 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 (asn1_any_type_from_der(tag, d, dlen, in, inlen) != 1) { + error_print(); + return -1; + } + if (x509_directory_name_check(*tag, *d, *dlen) != 1) { + error_print(); + return -1; + } + 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); +} static const struct { int oid; @@ -270,6 +369,10 @@ int x509_attr_type_and_value_to_der(int oid, int tag, const uint8_t *val, size_t uint8_t **out, size_t *outlen) { size_t len = 0; + + if (vlen == 0) { + return 0; + } if (x509_attr_type_and_value_check(oid, tag, val, vlen) != 1 || x509_name_type_to_der(oid, NULL, &len) != 1 || x509_directory_name_to_der(tag, val, vlen, NULL, &len) != 1 @@ -291,6 +394,11 @@ int x509_attr_type_and_value_from_der(int *oid, int *tag, const uint8_t **val, s if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); + else { + *tag = -1; + *val = NULL; + *vlen = 0; + } return ret; } if (x509_name_type_from_der(oid, &d, &dlen) != 1 @@ -339,16 +447,47 @@ err: return -1; } +int x509_rdn_check(const uint8_t *d, size_t dlen) +{ + int oid; + int tag; + const uint8_t *val; + size_t vlen; + + if (dlen == 0) { + return 0; + } + while (dlen) { + if (x509_attr_type_and_value_from_der(&oid, &tag, &val, &vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (vlen == 0) { + error_print(); + return -1; + } + } + return 1; +} + int x509_rdn_to_der(int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t morelen, uint8_t **out, size_t *outlen) { size_t len = 0; - if (x509_attr_type_and_value_to_der(oid, tag, val, vlen, NULL, &len) != 1 - || asn1_any_to_der(more, morelen, NULL, &len) < 0 + + if (vlen == 0 && morelen == 0) { + return 0; + } + if (x509_rdn_check(more, morelen) < 0) { + error_print(); + return -1; + } + if (x509_attr_type_and_value_to_der(oid, tag, val, vlen, NULL, &len) < 0 + || asn1_data_to_der(more, morelen, NULL, &len) < 0 || asn1_set_header_to_der(len, out, outlen) != 1 - || x509_attr_type_and_value_to_der(oid, tag, val, vlen, out, outlen) != 1 - || asn1_any_to_der(more, morelen, out, outlen) < 0) { + || x509_attr_type_and_value_to_der(oid, tag, val, vlen, out, outlen) < 0 + || asn1_data_to_der(more, morelen, out, outlen) < 0) { error_print(); return -1; } @@ -365,59 +504,46 @@ int x509_rdn_from_der(int *oid, int *tag, const uint8_t **val, size_t *vlen, if ((ret = asn1_set_from_der(&d, &dlen, in, inlen)) != 1) { if (ret < 0) error_print(); + else { + *oid = *tag = -1; + *val = *more = NULL; + *vlen = *morelen = 0; + } return ret; } if (x509_attr_type_and_value_from_der(oid, tag, val, vlen, &d, &dlen) != 1) { error_print(); return -1; } - if (dlen) { - *more = d; - *morelen = dlen; - // TODO: check more,morelen - } else { - *more = NULL; - *morelen = 0; - } - return 1; -} - -int x509_rdn_validate(const uint8_t *d, size_t dlen) -{ - int non_empty_attrs = 0; - const uint8_t *attr_d; - size_t attr_dlen; - - while (dlen) { - int oid; - int tag; - const uint8_t *val; - size_t vlen; - - if (asn1_sequence_from_der(&attr_d, &attr_dlen, &d, &dlen) != 1) { - error_print(); - return -1; - } - if (x509_attr_type_and_value_from_der(&oid, &tag, &val, &vlen, &attr_d, &attr_dlen) != 1 - || asn1_length_is_zero(attr_dlen) != 1) { - error_print(); - return -1; - } - if (val && vlen) { - if (tag != ASN1_TAG_PrintableString) { - non_empty_attrs++; - } else if (asn1_printable_string_case_ignore_match((char *)val, vlen, "", 0) != 1) { - non_empty_attrs++; - } - } - } - if (non_empty_attrs <= 0) { + if (x509_rdn_check(d, dlen) < 0) { error_print(); return -1; } + *more = dlen ? d : NULL; + *morelen = dlen; return 1; } +int x509_rdn_get_value_by_type(const uint8_t *d, size_t dlen, int type, int *tag, const uint8_t **val, size_t *vlen) +{ + int oid; + + while (dlen) { + if (x509_attr_type_and_value_from_der(&oid, tag, val, vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (oid == type) { + return 1; + } + } + + *tag = -1; + *val = NULL; + *vlen = 0; + return 0; +} + int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; @@ -442,27 +568,47 @@ int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t return 1; } +int x509_name_check(const uint8_t *d, size_t dlen) +{ + const uint8_t *rdn; + size_t rdnlen; + + if (dlen == 0) { + return 0; + } + while (dlen) { + if (asn1_set_from_der(&rdn, &rdnlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_rdn_check(rdn, rdnlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen, int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t morelen) { - size_t len = 0; - uint8_t *p = d + *dlen; + int ret; + uint8_t *p; + size_t len; - if (!val) { - if (more) { - error_print(); - return -1; - } - return 0; - } - if (x509_rdn_to_der(oid, tag, val, vlen, NULL, 0, NULL, &len) != 1 - || asn1_length_le(*dlen + len, maxlen) != 1 - || x509_rdn_to_der(oid, tag, val, vlen, NULL, 0, &p, dlen) != 1) { + if (!d || !dlen) { error_print(); return -1; } - return 1; + p = d + (*dlen); + if (x509_rdn_to_der(oid, tag, val, vlen, more, morelen, NULL, dlen) < 0 + || asn1_length_le(*dlen, maxlen) != 1 + || (ret = x509_rdn_to_der(oid, tag, val, vlen, more, morelen, &p, &len)) < 0) { + error_print(); + return -1; + } + return ret; } int x509_name_add_country_name(uint8_t *d, size_t *dlen, size_t maxlen, const char val[2]) @@ -528,7 +674,7 @@ int x509_name_add_domain_component(uint8_t *d, size_t *dlen, size_t maxlen, return ret; } -static size_t _strlen(const char *s) { return s ? strlen(s) : 0; } +static size_t optstrlen(const char *s) { return s ? strlen(s) : 0; } static int x509_name_tag(const char *str) { @@ -541,31 +687,29 @@ static int x509_name_tag(const char *str) } 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) { if (country && strlen(country) != 2) { error_print(); return -1; } - *dlen = 0; if (x509_name_add_country_name(d, dlen, maxlen, country) < 0 - || x509_name_add_state_or_province_name(d, dlen, maxlen, x509_name_tag(state), (uint8_t *)state, _strlen(state)) < 0 - || x509_name_add_locality_name(d, dlen, maxlen, x509_name_tag(locality), (uint8_t *)locality, _strlen(locality)) < 0 - || x509_name_add_organization_name(d, dlen, maxlen, x509_name_tag(org), (uint8_t *)org, _strlen(org)) < 0 - || x509_name_add_organizational_unit_name(d, dlen, maxlen, x509_name_tag(org_unit), (uint8_t *)org_unit, _strlen(org_unit)) < 0 - || x509_name_add_common_name(d, dlen, maxlen, x509_name_tag(common_name), (uint8_t *)common_name, _strlen(common_name)) != 1) { + || x509_name_add_state_or_province_name(d, dlen, maxlen, x509_name_tag(state), (uint8_t *)state, optstrlen(state)) < 0 + || x509_name_add_locality_name(d, dlen, maxlen, x509_name_tag(locality), (uint8_t *)locality, optstrlen(locality)) < 0 + || x509_name_add_organization_name(d, dlen, maxlen, x509_name_tag(org), (uint8_t *)org, optstrlen(org)) < 0 + || x509_name_add_organizational_unit_name(d, dlen, maxlen, x509_name_tag(org_unit), (uint8_t *)org_unit, optstrlen(org_unit)) < 0 + || x509_name_add_common_name(d, dlen, maxlen, x509_name_tag(common_name), (uint8_t *)common_name, optstrlen(common_name)) != 1) { error_print(); return -1; } return 1; } -// TODO: need to support NameConstraints -int x509_name_validate(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 rdn_cnt = 0; + int ret; const uint8_t *rdn; size_t rdnlen; @@ -574,16 +718,29 @@ int x509_name_validate(const uint8_t *d, size_t dlen) error_print(); return -1; } - if (x509_rdn_validate(rdn, rdnlen) != 1) { + if ((ret = x509_rdn_get_value_by_type(rdn, rdnlen, oid, tag, val, vlen)) < 0) { error_print(); return -1; } - rdn_cnt++; + if (ret) { + return 1; + } } + return 0; +} - if (rdn_cnt <= 0) { - error_print(); - return 0; // empty subject feild is allowed +int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen) +{ + int ret; + ret = x509_name_get_value_by_type(d, dlen, OID_at_common_name, tag, val, vlen); + if (ret < 0) error_print(); + return ret; +} + +int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) +{ + if (alen != blen || memcmp(a, b, blen) != 0) { + return 0; } return 1; } @@ -625,54 +782,6 @@ int x509_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_ return 1; } -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) -{ - const uint8_t *rdn_d; - size_t rdn_dlen; - - while (dlen) { - int attr_oid; - int attr_tag; - const uint8_t *attr_val; - size_t attr_vlen; - - if (asn1_set_from_der(&rdn_d, &rdn_dlen, &d, &dlen) != 1) { - error_print(); - return -1; - } - while (rdn_dlen) { - if (x509_attr_type_and_value_from_der(&attr_oid, &attr_tag, &attr_val, &attr_vlen, - &rdn_d, &rdn_dlen) != 1) { - error_print(); - return -1; - } - } - if (attr_oid == oid) { - *tag = attr_tag; - *val = attr_val; - *vlen = attr_vlen; - return 1; - } - } - return 0; -} - -int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen) -{ - int ret; - ret = x509_name_get_value_by_type(d, dlen, OID_at_common_name, tag, val, vlen); - if (ret < 0) error_print(); - return -1; -} - -int x509_name_equ(const uint8_t *a, size_t alen, const uint8_t *b, size_t blen) -{ - if (alen != blen || memcmp(a, b, blen) != 0) { - return 0; - } - return 1; -} - int x509_public_key_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p = d; @@ -706,144 +815,11 @@ err: return -1; } -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 (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_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; - } - *critical = 0; // FIXME: do not set default - 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_explicit_exts_to_der(int index, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) { size_t len = 0; - if (!d) { + + if (dlen == 0) { return 0; } if (asn1_sequence_to_der(d, dlen, NULL, &len) != 1 @@ -863,9 +839,13 @@ int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, cons if ((ret = asn1_explicit_from_der(index, &p, &len, in, inlen)) != 1) { if (ret < 0) error_print(); + else { + *d = NULL; + *dlen = 0; + } return ret; } - if (asn1_sequence_of_from_der(d, dlen, &p, &len) != 1 // TODO: check ALL SEQUENCE OF types + if (asn1_sequence_from_der(d, dlen, &p, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); return -1; @@ -873,57 +853,6 @@ int x509_explicit_exts_from_der(int index, const uint8_t **d, size_t *dlen, cons return 1; } -int x509_exts_get_count(const uint8_t *d, size_t dlen, size_t *cnt) -{ - return asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, 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) -{ - error_print(); - 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; - } - } - 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; -} - int x509_tbs_cert_to_der( int version, const uint8_t *serial, size_t serial_len, @@ -983,8 +912,8 @@ int x509_tbs_cert_from_der( size_t dlen; if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; + error_print(); + return -1; } if (x509_explicit_version_from_der(0, version, &d, &dlen) < 0 || asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 @@ -1039,116 +968,7 @@ err: return -1; } -int x509_certificate_to_der( - const uint8_t *tbs, size_t tbslen, // full TLV - int signature_algor, - const uint8_t *sig, size_t siglen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (asn1_data_to_der(tbs, tbslen, NULL, &len) != 1 - || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 - || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_data_to_der(tbs, tbslen, out, outlen) != 1 - || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 - || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_signed_to_der( - const uint8_t *tbs, size_t tbslen, // full TLV - int signature_algor, - const uint8_t *sig, size_t siglen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (asn1_data_to_der(tbs, tbslen, NULL, &len) != 1 - || x509_signature_algor_to_der(signature_algor, NULL, &len) != 1 - || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_data_to_der(tbs, tbslen, out, outlen) != 1 - || x509_signature_algor_to_der(signature_algor, out, outlen) != 1 - || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_signed_from_der(const uint8_t **tbs, size_t *tbs_len, - int *sig_alg, const uint8_t **sig, size_t *siglen, - 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 -1; - } - if (asn1_any_from_der(tbs, tbs_len, &d, &dlen) != 1 - || x509_signature_algor_from_der(sig_alg, &d, &dlen) != 1 - || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 - || asn1_length_is_zero(dlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_from_der( - const uint8_t **tbs, size_t *tbslen, // full TLV - int *signature_algor, - const uint8_t **sig, size_t *siglen, - 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 (asn1_any_from_der(tbs, tbslen, &d, &dlen) != 1 - || x509_signature_algor_from_der(signature_algor, &d, &dlen) != 1 - || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 - || asn1_length_is_zero(dlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) -{ - const uint8_t *p; - size_t len; - int val; - - format_print(fp, fmt, ind, "%s\n", label); - ind += 4; - - if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; - x509_tbs_cert_print(fp, fmt, ind, "tbsCertificate", p, len); - if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; - x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); - if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; - format_bytes(fp, fmt, ind, "signatureValue", p, len); - if (asn1_length_is_zero(dlen) != 1) goto err; - return 1; -err: - error_print(); - return -1; -} - -int x509_cert_sign( - uint8_t *cert, size_t *certlen, size_t maxlen, +int x509_cert_sign_to_der( int version, const uint8_t *serial, size_t serial_len, int signature_algor, @@ -1159,47 +979,102 @@ int x509_cert_sign( 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) + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen) { - uint8_t tbs[1024]; - size_t tbslen = 0; - uint8_t *p = tbs; size_t len = 0; - SM2_SIGN_CTX sign_ctx; + uint8_t *tbs; + size_t tbslen; int sig_alg = OID_sm2sign_with_sm3; uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; - size_t siglen; + size_t siglen = SM2_signature_typical_size; - if (x509_tbs_cert_to_der(version, serial, serial_len, signature_algor, - issuer, issuer_len, not_before, not_after, - subject, subject_len, subject_public_key, - issuer_unique_id, issuer_unique_id_len, - subject_unique_id, subject_unique_id_len, - exts, exts_len, NULL, &len) != 1 - || asn1_length_le(len, sizeof(tbs)) != 1 - || x509_tbs_cert_to_der(version, serial, serial_len, signature_algor, - issuer, issuer_len, not_before, not_after, - subject, subject_len, subject_public_key, - issuer_unique_id, issuer_unique_id_len, - subject_unique_id, subject_unique_id_len, - exts, exts_len, &p, &tbslen) != 1) { + if (x509_tbs_cert_to_der( + version, + serial, serial_len, + signature_algor, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, + NULL, &len) != 1) { + error_print(); + return -1; + } + tbslen = len; + if (x509_signature_algor_to_der(sig_alg, NULL, &len) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &len) != 1) { error_print(); return -1; } - if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 - || sm2_sign_update(&sign_ctx, tbs, tbslen) != 1 - || sm2_sign_finish(&sign_ctx, sig, &siglen) != 1) { - memset(&sign_ctx, 0, sizeof(sign_ctx)); + if (asn1_sequence_header_to_der(len, out, outlen) != 1) { error_print(); return -1; } - memset(&sign_ctx, 0, sizeof(sign_ctx)); + tbs = *out; - *certlen = len = 0; - if (x509_certificate_to_der(tbs, tbslen, sig_alg, sig, siglen, NULL, &len) != 1 - || asn1_length_le(len, maxlen) != 1 - || x509_certificate_to_der(tbs, tbslen, sig_alg, sig, siglen, &cert, certlen) != 1) { + if (x509_tbs_cert_to_der( + version, + serial, serial_len, + signature_algor, + issuer, issuer_len, + not_before, not_after, + subject, subject_len, + subject_public_key, + issuer_unique_id, issuer_unique_id_len, + subject_unique_id, subject_unique_id_len, + exts, exts_len, + out, outlen) != 1) { + error_print(); + return -1; + } + tbslen = *out - tbs; + + if (out && *out) { + SM2_SIGN_CTX sign_ctx; + if (sm2_sign_init(&sign_ctx, sign_key, signer_id, signer_id_len) != 1 + || sm2_sign_update(&sign_ctx, tbs, tbslen) != 1 + || sm2_sign_finish_fixlen(&sign_ctx, siglen, sig) != 1) { + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + error_print(); + return -1; + } + gmssl_secure_clear(&sign_ctx, sizeof(sign_ctx)); + } + + if (x509_signature_algor_to_der(sig_alg, out, outlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_signed_from_der(const uint8_t **tbs, size_t *tbslen, + int *sig_alg, const uint8_t **sig, size_t *siglen, + 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(); + else { + *tbs = *sig = NULL; + *tbslen = *siglen = 0; + *sig_alg = -1; + } + return ret; + } + if (asn1_any_from_der(tbs, tbslen, &d, &dlen) != 1 + || x509_signature_algor_from_der(sig_alg, &d, &dlen) != 1 + || asn1_bit_octets_from_der(sig, siglen, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } @@ -1209,7 +1084,6 @@ int x509_cert_sign( 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; const uint8_t *tbs; size_t tbslen; int sig_alg; @@ -1228,12 +1102,11 @@ int x509_signed_verify(const uint8_t *a, size_t alen, } if (sm2_verify_init(&verify_ctx, pub_key, signer_id, signer_id_len) != 1 || sm2_verify_update(&verify_ctx, tbs, tbslen) != 1 - || (ret = sm2_verify_finish(&verify_ctx, sig, siglen)) < 0) { + || sm2_verify_finish(&verify_ctx, sig, siglen) != 1) { error_print(); return -1; } - if (!ret) error_print(); - return ret; + return 1; } int x509_signed_verify_by_ca_cert(const uint8_t *a, size_t alen, @@ -1256,6 +1129,17 @@ 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) { + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *subject; + size_t subject_len; + + if (x509_cert_get_issuer(a, alen, &issuer, &issuer_len) != 1 + || x509_cert_get_subject(cacert, cacertlen, &subject, &subject_len) != 1 + || x509_name_equ(issuer, issuer_len, subject, subject_len) != 1) { + error_print(); + return -1; + } if (x509_signed_verify_by_ca_cert(a, alen, cacert, cacertlen, signer_id, signer_id_len) != 1) { error_print(); return -1; @@ -1265,16 +1149,34 @@ int x509_cert_verify_by_ca_cert(const uint8_t *a, size_t alen, 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); + int ret; + if ((ret = asn1_any_to_der(a, alen, out, outlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; } int x509_cert_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen) { - return asn1_any_from_der(a, alen, in, inlen); + int ret; + if ((ret = asn1_any_from_der(a, alen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_cert_get_subject(*a, *alen, NULL, NULL) != 1) { + error_print(); + return -1; + } + return 1; } int x509_cert_to_pem(const uint8_t *a, size_t alen, FILE *fp) { + if (x509_cert_get_subject(a, alen, NULL, NULL) != 1) { + error_print(); + return -1; + } if (pem_write(fp, "CERTIFICATE", a, alen) != 1) { error_print(); return -1; @@ -1287,19 +1189,12 @@ int x509_cert_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) int ret; if ((ret = pem_read(fp, "CERTIFICATE", a, alen, maxlen)) != 1) { if (ret < 0) error_print(); + else *alen = 0; return ret; } - return 1; -} - -int x509_cert_from_pem_by_index(uint8_t *a, size_t *alen, size_t maxlen, int index, FILE *fp) -{ - int i; - for (i = 0; i <= index; i++) { - if (x509_cert_from_pem(a, alen, maxlen, fp) != 1) { - error_print(); - return -1; - } + if (x509_cert_get_subject(a, *alen, NULL, NULL) != 1) { + error_print(); + return -1; } return 1; } @@ -1313,20 +1208,43 @@ int x509_cert_from_pem_by_subject(uint8_t *a, size_t *alen, size_t maxlen, const for (;;) { if ((ret = x509_cert_from_pem(a, alen, maxlen, fp)) != 1) { if (ret < 0) error_print(); + else *alen = 0; return ret; } if (x509_cert_get_subject(a, *alen, &d, &dlen) != 1) { error_print(); return -1; } - - if (dlen == namelen && memcmp(name, d, dlen) == 0) { + if (x509_name_equ(d, dlen, name, namelen) == 1) { return 1; } } + *alen = 0; return 0; } +static int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + int val; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_tbs_cert_print(fp, fmt, ind, "tbsCertificate", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len); + if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err; + format_bytes(fp, fmt, ind, "signatureValue", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); + return -1; +} + int x509_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) { const uint8_t *d; @@ -1358,67 +1276,62 @@ int x509_cert_get_details(const uint8_t *a, size_t alen, int *signature_algor, const uint8_t **signature, size_t *signature_len) { - const uint8_t *tbs; - size_t tbs_len; + const uint8_t *tbs_a; + size_t tbs_alen; int sig_alg; - const uint8_t *sig; size_t sig_len; + const uint8_t *sig; + size_t sig_len; - const uint8_t *d; - size_t dlen; + struct { + int version; + const uint8_t *serial; size_t serial_len; + int sig_alg; + const uint8_t *issuer; size_t issuer_len; + time_t not_before; time_t not_after; + const uint8_t *subject; size_t subject_len; + 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; + } tbs; - int ver; - const uint8_t *serial; size_t serial_len; - int inner_sig_alg; - const uint8_t *isur; size_t isur_len; - time_t before, after; - const uint8_t *subj; size_t subj_len; - SM2_KEY sm2_key; - const uint8_t *isur_uniq_id; size_t isur_uniq_id_len; - const uint8_t *subj_uniq_id; size_t subj_uniq_id_len; - const uint8_t *exts; size_t exts_len; - - if (x509_certificate_from_der(&tbs, &tbs_len, &sig_alg, &sig, &sig_len, &a, &alen) != 1 + if (x509_signed_from_der(&tbs_a, &tbs_alen, &sig_alg, &sig, &sig_len, &a, &alen) != 1 || asn1_length_is_zero(alen) != 1) { error_print(); return -1; } - if (asn1_sequence_from_der(&d, &dlen, &tbs, &tbs_len) != 1 - || asn1_length_is_zero(tbs_len) != 1) { + if (x509_tbs_cert_from_der( + &tbs.version, + &tbs.serial, &tbs.serial_len, + &tbs.sig_alg, + &tbs.issuer, &tbs.issuer_len, + &tbs.not_before, &tbs.not_after, + &tbs.subject, &tbs.subject_len, + &tbs.subject_public_key, + &tbs.issuer_unique_id, &tbs.issuer_unique_id_len, + &tbs.subject_unique_id, &tbs.subject_unique_id_len, + &tbs.exts, &tbs.exts_len, &tbs_a, &tbs_alen) != 1) { error_print(); return -1; } - if (x509_explicit_version_from_der(0, &ver, &d, &dlen) < 0 - || asn1_integer_from_der(&serial, &serial_len, &d, &dlen) != 1 - || x509_signature_algor_from_der(&inner_sig_alg, &d, &dlen) != 1 - || asn1_sequence_from_der(&isur, &isur_len, &d, &dlen) != 1 - || x509_validity_from_der(&before, &after, &d, &dlen) != 1 - || asn1_sequence_from_der(&subj, &subj_len, &d, &dlen) != 1 - || x509_public_key_info_from_der(&sm2_key, &d, &dlen) != 1 - || asn1_implicit_bit_octets_from_der(1, &isur_uniq_id, &isur_uniq_id_len, &d, &dlen) < 0 - || asn1_implicit_bit_octets_from_der(2, &subj_uniq_id, &subj_uniq_id_len, &d, &dlen) < 0 - || x509_explicit_exts_from_der(3, &exts, &exts_len, &d, &dlen) < 0) { - error_print(); - return -1; - } - - if (version) *version = ver; - if (serial_number) *serial_number = serial; - if (serial_number_len) *serial_number_len = serial_len; - if (inner_signature_algor) *inner_signature_algor = inner_sig_alg; - if (issuer) *issuer = isur; - if (issuer_len) *issuer_len = isur_len; - if (not_before) *not_before = before; - if (not_after) *not_after = after; - if (subject) *subject = subj; - if (subject_len) *subject_len = subj_len; - if (subject_public_key) *subject_public_key = sm2_key; - if (issuer_unique_id) *issuer_unique_id = isur_uniq_id; - if (issuer_unique_id_len) *issuer_unique_id_len = isur_uniq_id_len; - if (subject_unique_id) *subject_unique_id = subj_uniq_id; - if (subject_unique_id_len) *subject_unique_id_len = subj_uniq_id_len; - if (extensions) *extensions = exts; - if (extensions_len) *extensions_len = exts_len; + if (version) *version = tbs.version; + if (serial_number) *serial_number = tbs.serial; + if (serial_number_len) *serial_number_len = tbs.serial_len; + if (inner_signature_algor) *inner_signature_algor = tbs.sig_alg; + if (issuer) *issuer = tbs.issuer; + if (issuer_len) *issuer_len = tbs.issuer_len; + if (not_before) *not_before = tbs.not_before; + if (not_after) *not_after = tbs.not_after; + if (subject) *subject = tbs.subject; + if (subject_len) *subject_len = tbs.subject_len; + if (subject_public_key) *subject_public_key = tbs.subject_public_key; + if (issuer_unique_id) *issuer_unique_id = tbs.issuer_unique_id; + if (issuer_unique_id_len) *issuer_unique_id_len = tbs.issuer_unique_id_len; + if (subject_unique_id) *subject_unique_id = tbs.subject_unique_id; + if (subject_unique_id_len) *subject_unique_id_len = tbs.subject_unique_id_len; + if (extensions) *extensions = tbs.exts; + if (extensions_len) *extensions_len = tbs.exts_len; if (signature_algor) *signature_algor = sig_alg; if (signature) *signature = sig; if (signature_len) *signature_len = sig_len; @@ -1538,7 +1451,9 @@ int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp) int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp) { int ret; - size_t len, total_len = 0; + size_t len; + + *dlen = 0; for (;;) { if ((ret = x509_cert_from_pem(d, &len, maxlen, fp)) < 0) { @@ -1547,12 +1462,13 @@ int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp) } else if (ret == 0) { break; } + d += len; - total_len += len; + *dlen += len; maxlen -= len; } - *dlen = total_len; - if (!total_len) { + + if (*dlen == 0) { return 0; } return 1; @@ -1560,36 +1476,38 @@ int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp) int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt) { - if (asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt) != 1) { - error_print(); - return -1; - } - return 1; + int ret; + ret = asn1_types_get_count(d, dlen, ASN1_TAG_SEQUENCE, cnt); + if (ret < 0) error_print(); + return ret; } int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen) { - const uint8_t *a; - size_t alen; - int ret, i; + int i = 0; - for (i = 0; i <= index; i++) { - if ((ret = x509_cert_from_der(&a, &alen, &d, &dlen)) != 1) { - if (ret < 0) error_print(); - else error_print(); + if (index < 0) { + error_print(); + return -1; + } + while (dlen) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { + error_print(); return -1; } + if (i++ == index) { + return 1; + } } - *cert = a; - *certlen = alen; - return 1; + *cert = NULL; + *certlen = 0; + return 0; } int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, size_t *certlen) { - if (!dlen) { - error_print(); - return -1; + if (dlen == 0) { + return 0; } while (dlen) { if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { @@ -1603,44 +1521,29 @@ int x509_certs_get_last(const uint8_t *d, size_t dlen, const uint8_t **cert, siz int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen) { - const uint8_t *a; - size_t alen; const uint8_t *subj; size_t subj_len; while (dlen) { - if (x509_cert_from_der(&a, &alen, &d, &dlen) != 1) { + if (x509_cert_from_der(cert, certlen, &d, &dlen) != 1) { error_print(); return -1; } - if (x509_cert_get_subject(a, alen, &subj, &subj_len) != 1) { + if (x509_cert_get_subject(*cert, *certlen, &subj, &subj_len) != 1) { error_print(); return -1; } if (x509_name_equ(subj, subj_len, subject, subject_len) == 1) { - *cert = a; - *certlen = alen; return 1; } } - error_print(); // 可能来自于没有找到对应的CA证书 + *cert = NULL; + *certlen = 0; return 0; } -int x509_certs_get_cert_by_subject_and_key_identifier(const uint8_t *d, size_t dlen, - const uint8_t *subject, size_t subject_len, - const uint8_t *key_id, size_t key_id_len, // AuthorityKeyIdentifier.keyIdentifier - const uint8_t **cert, size_t *certlen) -{ - // TODO: implement this - error_print(); - return -1; -} - -int x509_certs_get_cert_by_issuer_and_serial_number( - const uint8_t *certs, size_t certs_len, - const uint8_t *issuer, size_t issuer_len, - const uint8_t *serial, size_t serial_len, +int x509_certs_get_cert_by_issuer_and_serial_number(const uint8_t *d, size_t dlen, + const uint8_t *issuer, size_t issuer_len, const uint8_t *serial, size_t serial_len, const uint8_t **cert, size_t *cert_len) { const uint8_t *cur_issuer; @@ -1648,50 +1551,43 @@ int x509_certs_get_cert_by_issuer_and_serial_number( const uint8_t *cur_serial; size_t cur_serial_len; - while (certs_len) { - if (asn1_any_from_der(cert, cert_len, &certs, &certs_len) != 1 + while (dlen) { + if (x509_cert_from_der(cert, cert_len, &d, &dlen) != 1 || x509_cert_get_issuer_and_serial_number(*cert, *cert_len, - &cur_issuer, &cur_issuer_len, - &cur_serial, &cur_serial_len) != 1) { + &cur_issuer, &cur_issuer_len, &cur_serial, &cur_serial_len) != 1) { error_print(); return -1; } - if (cur_issuer_len == issuer_len - && memcmp(cur_issuer, issuer, issuer_len) == 0 - && cur_serial_len == serial_len - && memcmp(cur_serial, serial, serial_len) == 0) { + if (x509_name_equ(cur_issuer, cur_issuer_len, issuer, issuer_len) == 1 + && cur_serial_len == serial_len && memcmp(cur_serial, serial, serial_len) == 0) { return 1; } } + *cert = NULL; + *cert_len = 0; return 0; } -// 这里面需要validate的类型是两种,一种直接得到了实际值,因此可以直接对实际值做验证 -// 另一种是SEQUENCE OF类型,本质上是完整的a,alen,因此这种类型实际上可以用from_der来解析 -int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, +int x509_cert_check(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraint) { int version; - time_t now; - time_t not_before; - time_t not_after; + const uint8_t *serial; + size_t serial_len; + int tbs_sig_algor; const uint8_t *issuer; size_t issuer_len; + time_t not_before; + time_t not_after; + time_t now; const uint8_t *subject; size_t subject_len; const uint8_t *exts; size_t extslen; - int tbs_sig_algor; int sig_algor; - const uint8_t *serial; - size_t serial_len; - const uint8_t *issuer_uniq_id; - size_t issuer_uniq_id_len; - const uint8_t *subj_uniq_id; - size_t subj_uniq_id_len; - x509_cert_get_details(cert, certlen, + if (x509_cert_get_details(cert, certlen, &version, // version &serial, &serial_len, // serial &tbs_sig_algor, // signature_algor @@ -1699,17 +1595,20 @@ int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, ¬_before, ¬_after, // validity &subject, &subject_len, // subject NULL, // subject_public_key - &issuer_uniq_id, &issuer_uniq_id_len, // issuer_unique_id - &subj_uniq_id, &subj_uniq_id_len, // subject_unique_id + NULL, NULL, // issuer_unique_id + NULL, NULL, // subject_unique_id &exts, &extslen, // extensions &sig_algor, // signature_algor - NULL, NULL); // signature + NULL, NULL // signature + ) != 1) { + error_print(); + return -1; + } if (version != X509_version_v3) { error_print(); return -1; } - if (!serial || !serial_len) { error_print(); return -1; @@ -1719,32 +1618,25 @@ int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, } time(&now); - if (x509_validity_validate(not_before, not_after, now, X509_VALIDITY_MAX_SECONDS) != 1) { + if (x509_validity_check(not_before, not_after, now, X509_VALIDITY_MAX_SECONDS) != 1) { error_print(); return -1; } // check issuer and subject not empty - if (x509_name_validate(issuer, issuer_len) != 1) { + if (x509_name_check(issuer, issuer_len) != 1) { error_print(); return -1; } - if (x509_name_validate(subject, subject_len) != 1) { + if (x509_name_check(subject, subject_len) != 1) { error_print(); return -1; } - // CAs conforming to RFC 5280 MUST NOT generate certificates with unique identifiers - if (issuer_uniq_id || subj_uniq_id) { - error_print(); - //return -1; - } - - if (x509_exts_validate(exts, extslen, cert_type, path_len_constraint) != 1) { + if (x509_exts_check(exts, extslen, cert_type, path_len_constraint) != 1) { error_print(); return -1; } - if (tbs_sig_algor != sig_algor) { error_print(); return -1; @@ -1784,7 +1676,7 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, error_print(); return -1; } - if (x509_cert_validate(cert, certlen, entity_cert_type, &path_len_constraint) != 1) { + if (x509_cert_check(cert, certlen, entity_cert_type, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1795,7 +1687,7 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, error_print(); return -1; } - if (x509_cert_validate(cert, certlen, X509_cert_ca, &path_len_constraint) != 1) { + if (x509_cert_check(cert, certlen, X509_cert_ca, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1833,7 +1725,7 @@ int x509_certs_verify(const uint8_t *certs, size_t certslen, int certs_type, return -1; } - if (x509_cert_validate(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1886,7 +1778,7 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type error_print(); return -1; } - if (x509_cert_validate(cert, certlen, sign_cert_type, &path_len_constraint) != 1) { + if (x509_cert_check(cert, certlen, sign_cert_type, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1896,7 +1788,7 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type error_print(); return -1; } - if (x509_cert_validate(kenc_cert, kenc_certlen, kenc_cert_type, &path_len_constraint) != 1) { + if (x509_cert_check(kenc_cert, kenc_certlen, kenc_cert_type, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1907,7 +1799,7 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type error_print(); return -1; } - if (x509_cert_validate(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1951,7 +1843,7 @@ int x509_certs_verify_tlcp(const uint8_t *certs, size_t certslen, int certs_type error_print(); return -1; } - if (x509_cert_validate(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { + if (x509_cert_check(cacert, cacertlen, X509_cert_ca, &path_len_constraint) != 1) { error_print(); return -1; } @@ -1995,62 +1887,3 @@ int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_ } return 1; } - -#include -#include - -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; -} diff --git a/src/x509_crl.c b/src/x509_crl.c index 8d38f19b..81febf8f 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -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; } - - diff --git a/src/x509_ext.c b/src/x509_ext.c index 7018b75d..2b2631d8 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -24,12 +24,34 @@ #include +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; } diff --git a/src/x509_str.c b/src/x509_str.c index 307f960a..928eec21 100644 --- a/src/x509_str.c +++ b/src/x509_str.c @@ -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 #include #include +#include #include +#include + +#include +#include /* 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; +} + diff --git a/tests/asn1test.c b/tests/asn1test.c index a9b42991..0ed5ce79 100644 --- a/tests/asn1test.c +++ b/tests/asn1test.c @@ -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; diff --git a/tests/cmstest.c b/tests/cmstest.c index 941d6321..660d0881 100644 --- a/tests/cmstest.c +++ b/tests/cmstest.c @@ -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(¬_before) == -1 || x509_validity_add_days(¬_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(¬_before); x509_validity_add_days(¬_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(¬_before) == - 1 || x509_validity_add_days(¬_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; } diff --git a/tests/x509_exttest.c b/tests/x509_exttest.c index 0af731bf..9a350170 100644 --- a/tests/x509_exttest.c +++ b/tests/x509_exttest.c @@ -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); diff --git a/tests/x509test.c b/tests/x509test.c index 408d2706..e8df4fa5 100644 --- a/tests/x509test.c +++ b/tests/x509test.c @@ -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; } diff --git a/tools/certgen.c b/tools/certgen.c index ebcf611f..38830658 100644 --- a/tools/certgen.c +++ b/tools/certgen.c @@ -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; diff --git a/tools/reqsign.c b/tools/reqsign.c index 0f8e65ba..34c4a911 100644 --- a/tools/reqsign.c +++ b/tools/reqsign.c @@ -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);