From c4c11ffe6bda205671663e5cf7162fd63ef03039 Mon Sep 17 00:00:00 2001 From: Zhi Guan Date: Wed, 25 Jan 2023 22:39:12 +0800 Subject: [PATCH] Update CRL functions and tools --- CMakeLists.txt | 2 + demos/wget.c | 33 ++ include/gmssl/asn1.h | 1 + include/gmssl/file.h | 3 +- include/gmssl/http.h | 4 +- include/gmssl/oid.h | 5 +- include/gmssl/sm2.h | 3 +- include/gmssl/x509.h | 12 + include/gmssl/x509_crl.h | 177 +++--- include/gmssl/x509_ext.h | 11 +- src/file.c | 30 +- src/http.c | 70 ++- src/sm2_lib.c | 19 +- src/x509_cer.c | 46 +- src/x509_crl.c | 1193 +++++++++++++++++++++++++++----------- src/x509_ext.c | 168 +++++- tests/httptest.c | 27 +- tests/x509_crltest.c | 267 ++++++++- tools/certrevoke.c | 139 +++++ tools/crlgen.c | 161 +++++ tools/gmssl.c | 10 +- 21 files changed, 1854 insertions(+), 527 deletions(-) create mode 100644 demos/wget.c create mode 100644 tools/certrevoke.c create mode 100644 tools/crlgen.c diff --git a/CMakeLists.txt b/CMakeLists.txt index da1af8f4..27709149 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,9 +99,11 @@ set(tools tools/certgen.c tools/certparse.c tools/certverify.c + tools/certrevoke.c tools/reqgen.c tools/reqparse.c tools/reqsign.c + tools/crlgen.c tools/crlparse.c tools/crlverify.c tools/cmssign.c diff --git a/demos/wget.c b/demos/wget.c new file mode 100644 index 00000000..b1317314 --- /dev/null +++ b/demos/wget.c @@ -0,0 +1,33 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + uint8_t buf[65536]; + uint8_t *content; + size_t contentlen; + + if (argc < 2) { + printf("usage: %s \n", argv[0]); + return 1; + } + if (http_get(argv[1], buf, sizeof(buf), &content, &contentlen) != 1) { + error_print(); + return -1; + } + fwrite(content, contentlen, 1, stdout); + return 0; +} diff --git a/include/gmssl/asn1.h b/include/gmssl/asn1.h index 6c3fbd1b..307fc646 100644 --- a/include/gmssl/asn1.h +++ b/include/gmssl/asn1.h @@ -260,6 +260,7 @@ int asn1_string_print(FILE *fp, int fmt, int ind, const char *label, int tag, co #define ASN1_UTC_TIME_STRLEN (sizeof("YYMMDDHHMMSSZ")-1) #define ASN1_GENERALIZED_TIME_STRLEN (sizeof("YYYYMMDDHHMMSSZ")-1) +#define ASN1_GENERALIZED_TIME_MAX_SIZE (2 + ASN1_GENERALIZED_TIME_STRLEN) int asn1_time_to_str(int utc_time, time_t timestamp, char *str); int asn1_time_from_str(int utc_time, time_t *timestamp, const char *str); diff --git a/include/gmssl/file.h b/include/gmssl/file.h index 4906e2ce..1165e5be 100644 --- a/include/gmssl/file.h +++ b/include/gmssl/file.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -19,6 +19,7 @@ extern "C" { int file_size(FILE *fp, size_t *size); +int file_read_all(const char *file, uint8_t **out, size_t *outlen); #ifdef __cplusplus diff --git a/include/gmssl/http.h b/include/gmssl/http.h index 157b71be..cda8ad7b 100644 --- a/include/gmssl/http.h +++ b/include/gmssl/http.h @@ -19,8 +19,8 @@ extern "C" { int http_parse_uri(const char *uri, char host[128], int *port, char path[256]); -int http_parse_response(uint8_t *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left); -int http_get(const char *uri, uint8_t *buf, size_t buflen, uint8_t **content, size_t *contentlen); +int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left); +int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen); #ifdef __cplusplus diff --git a/include/gmssl/oid.h b/include/gmssl/oid.h index 9e1ceb3d..f7336768 100644 --- a/include/gmssl/oid.h +++ b/include/gmssl/oid.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -205,8 +205,7 @@ enum { -#define oid_cnt(nodes) (sizeof(nodes)/sizeof(int)) - +#define oid_cnt(nodes) (sizeof(nodes)/sizeof((nodes)[0])) diff --git a/include/gmssl/sm2.h b/include/gmssl/sm2.h index 5fef50a5..32a56a75 100644 --- a/include/gmssl/sm2.h +++ b/include/gmssl/sm2.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -323,6 +323,7 @@ typedef struct { int sm2_sign_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); int sm2_sign_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen); +int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig); int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen); int sm2_verify_update(SM2_SIGN_CTX *ctx, const uint8_t *data, size_t datalen); diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index ddcd95b0..9a706754 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -268,6 +268,18 @@ int x509_certificate_from_der( int *signature_algor, const uint8_t **sig, size_t *siglen, const uint8_t **in, size_t *inlen); + +int x509_signed_to_der( + const uint8_t *tbs, size_t tbslen, + int signature_algor, + const uint8_t *sig, size_t siglen, + uint8_t **out, size_t *outlen); +int x509_signed_from_der( + const uint8_t **tbs, size_t *tbslen, + int *signature_algor, + const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen); + int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); // x509_cert functions diff --git a/include/gmssl/x509_crl.h b/include/gmssl/x509_crl.h index 593957c7..7c2c7bb1 100644 --- a/include/gmssl/x509_crl.h +++ b/include/gmssl/x509_crl.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -13,17 +13,15 @@ #define GMSSL_X509_CRL_H +#include +#include +#include + + #ifdef __cplusplus extern "C" { #endif -/* -X509 CRL Public API - - -*/ - - /* CRLReason ::= ENUMERATED @@ -46,34 +44,41 @@ const char *x509_crl_reason_name(int reason); int x509_crl_reason_from_name(int *reason, const char *name); int x509_crl_reason_to_der(int reason, uint8_t **out, size_t *outlen); int x509_crl_reason_from_der(int *reason, const uint8_t **in, size_t *inlen); +int x509_implicit_crl_reason_from_der(int index, int *reason, const uint8_t **in, size_t *inlen); /* CRL Entry Extensions: - OID_ce_crl_reasons ENUMERATED - OID_ce_invalidity_date GeneralizedTime - OID_ce_certificate_issuer SEQUENCE GeneralNames + OID_ce_crl_reasons ENUMERATED non-critical + OID_ce_invalidity_date GeneralizedTime non-critical + OID_ce_certificate_issuer GeneralNames MUST critical */ const char *x509_crl_entry_ext_id_name(int oid); int x509_crl_entry_ext_id_from_name(const char *name); int x509_crl_entry_ext_id_to_der(int oid, uint8_t **out, size_t *outlen); int x509_crl_entry_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen); -int x509_crl_entry_exts_add_reason( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - int reason); -int x509_crl_entry_exts_add_invalidity_date( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - time_t tv); -int x509_crl_entry_exts_add_certificate_issuer( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - const uint8_t *d, size_t dlen); -#define x509_crl_entry_exts_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) -#define x509_crl_entry_exts_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) +int x509_crl_entry_ext_critical_validate(int oid, int critical); + +int x509_crl_reason_ext_to_der(int critical, int reason, uint8_t **out, size_t *outlen); +int x509_invalidity_date_ext_to_der(int critical, time_t date, uint8_t **out, size_t *outlen); +int x509_cert_issuer_ext_to_der(int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen); +int x509_crl_entry_ext_from_der(int *oid, int *critical, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_crl_entry_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_entry_exts_to_der( + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); +int x509_crl_entry_exts_from_der( + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen); +int x509_crl_entry_exts_get(const uint8_t *d, size_t dlen, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len); +int x509_crl_entry_exts_validate(const uint8_t *d, size_t dlen); int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + /* RevokedCertificate ::= SEQUENCE { userCertificate CertificateSerialNumber, @@ -81,45 +86,50 @@ RevokedCertificate ::= SEQUENCE { crlEntryExtensions Extensions OPTIONAL } */ int x509_revoked_cert_to_der( - const uint8_t *serial, size_t serial_len, - time_t revoke_date, - const uint8_t *entry_exts, size_t entry_exts_len, + const uint8_t *serial, size_t serial_len, time_t revoke_date, + const uint8_t *crl_entry_exts, size_t crl_entry_exts_len, uint8_t **out, size_t *outlen); int x509_revoked_cert_from_der( - const uint8_t **serial, size_t *serial_len, - time_t *revoke_date, - const uint8_t **entry_exts, size_t *entry_exts_len, + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len, + const uint8_t **in, size_t *inlen); +int x509_revoked_cert_to_der_ex( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); +int x509_revoked_cert_from_der_ex( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, const uint8_t **in, size_t *inlen); int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); +int x509_cert_revoke_to_der(const uint8_t *cert, size_t certlen, + time_t revoke_date, int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen); + /* RevokedCertificates ::= SEQUENCE OF RevokedCertificate */ -int x509_revoked_certs_add_revoked_cert(uint8_t *d, size_t *dlen, size_t maxlen, - const uint8_t *serial, size_t serial_len, - time_t revoke_date, - const uint8_t *entry_exts, size_t entry_exts_len); -int x509_revoked_certs_get_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, - const uint8_t *serial, size_t serial_len, - time_t *revoke_date, - const uint8_t **entry_exts, size_t *entry_exts_len); -#define x509_revoked_certs_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen) -#define x509_revoked_certs_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen) +int x509_revoked_certs_find_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, + const uint8_t *serial, size_t serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len); int x509_revoked_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); /* CRL Extensions: - OID_ce_authority_key_identifier SEQUENCE AuthorityKeyIdentifier - OID_ce_issuer_alt_name SEQUENCE GeneralNames - OID_ce_crl_number INTEGER - OID_ce_delta_crl_indicator INTEGER - OID_ce_issuing_distribution_point SEQUENCE IssuingDistributionPoint + OID_ce_authority_key_identifier AuthorityKeyIdentifier critical or non-critical + OID_ce_issuer_alt_name GeneralNames SHOULD non-critical + OID_ce_crl_number INTEGER MUST non-critical + OID_ce_delta_crl_indicator INTEGER MUST critical + OID_ce_issuing_distribution_point IssuingDistributionPoint critical + OID_ce_freshest_crl CRLDistributionPoints MUST non-critical + OID_pe_authority_info_access AccessDescriptions MUST non-critical */ const char *x509_crl_ext_id_name(int oid); int x509_crl_ext_id_from_name(const char *name); int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen); int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen); - +int x509_crl_ext_id_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, const uint8_t **in, size_t *inlen); /* IssuingDistributionPoint ::= SEQUENCE { @@ -132,7 +142,7 @@ IssuingDistributionPoint ::= SEQUENCE { */ int x509_issuing_distribution_point_to_der( - int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len, + const char *dist_point_uri, size_t dist_point_uri_len, int only_contains_user_certs, int only_contains_ca_certs, int only_some_reasons, @@ -147,6 +157,15 @@ int x509_issuing_distribution_point_from_der( int *indirect_crl, int *only_contains_attr_certs, const uint8_t **in, size_t *inlen); +int x509_issuing_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_ext_critical_validate(int oid, int critical); +int x509_crl_ext_to_der(int oid, int critical, const uint8_t *val, size_t vlen, uint8_t **out, size_t *outlen); +int x509_crl_ext_from_der_ex(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 x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + int x509_crl_exts_add_authority_key_identifier( uint8_t *exts, size_t *extslen, size_t maxlen, @@ -158,6 +177,9 @@ int x509_crl_exts_add_issuer_alt_name( uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const uint8_t *d, size_t dlen); +int x509_crl_exts_add_crl_number_ex( + uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, int num); int x509_crl_exts_add_crl_number( uint8_t *exts, size_t *extslen, size_t maxlen, int critical, @@ -169,13 +191,22 @@ int x509_crl_exts_add_delta_crl_indicator( int x509_crl_exts_add_issuing_distribution_point( uint8_t *exts, size_t *extslen, size_t maxlen, int critical, - const uint8_t *dist_point, size_t dist_point_len, + const char *dist_point_uri, size_t dist_point_uri_len, int only_contains_user_certs, int only_contains_ca_certs, int only_some_reasons, int indirect_crl, int only_contains_attr_certs); +int x509_crl_exts_add_freshest_crl( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *http_uri, size_t http_urilen, + const char *ldap_uri, size_t ldap_urilen); +int x509_crl_exts_add_authority_info_acess( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, + const char *ocsp_uri, size_t ocsp_urilen); +int x509_crl_exts_validate(const uint8_t *d, size_t dlen); #define x509_crl_exts_to_der(d,dlen,out,outlen) x509_explicit_exts_to_der(0,d,dlen,out,outlen) #define x509_crl_exts_from_der(d,dlen,in,inlen) x509_explicit_exts_from_der(0,d,dlen,in,inlen) int x509_crl_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); @@ -217,12 +248,8 @@ CertificateList ::= SEQUENCE { signatureAlgorithm AlgorithmIdentifier, signatureValue BIT STRING } */ -int x509_cert_list_to_der(const uint8_t *tbs_crl, size_t tbs_crl_len, - int signature_algor, const uint8_t *sig, size_t siglen, - uint8_t **out, size_t *outlen); -int x509_cert_list_from_der(const uint8_t **tbs_crl, size_t *tbs_crl_len, - int *signature_algor, const uint8_t **sig, size_t *siglen, - const uint8_t **in, size_t *inlen); +#define x509_cert_list_to_der(tbs,tbslen,sig_alg,sig,siglen,out,outlen) x509_signed_to_der(tbs,tbslen,sig_alg,sig,siglen,out,outlen) +#define x509_cert_list_from_der(tbs,tbslen,sig_alg,sig,siglen,in,inlen) x509_signed_from_der(tbs,tbslen,sig_alg,sig,siglen,in,inlen) int x509_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); // x509_crl_ functions @@ -230,28 +257,34 @@ int x509_crl_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen int x509_crl_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen); int x509_crl_to_pem(const uint8_t *a, size_t alen, FILE *fp); int x509_crl_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp); -int x509_crl_to_fp(const uint8_t *a, size_t alen, FILE *fp); // 去掉这个函数 -int x509_crl_from_fp(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp); // 去掉这个函数 - - int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); -int x509_crl_sign(uint8_t *crl, size_t *crl_len, - int version, - int signature_algor, + +int x509_crl_sign_to_der( + int version, int sig_alg, const uint8_t *issuer, size_t issuer_len, - time_t this_update, - time_t next_update, + 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 SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len); + const uint8_t *crl_exts, size_t crl_exts_len, + const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, + uint8_t **out, size_t *outlen); +int x509_crl_from_der_ex( + int *version, + int *inner_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, + int *sig_alg, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen); +int x509_crl_validate(const uint8_t *a, size_t alen, time_t now, const uint8_t *ca_subject, size_t ca_subject_len); int x509_crl_verify(const uint8_t *a, size_t alen, const SM2_KEY *sign_pub_key, const char *signer_id, size_t signer_id_len); int x509_crl_verify_by_ca_cert(const uint8_t *a, size_t alen, const uint8_t *cacert, size_t cacertlen, const char *signer_id, size_t signer_id_len); - int x509_crl_get_details(const uint8_t *crl, size_t crl_len, int *version, + int *inner_sig_alg, const uint8_t **issuer, size_t *issuer_len, time_t *this_update, time_t *next_update, @@ -261,15 +294,17 @@ int x509_crl_get_details(const uint8_t *crl, size_t crl_len, const uint8_t **sig, size_t *siglen); int x509_crl_get_issuer(const uint8_t *crl, size_t crl_len, const uint8_t **issuer, size_t *issuer_len); - +int x509_crl_get_revoked_certs(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen); int x509_crl_find_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, const uint8_t *serial, size_t serial_len, time_t *revoke_date, const uint8_t **entry_exts, size_t *entry_exts_len); - - - int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + +int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen); + + + #ifdef __cplusplus } #endif diff --git a/include/gmssl/x509_ext.h b/include/gmssl/x509_ext.h index db8a4c27..3036b5dc 100644 --- a/include/gmssl/x509_ext.h +++ b/include/gmssl/x509_ext.h @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -24,6 +24,12 @@ extern "C" { #endif + +enum { + X509_non_critical = 0, + X509_critical = 1, +}; + /* Extensions: @@ -64,6 +70,8 @@ int x509_exts_add_policy_constraints(uint8_t *exts, size_t *extslen, size_t maxl int require_explicit_policy, int inhibit_policy_mapping); int x509_exts_add_basic_constraints(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int ca, int path_len_constraint); int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const int *key_purposes, size_t key_purposes_cnt); +int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int oid, + const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen); int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen); int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int skip_certs); @@ -471,6 +479,7 @@ DistributionPointName ::= CHOICE { nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } -- SET OF */ int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen, uint8_t **out, size_t *outlen); +#define x509_uri_as_general_names_to_der(uri,urilen,out,outlen) x509_uri_as_general_names_to_der_ex(ASN1_TAG_SEQUENCE,uri,urilen,out,outlen) int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen); int x509_uri_as_explicit_distribution_point_name_to_der(int index, const char *uri, size_t urilen, uint8_t **out, size_t *outlen); diff --git a/src/file.c b/src/file.c index 1e86bec4..f9afcd71 100644 --- a/src/file.c +++ b/src/file.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -33,3 +33,31 @@ int file_size(FILE *fp, size_t *size) *size = st.st_size; return 1; } + +int file_read_all(const char *file, uint8_t **out, size_t *outlen) +{ + int ret = -1; + FILE *fp = NULL; + size_t fsize; + uint8_t *buf = NULL; + + if (!(fp = fopen(file, "r")) + || file_size(fp, &fsize) != 1 + || (buf = malloc(fsize)) == NULL) { + error_print(); + goto end; + } + if (fread(buf, 1, fsize, fp) != fsize) { + error_print(); + goto end; + } + *out = buf; + *outlen = fsize; + buf = NULL; + ret = 1; +end: + if (fp) fclose(fp); + if (buf) free(buf); + return ret; +} + diff --git a/src/http.c b/src/http.c index 8342fe98..9a8922bb 100644 --- a/src/http.c +++ b/src/http.c @@ -1,5 +1,4 @@ - -/* +/* * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may @@ -65,7 +64,7 @@ static int socket_recv_all(int sock, uint8_t *buf, size_t len) return 1; } -int http_parse_response(uint8_t *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left) +int http_parse_response(char *buf, size_t buflen, uint8_t **content, size_t *contentlen, size_t *left) { char *ok = "HTTP/1.1 200 OK\r\n"; char *p; @@ -75,14 +74,14 @@ int http_parse_response(uint8_t *buf, size_t buflen, uint8_t **content, size_t * error_print(); return -1; } - if (!(p = strnstr((char *)buf, "\r\n\r\n", buflen))) { + if (!(p = strnstr(buf, "\r\n\r\n", buflen))) { error_print(); return -1; } *content = (uint8_t *)(p + 4); - headerlen = *content - buf; + headerlen = *content - (uint8_t *)buf; - if (!(p = strnstr((char *)buf, "\r\nContent-Length: ", headerlen))) { + if (!(p = strnstr(buf, "\r\nContent-Length: ", headerlen))) { error_print(); return -1; } @@ -104,10 +103,9 @@ int http_parse_response(uint8_t *buf, size_t buflen, uint8_t **content, size_t * #define HTTP_GET_TEMPLATE "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "\r\n\r\n" -int http_get(const char *uri, uint8_t *buf, size_t buflen, - uint8_t **content, size_t *contentlen) +int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen) { - char *uribuf = NULL; + int ret = -1; char host[128]; int port; char path[256]; @@ -116,16 +114,22 @@ int http_get(const char *uri, uint8_t *buf, size_t buflen, tls_socket_t sock; char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)]; int getlen; + char response[512]; + uint8_t *p; size_t len; size_t left; - // parse uri + // parse uri and compose request if (http_parse_uri(uri, host, &port, path) != 1) { error_print(); return -1; } + if ((getlen = snprintf(get, sizeof(get), HTTP_GET_TEMPLATE, path, host)) <= 0) { + error_print(); + return -1; + } - // connect + // connect and send request if (!(hp = gethostbyname(host))) { error_print(); return -1; @@ -140,42 +144,36 @@ int http_get(const char *uri, uint8_t *buf, size_t buflen, } if (connect(sock, (struct sockaddr *)&server , sizeof(server)) < 0) { error_print(); - return -1; - } - - // request - if ((getlen = snprintf(get, sizeof(get), - "GET %s HTTP/1.1\r\n" - "Host: %s\r\n" - "\r\n\r\n", path, host)) <= 0) { - error_print(); - return -1; + goto end; } if (send(sock, get, strlen(get), 0) != getlen) { error_print(); - return -1; + goto end; + } + if ((len = recv(sock, response, sizeof(response), 0)) <= 0) { + error_print(); + goto end; } - // response - if ((len = recv(sock, buf, buflen, 0)) <= 0) { + // process response header and retrieve left + if (http_parse_response(response, len, &p, contentlen, &left) != 1) { error_print(); - return -1; + goto end; } - if (http_parse_response(buf, len, content, contentlen, &left) != 1) { - error_print(); - return -1; + if (!buf || buflen < *contentlen) { + ret = 0; + goto end; } + memcpy(buf, p, *contentlen - left); if (left) { - if (len + left > buflen) { - error_print(); // buf is not enough - return -1; - } - if (socket_recv_all(sock, buf + len, left) != 1) { + if (socket_recv_all(sock, buf + *contentlen - left, left) != 1) { error_print(); - return -1; + goto end; } } + ret = 1; - return 1; +end: + close(sock); + return ret; } - diff --git a/src/sm2_lib.c b/src/sm2_lib.c index f5fcb14c..e198ca13 100644 --- a/src/sm2_lib.c +++ b/src/sm2_lib.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -382,6 +382,23 @@ int sm2_sign_finish(SM2_SIGN_CTX *ctx, uint8_t *sig, size_t *siglen) return 1; } +int sm2_sign_finish_fixlen(SM2_SIGN_CTX *ctx, size_t siglen, uint8_t *sig) +{ + int ret; + uint8_t dgst[SM3_DIGEST_SIZE]; + + if (!ctx || !sig || !siglen) { + error_print(); + return -1; + } + sm3_finish(&ctx->sm3_ctx, dgst); + if ((ret = sm2_sign_fixlen(&ctx->key, dgst, siglen, sig)) != 1) { + if (ret < 0) error_print(); + return ret; + } + return 1; +} + int sm2_verify_init(SM2_SIGN_CTX *ctx, const SM2_KEY *key, const char *id, size_t idlen) { if (!ctx || !key) { diff --git a/src/x509_cer.c b/src/x509_cer.c index bd8e4924..d0738e32 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -729,7 +729,7 @@ int x509_ext_from_der(int *oid, uint32_t *nodes, size_t *nodes_cnt, if (ret < 0) error_print(); return ret; } - *critical = 0; + *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 @@ -1041,6 +1041,48 @@ int x509_certificate_to_der( 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, @@ -1571,6 +1613,8 @@ int x509_certs_get_cert_by_issuer_and_serial_number( return 0; } +// 这里面需要validate的类型是两种,一种直接得到了实际值,因此可以直接对实际值做验证 +// 另一种是SEQUENCE OF类型,本质上是完整的a,alen,因此这种类型实际上可以用from_der来解析 int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraints) { diff --git a/src/x509_crl.c b/src/x509_crl.c index 431607de..e0cdac68 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -18,8 +18,11 @@ #include #include #include +#include +#include #include + static const char *x509_crl_reason_names[] = { "unspecified", "keyCompromise", @@ -60,21 +63,46 @@ int x509_crl_reason_from_name(int *reason, const char *name) int x509_crl_reason_to_der(int reason, uint8_t **out, size_t *outlen) { - if (reason >= 0 && !x509_crl_reason_name(reason)) { + if (reason == -1) { + return 0; + } + if (!x509_crl_reason_name(reason)) { error_print(); return -1; } - return asn1_enumerated_to_der(reason, out, outlen); + if (asn1_enumerated_to_der(reason, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; } int x509_crl_reason_from_der(int *reason, const uint8_t **in, size_t *inlen) { - return asn1_enumerated_from_der(reason, in, inlen); + int ret; + if ((ret = asn1_enumerated_from_der(reason, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_reason_name(*reason) == NULL) { + error_print(); + return -1; + } + return 1; } int x509_implicit_crl_reason_from_der(int index, int *reason, const uint8_t **in, size_t *inlen) { - return asn1_implicit_enumerated_from_der(index, reason, in, inlen); + int ret; + if ((ret = asn1_implicit_enumerated_from_der(index, reason, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (!x509_crl_reason_name(*reason)) { + error_print(); + return -1; + } + return 1; } @@ -83,9 +111,9 @@ static uint32_t oid_ce_invalidity_date[] = { oid_ce,24 }; static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; static const ASN1_OID_INFO x509_crl_entry_exts[] = { - { OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, sizeof(oid_ce_crl_reasons)/sizeof(int) }, - { OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, sizeof(oid_ce_invalidity_date)/sizeof(int) }, - { OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, sizeof(oid_ce_certificate_issuer)/sizeof(int) }, + { OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, oid_cnt(oid_ce_crl_reasons) }, + { OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, oid_cnt(oid_ce_invalidity_date) }, + { OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, oid_cnt(oid_ce_certificate_issuer) }, }; static const int x509_crl_entry_exts_count = @@ -139,51 +167,152 @@ int x509_crl_entry_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) return 1; } -int x509_crl_entry_exts_add_reason(uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, int reason) +int x509_crl_entry_ext_critical_validate(int oid, int critical) +{ + switch (oid) { + case OID_ce_crl_reasons: + case OID_ce_invalidity_date: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_issuer: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; +} + +int x509_crl_reason_ext_to_der(int critical, int reason, uint8_t **out, size_t *outlen) { int oid = OID_ce_crl_reasons; - size_t curlen = *extslen; - uint8_t val[16]; + uint8_t val[3]; uint8_t *p = val; size_t vlen = 0; - exts += *extslen; + if (reason < 0) { + return 0; + } if (x509_crl_reason_to_der(reason, &p, &vlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 - || asn1_length_le(curlen, maxlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + || asn1_length_le(vlen, sizeof(val)) != 1 + || x509_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { error_print(); return -1; } return 1; } -int x509_crl_entry_exts_add_invalidity_date(uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, time_t tv) +int x509_invalidity_date_ext_to_der(int critical, time_t date, uint8_t **out, size_t *outlen) { int oid = OID_ce_invalidity_date; - size_t curlen = *extslen; - uint8_t val[16]; + uint8_t val[ASN1_GENERALIZED_TIME_MAX_SIZE]; uint8_t *p = val; size_t vlen = 0; - exts += *extslen; - if (asn1_generalized_time_to_der(tv, &p, &vlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 - || asn1_length_le(curlen, maxlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + if (date < 0) { + return 0; + } + if (asn1_generalized_time_to_der(date, &p, &vlen) != 1 + || asn1_length_le(vlen, sizeof(val)) != 1 + || x509_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { error_print(); return -1; } return 1; } -int x509_crl_entry_exts_add_certificate_issuer(uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, const uint8_t *d, size_t dlen) +int x509_cert_issuer_ext_to_der(int critical, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) { int oid = OID_ce_certificate_issuer; - return x509_exts_add_sequence(exts, extslen, maxlen, oid, critical, d, dlen); + uint8_t val[256]; + uint8_t *p = val; + size_t vlen = 0; + + if (!d) { + return 0; + } + if (asn1_sequence_to_der(d, dlen, NULL, &vlen) != 1 + || asn1_length_le(vlen, sizeof(val)) != 1) { + error_print(); + return -1; + } + vlen = 0; + if (asn1_sequence_to_der(d, dlen, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_ext_from_der(int *oid, int *critical, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *val; + size_t vlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_crl_entry_ext_id_from_der(oid, &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; + } + switch (*oid) { + case OID_ce_crl_reasons: + if (*reason != -1) { + error_print(); + return -1; + } + if (x509_crl_reason_from_der(reason, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_invalidity_date: + if (*invalid_date != -1) { + error_print(); + return -1; + } + if (asn1_generalized_time_from_der(invalid_date, &val, &vlen) != 1) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_issuer: + if (*cert_issuer != NULL) { + error_print(); + return -1; + } + if (asn1_sequence_from_der(cert_issuer, cert_issuer_len, &val, &vlen) != 1) { + error_print(); + return -1; + } + if (!cert_issuer) { + error_print(); + return -1; + } + break; + default: + error_print(); + return -1; + } + return 1; } int x509_crl_entry_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -235,6 +364,100 @@ err: return 1; } +int x509_crl_entry_exts_to_der( + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 0; + if (reason == -1 && invalid_date == -1 && !cert_issuer) { + return 0; + } + if (x509_crl_reason_ext_to_der(-1, reason, NULL, &len) < 0 + || x509_invalidity_date_ext_to_der(-1, invalid_date, NULL, &len) < 0 + || x509_cert_issuer_ext_to_der(X509_critical, cert_issuer, cert_issuer_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_crl_reason_ext_to_der(-1, reason, out, outlen) < 0 + || x509_invalidity_date_ext_to_der(-1, invalid_date, out, outlen) < 0 + || x509_cert_issuer_ext_to_der(X509_critical, cert_issuer, cert_issuer_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_get(const uint8_t *d, size_t dlen, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len) +{ + int oid; + int critical; + *reason = -1; + *invalid_date = -1; + *cert_issuer = NULL; + *cert_issuer_len = 0; + + while (dlen) { + if (x509_crl_entry_ext_from_der(&oid, &critical, reason, invalid_date, cert_issuer, cert_issuer_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_ext_critical_validate(oid, critical) != 1) { + error_print(); + return -1; + } + } + return 1; +} + +int x509_crl_entry_exts_from_der( + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret = 0; + 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 (!d || !dlen) { + error_print(); + return -1; + } + if (x509_crl_entry_exts_get(d, dlen, reason, invalid_date, cert_issuer, cert_issuer_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_entry_exts_validate(const uint8_t *d, size_t dlen) +{ + int oid; + int critical; + int reason = -1; + time_t invalid_date = -1; + const uint8_t *cert_issuer = NULL; + size_t cert_issuer_len = 0; + + while (dlen) { + if (x509_crl_entry_ext_from_der(&oid, &critical, + &reason, &invalid_date, &cert_issuer, &cert_issuer_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_ext_critical_validate(oid, critical) != 1) { + error_print(); + return -1; + } + if (cert_issuer) { + error_print(); + //return -1; // currently cert_issuer can not be processed + } + } + return 1; +} + int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; @@ -254,19 +477,37 @@ int x509_crl_entry_exts_print(FILE *fp, int fmt, int ind, const char *label, con } int x509_revoked_cert_to_der( - const uint8_t *serial, size_t serial_len, - time_t revoke_date, - const uint8_t *entry_exts, size_t entry_exts_len, + const uint8_t *serial, size_t serial_len, time_t revoke_date, + const uint8_t *crl_entry_exts, size_t crl_entry_exts_len, uint8_t **out, size_t *outlen) { size_t len = 0; if (asn1_integer_to_der(serial, serial_len, NULL, &len) != 1 - || x509_time_to_der(revoke_date, NULL, &len) != 1 - || asn1_sequence_to_der(entry_exts, entry_exts_len, NULL, &len) < 0 + || asn1_generalized_time_to_der(revoke_date, NULL, &len) != 1 + || asn1_sequence_to_der(crl_entry_exts, crl_entry_exts_len, NULL, &len) < 0 || asn1_sequence_header_to_der(len, out, outlen) != 1 || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 - || x509_time_to_der(revoke_date, out, outlen) != 1 - || asn1_sequence_to_der(entry_exts, entry_exts_len, out, outlen) < 0) { + || asn1_generalized_time_to_der(revoke_date, out, outlen) != 1 + || asn1_sequence_to_der(crl_entry_exts, crl_entry_exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +int x509_revoked_cert_to_der_ex( + const uint8_t *serial, size_t serial_len, time_t revoke_date, + int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) +{ + size_t len = 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 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_integer_to_der(serial, serial_len, out, outlen) != 1 + || asn1_generalized_time_to_der(revoke_date, out, outlen) != 1 + || x509_crl_entry_exts_to_der(reason, invalid_date, cert_issuer, cert_issuer_len, out, outlen) < 0) { error_print(); return -1; } @@ -274,9 +515,8 @@ int x509_revoked_cert_to_der( } int x509_revoked_cert_from_der( - const uint8_t **serial, size_t *serial_len, - time_t *revoke_date, - const uint8_t **entry_exts, size_t *entry_exts_len, + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len, const uint8_t **in, size_t *inlen) { int ret; @@ -289,7 +529,7 @@ int x509_revoked_cert_from_der( } if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 || x509_time_from_der(revoke_date, &d, &dlen) != 1 - || asn1_sequence_from_der(entry_exts, entry_exts_len, &d, &dlen) < 0 + || asn1_sequence_from_der(crl_entry_exts, crl_entry_exts_len, &d, &dlen) != 1 || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; @@ -297,6 +537,36 @@ int x509_revoked_cert_from_der( return 1; } +int x509_revoked_cert_from_der_ex( + const uint8_t **serial, size_t *serial_len, time_t *revoke_date, + int *reason, time_t *invalid_date, const uint8_t **cert_issuer, size_t *cert_issuer_len, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *d; + size_t dlen; + const uint8_t *crl_entry_exts; + size_t crl_entry_exts_len; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_integer_from_der(serial, serial_len, &d, &dlen) != 1 + || x509_time_from_der(revoke_date, &d, &dlen) != 1 + || asn1_sequence_from_der(&crl_entry_exts, &crl_entry_exts_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_entry_exts_get(crl_entry_exts, crl_entry_exts_len, + reason, invalid_date, cert_issuer, cert_issuer_len) != 1) { + error_print(); + return -1; + } + return 1; +} + int x509_revoked_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int ret; @@ -320,22 +590,43 @@ err: return -1; } -int x509_revoked_certs_add_revoked_cert(uint8_t *d, size_t *dlen, size_t maxlen, - const uint8_t *serial, size_t serial_len, - time_t revoke_date, - const uint8_t *entry_exts, size_t entry_exts_len) +int x509_cert_revoke_to_der(const uint8_t *cert, size_t certlen, + time_t revoke_date, int reason, time_t invalid_date, const uint8_t *cert_issuer, size_t cert_issuer_len, + uint8_t **out, size_t *outlen) { - error_print(); - return -1; + const uint8_t *serial; + size_t serial_len; + + if (x509_cert_get_issuer_and_serial_number(cert, certlen, NULL, 0, &serial, &serial_len) != 1 + || x509_revoked_cert_to_der_ex(serial, serial_len, revoke_date, + reason, invalid_date, cert_issuer, cert_issuer_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; } -int x509_revoked_certs_get_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, +int x509_revoked_certs_find_revoked_cert_by_serial_number(const uint8_t *d, size_t dlen, const uint8_t *serial, size_t serial_len, - time_t *revoke_date, - const uint8_t **entry_exts, size_t *entry_exts_len) + time_t *revoke_date, const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len) { - error_print(); - return -1; + const uint8_t *sn; + size_t sn_len; + + while (dlen) { + if (x509_revoked_cert_from_der(&sn, &sn_len, revoke_date, + crl_entry_exts, crl_entry_exts_len, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (sn_len == serial_len && memcmp(sn, serial, serial_len) == 0) { + return 1; + } + } + *revoke_date = -1; + *crl_entry_exts = NULL; + *crl_entry_exts_len = 0; + return 0; } int x509_revoked_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -357,6 +648,7 @@ int x509_revoked_certs_print(FILE *fp, int fmt, int ind, const char *label, cons } +// CRL Extensions static uint32_t oid_ce_authority_key_identifier[] = { oid_ce,35 }; static uint32_t oid_ce_issuer_alt_name[] = { oid_ce,18 }; static uint32_t oid_ce_crl_number[] = { oid_ce,20 }; @@ -365,15 +657,14 @@ static uint32_t oid_ce_issuing_distribution_point[] = { oid_ce,28 }; static uint32_t oid_ce_freshest_crl[] = { oid_ce,46 }; static uint32_t oid_pe_authority_info_access[] = { oid_pe,1 }; - static const ASN1_OID_INFO x509_crl_exts[] = { - { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, sizeof(oid_ce_authority_key_identifier)/sizeof(int) }, - { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, sizeof(oid_ce_issuer_alt_name)/sizeof(int) }, - { OID_ce_crl_number, "CRLNumber", oid_ce_crl_number, sizeof(oid_ce_crl_number)/sizeof(int) }, - { OID_ce_delta_crl_indicator, "DeltaCRLIndicator", oid_ce_delta_crl_indicator, sizeof(oid_ce_delta_crl_indicator)/sizeof(int) }, - { OID_ce_issuing_distribution_point, "IssuingDistributionPoint", oid_ce_issuing_distribution_point, sizeof(oid_ce_issuing_distribution_point)/sizeof(int) }, - { OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, sizeof(oid_ce_freshest_crl)/sizeof(int) }, - { OID_pe_authority_info_access, "AuthorityInfoAccess", oid_pe_authority_info_access, sizeof(oid_pe_authority_info_access)/sizeof(int) }, + { OID_ce_authority_key_identifier, "AuthorityKeyIdentifier", oid_ce_authority_key_identifier, oid_cnt(oid_ce_authority_key_identifier) }, + { OID_ce_issuer_alt_name, "IssuerAltName", oid_ce_issuer_alt_name, oid_cnt(oid_ce_issuer_alt_name) }, + { OID_ce_crl_number, "CRLNumber", oid_ce_crl_number, oid_cnt(oid_ce_crl_number) }, + { OID_ce_delta_crl_indicator, "DeltaCRLIndicator", oid_ce_delta_crl_indicator, oid_cnt(oid_ce_delta_crl_indicator) }, + { OID_ce_issuing_distribution_point, "IssuingDistributionPoint", oid_ce_issuing_distribution_point, oid_cnt(oid_ce_issuing_distribution_point) }, + { OID_ce_freshest_crl, "FreshestCRL", oid_ce_freshest_crl, oid_cnt(oid_ce_freshest_crl) }, + { OID_pe_authority_info_access, "AuthorityInfoAccess", oid_pe_authority_info_access, oid_cnt(oid_pe_authority_info_access) }, }; static const int x509_crl_exts_count = @@ -402,12 +693,7 @@ int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen) { const ASN1_OID_INFO *info; size_t len = 0; - if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) { - error_print(); - return -1; - } - if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, NULL, &len) != 1 - || asn1_sequence_header_to_der(len, out, outlen) != 1 + if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid)) || asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) { error_print(); return -1; @@ -422,8 +708,8 @@ int x509_crl_ext_id_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, co *oid = 0; if ((ret = asn1_oid_info_from_der_ex(&info, nodes, nodes_cnt, x509_crl_exts, x509_crl_exts_count, in, inlen)) != 1) { - error_print(); - return -1; + if (ret < 0) error_print(); + return ret; } if (info) { *oid = info->oid; @@ -431,93 +717,25 @@ int x509_crl_ext_id_from_der_ex(int *oid, uint32_t *nodes, size_t *nodes_cnt, co return ret; } -int x509_crl_exts_add_authority_key_identifier( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - const uint8_t *keyid, size_t keyid_len, - const uint8_t *issuer, size_t issuer_len, - const uint8_t *serial, size_t serial_len) +int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen) { - if (x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, - keyid, keyid_len, issuer, issuer_len, serial, serial_len) != 1) { + int ret; + uint32_t nodes[32]; + size_t nodes_cnt; + + if ((ret = x509_crl_ext_id_from_der_ex(oid, nodes, &nodes_cnt, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (*oid == OID_undef) { error_print(); return -1; } return 1; } -int x509_crl_exts_add_issuer_alt_name( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - const uint8_t *d, size_t dlen) -{ - if (x509_exts_add_issuer_alt_name(exts, extslen, maxlen, critical, d, dlen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_crl_exts_add_crl_number( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - int num) -{ - int oid = OID_ce_crl_number; - size_t curlen = *extslen; - uint8_t val[32]; - uint8_t *p = val; - size_t vlen = 0; - - exts += *extslen; - if (asn1_int_to_der(num, &p, &vlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 - || asn1_length_le(curlen, maxlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_crl_exts_add_delta_crl_indicator( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - int num) -{ - int oid = OID_ce_delta_crl_indicator; - size_t curlen = *extslen; - uint8_t val[32]; - uint8_t *p = val; - size_t vlen = 0; - - exts += *extslen; - if (asn1_int_to_der(num, &p, &vlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 - || asn1_length_le(curlen, maxlen) != 1 - || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { - error_print(); - return -1; - } - return 1; -} - -int x509_crl_exts_add_issuing_distribution_point( - uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, - const uint8_t *dist_point, size_t dist_point_len, - int only_contains_user_certs, - int only_contains_ca_certs, - int only_some_reasons, - int indirect_crl, - int only_contains_attr_certs) -{ - error_print(); - return -1; -} - int x509_issuing_distribution_point_to_der( - int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len, + const char *dist_point_uri, size_t dist_point_uri_len, int only_contains_user_certs, int only_contains_ca_certs, int only_some_reasons, @@ -525,25 +743,23 @@ int x509_issuing_distribution_point_to_der( int only_contains_attr_certs, uint8_t **out, size_t *outlen) { - /* size_t len = 0; - if (x509_explicit_distribution_point_name_to_der(0, dist_point_choice, dist_point, dist_point_len, NULL, &len) < 0 + 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 - || asn1_implicit_bits_to_der(3, only_some_reasons, NULL, &len) < 0 // 是否有特化的类型 + || asn1_implicit_bits_to_der(3, only_some_reasons, NULL, &len) < 0 // TODO: 特化的类型 || asn1_implicit_boolean_to_der(4, indirect_crl, NULL, &len) < 0 || asn1_implicit_boolean_to_der(5, only_contains_attr_certs, NULL, &len) < 0 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || x509_explicit_distribution_point_name_to_der(0, dist_point_choice, dist_point, dist_point_len, out, outlen) < 0 + || x509_uri_as_explicit_distribution_point_name_to_der(0, dist_point_uri, dist_point_uri_len, out, outlen) < 0 || asn1_implicit_boolean_to_der(1, only_contains_user_certs, out, outlen) < 0 || asn1_implicit_boolean_to_der(2, only_contains_ca_certs, out, outlen) < 0 - || asn1_implicit_bits_to_der(3, only_some_reasons, out, outlen) < 0 // 是否有特化的类型 + || asn1_implicit_bits_to_der(3, only_some_reasons, out, outlen) < 0 // TODO: 特化的类型 || asn1_implicit_boolean_to_der(4, indirect_crl, out, outlen) < 0 || asn1_implicit_boolean_to_der(5, only_contains_attr_certs, out, outlen) < 0) { error_print(); return -1; } - */ return 1; } @@ -556,7 +772,6 @@ int x509_issuing_distribution_point_from_der( int *only_contains_attr_certs, const uint8_t **in, size_t *inlen) { - /* int ret; const uint8_t *d; size_t dlen; @@ -565,6 +780,7 @@ int x509_issuing_distribution_point_from_der( if (ret < 0) error_print(); return ret; } + /* if (x509_explicit_distribution_point_name_from_der(0, dist_point_choice, dist_point, dist_point_len, &d, &dlen) < 0 || asn1_implicit_boolean_from_der(1, only_contains_user_certs, &d, &dlen) < 0 || asn1_implicit_boolean_from_der(2, only_contains_ca_certs, &d, &dlen) < 0 @@ -611,10 +827,77 @@ end: return -1; } -int x509_access_descriptions_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +int x509_crl_ext_critical_validate(int oid, int critical) { - error_print(); - return -1; + switch (oid) { + // MUST be critical + case OID_ce_delta_crl_indicator: + case OID_ce_issuing_distribution_point: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + // critical or non-critical + case OID_ce_authority_key_identifier: + break; + // SHOULD be non-critical + case OID_ce_issuer_alt_name: + if (critical == X509_critical) { + error_print(); + return 0; + } + break; + // MUST be non-critical + case OID_ce_crl_number: + case OID_ce_freshest_crl: + case OID_pe_authority_info_access: + default: + if (critical == X509_critical) { + error_print(); + return -1; + } + } + return 1; +} + +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 (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 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || x509_crl_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_crl_ext_from_der_ex(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_crl_ext_id_from_der_ex(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_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -672,7 +955,7 @@ int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint case OID_ce_delta_crl_indicator: format_print(fp, fmt, ind, "%s: %d\n", name, num); break; case OID_ce_issuing_distribution_point: x509_issuing_distribution_point_print(fp, fmt, ind, name, p, len); break; case OID_ce_freshest_crl: x509_crl_distribution_points_print(fp, fmt, ind, name, p, len); break; - case OID_pe_authority_info_access: x509_access_descriptions_print(fp, fmt, ind, name, p, len); break; + case OID_pe_authority_info_access: x509_authority_info_access_print(fp, fmt, ind, name, p, len); break; default: format_bytes(fp, fmt, ind, "value", p, len); } if (asn1_length_is_zero(vlen) != 1) goto err; @@ -682,6 +965,174 @@ err: return -1; } +int x509_crl_exts_add_authority_key_identifier( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + 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 (!keyid || !keyid_len) { + error_print(); + return -1; + } + if (x509_exts_add_authority_key_identifier(exts, extslen, maxlen, critical, + keyid, keyid_len, issuer, issuer_len, serial, serial_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_issuer_alt_name( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const uint8_t *d, size_t dlen) +{ + if (x509_exts_add_issuer_alt_name(exts, extslen, maxlen, critical, d, dlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_crl_number_ex( + uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, int num) +{ + size_t curlen = *extslen; + uint8_t val[32]; + uint8_t *p = val; + size_t vlen = 0; + + exts += *extslen; + if (asn1_int_to_der(num, &p, &vlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_ext_to_der(oid, critical, val, vlen, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_crl_number( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, int num) +{ + int oid = OID_ce_crl_number; + if (x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_delta_crl_indicator( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + int num) +{ + int oid = OID_ce_delta_crl_indicator; + if (x509_crl_exts_add_crl_number_ex(exts, extslen, maxlen, oid, critical, num) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_issuing_distribution_point( + uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, + const char *dist_point_uri, size_t dist_point_uri_len, + int only_contains_user_certs, + int only_contains_ca_certs, + int only_some_reasons, + int indirect_crl, + int only_contains_attr_certs) +{ + int oid = OID_ce_issuing_distribution_point; + size_t curlen = *extslen; + uint8_t val[512]; + uint8_t *p = val; + size_t vlen = 0; + + exts += *extslen; + if (x509_issuing_distribution_point_to_der( + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, NULL, &curlen) != 1 + || asn1_length_le(curlen, maxlen) != 1 + || x509_issuing_distribution_point_to_der( + dist_point_uri, dist_point_uri_len, + only_contains_user_certs, + only_contains_ca_certs, + only_some_reasons, + indirect_crl, + only_contains_attr_certs, &exts, extslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_freshest_crl( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) +{ + int oid = OID_ce_freshest_crl; + if (x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, + oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_add_authority_info_acess( + uint8_t *exts, size_t *extslen, size_t maxlen, int critical, + const char *ca_issuers_uri, size_t ca_issuers_urilen, const char *ocsp_uri, size_t ocsp_urilen) +{ + if (x509_exts_add_authority_info_access(exts, extslen, maxlen, critical, + ca_issuers_uri, ca_issuers_urilen, ocsp_uri, ocsp_urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_exts_validate(const uint8_t *d, size_t dlen) +{ + int oid; + uint32_t nodes[32]; + size_t nodes_cnt; + int critical; + const uint8_t *val; + size_t vlen; + int tag; + const uint8_t *p; + size_t len; + + while (dlen) { + if (x509_crl_ext_from_der_ex(&oid, nodes, &nodes_cnt, &critical, &val, &vlen, &d, &dlen) != 1) { + error_print(); + return -1; + } + if (x509_crl_ext_critical_validate(oid, critical) != 1) { + error_print(); + return -1; + } + if (critical == X509_critical) { + error_print(); + return -1; + } + } + return 1; +} + int x509_crl_exts_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; @@ -810,46 +1261,6 @@ err: return -1; } -int x509_cert_list_to_der(const uint8_t *tbs_crl, size_t tbs_crl_len, - int signature_algor, const uint8_t *sig, size_t siglen, - uint8_t **out, size_t *outlen) -{ - size_t len = 0; - if (asn1_sequence_to_der(tbs_crl, tbs_crl_len, 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_sequence_to_der(tbs_crl, tbs_crl_len, 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_cert_list_from_der(const uint8_t **tbs_crl, size_t *tbs_crl_len, - 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_sequence_from_der(tbs_crl, tbs_crl_len, &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_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int val; @@ -869,7 +1280,6 @@ err: return -1; } -// FIXME: 这两个函数应该检查CRL格式是否正确 int x509_crl_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen) { int ret; @@ -909,6 +1319,7 @@ int x509_crl_from_pem(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) return 1; } +/* int x509_crl_to_fp(const uint8_t *a, size_t alen, FILE *fp) { if (fwrite(a, 1, alen, fp) != alen) { @@ -945,7 +1356,7 @@ int x509_crl_from_fp(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp) *alen = len; return 1; } - +*/ int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen) { @@ -964,172 +1375,218 @@ int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t return 1; } -int x509_tbs_crl_sign( - int version, - int signature_algor, +int x509_crl_sign_to_der( + 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 *crl_exts, size_t crl_exts_len, const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len, - uint8_t *crl, size_t *crl_len) + uint8_t **out, size_t *outlen) { - uint8_t tbs[512]; - size_t tbslen; - SM2_SIGN_CTX sign_ctx; uint8_t sig[SM2_MAX_SIGNATURE_SIZE]; - size_t siglen; - uint8_t *p = tbs; - size_t len = 0; - uint8_t *out = crl; - size_t outlen = 0; + size_t siglen = SM2_signature_typical_size; + size_t tbs_dlen = 0; + size_t tbs_alen = 0; + uint8_t *tbs_a = sig; + size_t crl_dlen; - if (x509_tbs_crl_to_der(version, signature_algor, issuer, issuer_len, + if (asn1_int_to_der(version, NULL, &tbs_dlen) != 1 + || x509_signature_algor_to_der(sig_alg, NULL, &tbs_dlen) != 1 + || x509_name_to_der(issuer, issuer_len, NULL, &tbs_dlen) != 1 + || x509_time_to_der(this_update, NULL, &tbs_dlen) != 1 + || x509_time_to_der(next_update, NULL, &tbs_dlen) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, NULL, &tbs_dlen) < 0 + || x509_explicit_exts_to_der(0, crl_exts, crl_exts_len, NULL, &tbs_dlen) < 0 + || asn1_sequence_to_der(tbs_a, tbs_dlen, NULL, &tbs_alen) != 1) { + error_print(); + return -1; + } + crl_dlen = tbs_alen; + if (x509_signature_algor_to_der(sig_alg, NULL, &crl_dlen) != 1 + || asn1_bit_octets_to_der(sig, siglen, NULL, &crl_dlen) != 1 + || asn1_sequence_header_to_der(crl_dlen, out, outlen) != 1) { + error_print(); + return -1; + } + if (out && *out) { + tbs_a = *out; + } + if (asn1_sequence_header_to_der(tbs_dlen, out, outlen) != 1 + || asn1_int_to_der(version, out, outlen) != 1 + || x509_signature_algor_to_der(sig_alg, out, outlen) != 1 + || x509_name_to_der(issuer, issuer_len, out, outlen) != 1 + || x509_time_to_der(this_update, out, outlen) != 1 + || x509_time_to_der(next_update, out, outlen) < 0 + || asn1_sequence_to_der(revoked_certs, revoked_certs_len, out, outlen) < 0 + || x509_explicit_exts_to_der(0, crl_exts, crl_exts_len, out, outlen) < 0) { + error_print(); + return -1; + } + 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_a, tbs_alen) != 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_crl_from_der_ex( + int *version, + int *inner_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, + int *sig_alg, const uint8_t **sig, size_t *siglen, + const uint8_t **in, size_t *inlen) +{ + int ret; + const uint8_t *tbs; + size_t tbs_len; + + if ((ret = x509_signed_from_der(&tbs, &tbs_len, sig_alg, sig, siglen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (x509_tbs_crl_from_der(version, inner_sig_alg, issuer, issuer_len, this_update, next_update, revoked_certs, revoked_certs_len, - exts, exts_len, &p, &tbslen) != 1) { + exts, exts_len, &tbs, &tbs_len) != 1 + || asn1_length_is_zero(tbs_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) { - error_print(); - return -1; - } - if (asn1_any_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_any_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; - } - *crl_len = outlen; return 1; } int x509_crl_verify(const uint8_t *a, size_t alen, const SM2_KEY *pub_key, const char *signer_id, size_t signer_id_len) { - int ret; - const uint8_t *d; - size_t dlen; - const uint8_t *tbs; - size_t tbslen; - int sig_alg; - const uint8_t *sig; - size_t siglen; - SM2_SIGN_CTX verify_ctx; - - if ((ret = asn1_sequence_from_der(&d, &dlen, &a, &alen)) != 1) { - if (ret < 0) error_print(); - else error_print(); - return -1; - } - 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) { + // change x509_cert_verify to x509_verify + if (x509_cert_verify(a, alen, pub_key, signer_id, signer_id_len) != 1) { error_print(); return -1; } - if (sig_alg != OID_sm2sign_with_sm3) { - error_print(); - return -1; - } - if (sm2_verify_init(&verify_ctx, pub_key, signer_id, signer_id_len) != 1 - || sm2_verify_update(&verify_ctx, tbs, tbslen) != 1) { - error_print(); - return -1; - } - if ((ret = sm2_verify_finish(&verify_ctx, sig, siglen)) != 1) { - if (ret < 0) error_print(); - else error_print(); - return -1; - } return 1; } -int x509_crl_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_crl_verify_by_ca_cert(const uint8_t *a, size_t alen, + const uint8_t *cert, size_t certlen, const char *signer_id, size_t signer_id_len) { - int ret; - SM2_KEY public_key; - - if (x509_cert_get_subject_public_key(cacert, cacertlen, &public_key) != 1 - || (ret = x509_crl_verify(a, alen, &public_key, signer_id, signer_id_len)) < 0) { + if (x509_cert_verify_by_ca_cert(a, alen, cert, certlen, signer_id, signer_id_len) != 1) { error_print(); return -1; } - if (!ret) error_print(); - return ret; + return 1; } int x509_crl_get_details(const uint8_t *a, size_t alen, - int *opt_version, - const uint8_t **opt_issuer, size_t *opt_issuer_len, - time_t *opt_this_update, - time_t *opt_next_update, - const uint8_t **opt_revoked_certs, size_t *opt_revoked_certs_len, - const uint8_t **opt_exts, size_t *opt_exts_len, - int *opt_signature_algor, - const uint8_t **opt_sig, size_t *opt_siglen) + int *version, int *inner_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, + int *sig_alg, const uint8_t **sig, size_t *siglen) { - int ret; - const uint8_t *d; - size_t dlen; - const uint8_t *tbs; - size_t tbs_len; - int signature_algor; - const uint8_t *sig; - size_t siglen; + int crl_sig_alg; + const uint8_t *crl_sig; + size_t crl_siglen; + 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; + } tbs; + if (x509_tbs_crl_from_der( + &tbs.version, &tbs.sig_alg, + &tbs.issuer, &tbs.issuer_len, + &tbs.this_update, &tbs.next_update, + &tbs.revoked_certs, &tbs.revoked_certs_len, + &tbs.exts, &tbs.exts_len, &a, &alen) != 1 + || asn1_length_is_zero(alen) != 1) { + error_print(); + return -1; + } + + if (version) *version = tbs.version; + if (inner_sig_alg) *inner_sig_alg = tbs.sig_alg; + if (issuer) *issuer = tbs.issuer; + if (issuer_len) *issuer_len = tbs.issuer_len; + if (this_update) *this_update = tbs.this_update; + if (next_update) *next_update = tbs.next_update; + if (revoked_certs) *revoked_certs = tbs.revoked_certs; + if (revoked_certs_len) *revoked_certs_len = tbs.revoked_certs_len; + if (exts) *exts = tbs.exts; + if (exts_len) *exts_len = tbs.exts_len; + if (sig_alg) *sig_alg = crl_sig_alg; + if (sig) *sig = crl_sig; + if (siglen) *siglen = crl_siglen; + return 1; +} + +int x509_crl_validate(const uint8_t *a, size_t alen, time_t now, const uint8_t *ca_subject, size_t ca_subject_len) +{ int version; - int sig_alg; + int inner_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; + int sig_alg; - if ((ret = asn1_sequence_from_der(&d, &dlen, &a, &alen)) != 1) { - if (ret < 0) error_print(); - else error_print(); - return -1; - } - if (asn1_any_from_der(&tbs, &tbs_len, &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) { + if (x509_crl_get_details(a, alen, &version, &inner_sig_alg, + &issuer, &issuer_len, &this_update, &next_update, + NULL, NULL, &exts, &exts_len, &sig_alg, NULL, NULL) != 1) { error_print(); return -1; } - if (opt_signature_algor) *opt_signature_algor = signature_algor; - if (opt_sig) *opt_sig = sig; - if (opt_siglen) *opt_siglen = siglen; - - if (x509_tbs_crl_from_der(&version, &sig_alg, &issuer, &issuer_len, - &this_update, &next_update, &revoked_certs, &revoked_certs_len, - &exts, &exts_len, &tbs, &tbs_len) != 1 - || asn1_length_is_zero(tbs_len) != 1) { + if (inner_sig_alg != sig_alg) { + error_print(); + return -1; + } + if (version != X509_version_v1 && version != X509_version_v2) { + error_print(); + return -1; + } + if (issuer_len != ca_subject_len || memcmp(issuer, ca_subject, ca_subject_len) != 0) { + error_print(); + return -1; + } + // this_update <= now < next_update + if (now < this_update) { + error_print(); + return -1; + } + if (next_update >= 0) { + if (now >= next_update) { + error_print(); + return -1; + } + } + if (x509_crl_exts_validate(exts, exts_len) != 1) { error_print(); return -1; } - - if (opt_version) *opt_version = version; - if (opt_issuer) *opt_issuer = issuer; - if (opt_issuer_len) *opt_issuer_len = issuer_len; - if (opt_this_update) *opt_this_update = this_update; - if (opt_next_update) *opt_next_update = next_update; - if (opt_revoked_certs) *opt_revoked_certs = revoked_certs; - if (opt_revoked_certs_len) *opt_revoked_certs_len = revoked_certs_len; - if (opt_exts) *opt_exts = exts; - if (opt_exts_len) *opt_exts_len = exts_len; return 1; } @@ -1138,12 +1595,29 @@ int x509_crl_get_issuer(const uint8_t *crl, size_t crl_len, { if (x509_crl_get_details(crl, crl_len, NULL, // version - issuer, issuer_len, + NULL, // sig_alg + issuer, issuer_len, // issuer, issuer_len NULL, NULL, // this_udpate, next_update NULL, NULL, // revoked_certs, revoked_certs_len NULL, NULL, // exts, exts_len, - NULL, // signature_algor - NULL, NULL // sig, siglen + NULL, NULL, NULL // sig_alg, sig, siglen + ) != 1) { + error_print(); + return -1; + } + return 1; +} + +int x509_crl_get_revoked_certs(const uint8_t *a, size_t alen, const uint8_t **d, size_t *dlen) +{ + if (x509_crl_get_details(a, alen, + NULL, // version + NULL, // sig_alg + NULL, NULL, // issuer, issuer_len + NULL, NULL, // this_udpate, next_update + d, dlen, // revoked_certs, revoked_certs_len + NULL, NULL, // exts, exts_len + NULL, NULL, NULL // sig_alg, sig, siglen ) != 1) { error_print(); return -1; @@ -1152,39 +1626,23 @@ int x509_crl_get_issuer(const uint8_t *crl, size_t crl_len, } int x509_crl_find_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, - const uint8_t *serial, size_t serial_len, - time_t *revoke_date, - const uint8_t **entry_exts, size_t *entry_exts_len) + const uint8_t *serial, size_t serial_len, time_t *revoke_date, + const uint8_t **crl_entry_exts, size_t *crl_entry_exts_len) { - const uint8_t *certs; - size_t certslen; + int ret; + const uint8_t *d; + size_t dlen; - if (x509_crl_get_details(a, alen, - NULL, NULL, NULL, NULL, NULL, - &certs, &certslen, - NULL, NULL, NULL, NULL, NULL) != 1) { + if (x509_crl_get_revoked_certs(a, alen, &d, &dlen) != 1) { error_print(); return -1; } - while (certslen) { - const uint8_t *serial_number; - size_t serial_number_len; - - if (x509_revoked_cert_from_der( - &serial_number, &serial_number_len, - revoke_date, - entry_exts, entry_exts_len, - &certs, &certslen) != 1) { - error_print(); - return -1; - } - if (serial_number_len == serial_len - && memcmp(serial_number, serial, serial_len) == 0) { - return 1; - } + if ((ret = x509_revoked_certs_find_revoked_cert_by_serial_number(d, dlen, serial, serial_len, + revoke_date, crl_entry_exts, crl_entry_exts_len)) < 0) { + error_print(); + return -1; } - - return 0; + return ret; } int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -1204,3 +1662,44 @@ int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t } return 1; } + +int x509_crl_new_from_uri(uint8_t **crl, size_t *crl_len, const char *uri, size_t urilen) +{ + int ret = -1; + char *uristr = NULL; + uint8_t *buf = NULL; + size_t buflen; + const uint8_t *p; + + if (!(uristr = strndup(uri, urilen))) { + error_print(); + return -1; + } + if (http_get(uristr, NULL, &buflen, 0) < 0) { + error_print(); + goto end; + } + if (!buflen) { + error_print(); + goto end; + } + if (!(buf = malloc(buflen))) { + error_print(); + goto end; + } + if (http_get(uristr, buf, &buflen, buflen) != 1) { + error_print(); + goto end; + } + p = buf; + if (x509_crl_from_der((const uint8_t **)crl, crl_len, &p, &buflen) != 1) { + error_print(); + goto end; + } + buf = NULL; + ret = 1; +end: + if (uristr) free(uristr); + if (buf) free(buf); + return ret; +} diff --git a/src/x509_ext.c b/src/x509_ext.c index 17b1d1dc..22691f7f 100644 --- a/src/x509_ext.c +++ b/src/x509_ext.c @@ -284,23 +284,15 @@ int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen, return 1; } -int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, - int critical, const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) +int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, size_t maxlen, + int oid, int critical, const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) { - int oid = OID_ce_crl_distribution_points; size_t curlen = *extslen; uint8_t val[256]; uint8_t *p = val; size_t vlen = 0; size_t len = 0; - // The extension SHOULD be non-critical, but this profile - // RECOMMENDS support for this extension by CAs and applications. - if (critical) { - error_print(); - //return -1; - } - if (x509_distribution_points_to_der(http_uri, http_urilen, ldap_uri, ldap_urilen, NULL, &len) != 1 || asn1_length_le(len, sizeof(val)) != 1 || x509_distribution_points_to_der(http_uri, http_urilen, ldap_uri, ldap_urilen, &p, &vlen) != 1) { @@ -317,6 +309,18 @@ int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t return 1; } +int x509_exts_add_crl_distribution_points(uint8_t *exts, size_t *extslen, size_t maxlen, + int critical, const char *http_uri, size_t http_urilen, const char *ldap_uri, size_t ldap_urilen) +{ + int oid = OID_ce_crl_distribution_points; + if (x509_exts_add_crl_distribution_points_ex(exts, extslen, maxlen, + oid, critical, http_uri, http_urilen, ldap_uri, ldap_urilen) != 1) { + error_print(); + return -1; + } + return 1; +} + int x509_exts_add_inhibit_any_policy(uint8_t *exts, size_t *extslen, size_t maxlen, int critical, int skip_certs) { @@ -705,6 +709,38 @@ 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; @@ -1118,6 +1154,12 @@ 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) +{ + error_print(); + return -1; +} + int x509_certificate_policies_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; @@ -1201,6 +1243,16 @@ 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; @@ -1343,6 +1395,8 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t * return 1; } + +// 这个函数原型可能要改一下 int x509_basic_constraints_validate(int ca, int path_len_cons, int cert_type) { /* @@ -1598,6 +1652,12 @@ int x509_policy_constraints_from_der( return 1; } +int x509_policy_constraints_validate(const uint8_t *a, size_t alen) +{ + return -1; + +} + int x509_policy_constraints_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { int ret, val; @@ -1670,6 +1730,7 @@ int x509_ext_key_usage_from_der(int *oids, size_t *oids_cnt, size_t max_cnt, con return 1; } +// 这个函数原型可能也要改一下 int x509_ext_key_usage_validate(const int *oids, size_t oids_cnt, int cert_type) { int ret = -1; @@ -1994,6 +2055,11 @@ err: return -1; } +int x509_distribution_points_validate(const uint8_t *d, size_t dlen) +{ + return -1; +} + int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { const uint8_t *p; @@ -2055,6 +2121,69 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type, } switch (oid) { + case OID_ce_authority_key_identifier: + if (critical == X509_critical) { + error_print(); + return -1; + } + /* + if (x509_authority_key_identifier(val, vlen) != 1) { + error_print(); + return -1; + } + */ + break; + case OID_ce_subject_key_identifier: + if (critical == X509_critical) { + error_print(); + return -1; + } + const uint8_t *p; + size_t len; + if (asn1_octet_string_from_der(&p, &len, &val, &vlen) != 1 + || asn1_length_is_zero(vlen) != 1) { + error_print(); + return -1; + } + if (!p || !len) { + error_print(); + return -1; + } + break; + case OID_ce_key_usage: + if (critical != X509_critical) { + error_print(); + // 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) { + error_print(); + return -1; + } + break; + case OID_ce_certificate_policies: + break; + case OID_ce_policy_mappings: + if (critical != X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_subject_alt_name: + break; + case OID_ce_issuer_alt_name: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + case OID_ce_subject_directory_attributes: + if (critical == X509_critical) { + error_print(); + return -1; + } + break; + 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) { @@ -2063,13 +2192,7 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type, } break; - case OID_ce_key_usage: - if (asn1_bits_from_der(&key_usage, &val, &vlen) != 1 - || x509_key_usage_validate(key_usage, cert_type) != 1) { - error_print(); - return -1; - } - break; + case OID_ce_ext_key_usage: if (x509_ext_key_usage_from_der(ext_key_usages, &ext_key_usages_cnt, @@ -2080,20 +2203,15 @@ int x509_exts_validate(const uint8_t *exts, size_t extslen, int cert_type, } break; - case OID_ce_authority_key_identifier: - case OID_ce_subject_key_identifier: - case OID_ce_certificate_policies: - case OID_ce_policy_mappings: - case OID_ce_subject_alt_name: - case OID_ce_issuer_alt_name: - case OID_ce_subject_directory_attributes: case OID_ce_name_constraints: case OID_ce_policy_constraints: case OID_ce_crl_distribution_points: case OID_ce_inhibit_any_policy: case OID_ce_freshest_crl: + + break; default: - if (critical) { + if (critical == X509_critical) { error_print(); return -1; } diff --git a/tests/httptest.c b/tests/httptest.c index 680f3628..7c7641c9 100644 --- a/tests/httptest.c +++ b/tests/httptest.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -77,17 +78,33 @@ static int test_http_parse_uri_bad(void) return 1; } +static int test_http_get_crl(void) +{ + char *tests[] = { + "http://crl.pki.goog/gsr1/gsr1.crl", + }; + uint8_t buf[65536]; + size_t contentlen; + size_t i; + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (http_get(tests[i], buf, &contentlen, sizeof(buf)) != 1) { + fprintf(stderr, "%s() tests[%zu] <%s> failure\n", __FUNCTION__, i, tests[i]); + error_print(); + return -1; + } + x509_crl_print(stderr, 0, 0, "CRL", buf, contentlen); + } - - - - + printf("%s() ok\n", __FUNCTION__); + return 1; +} int main(void) { if (test_http_parse_uri() != 1) { error_print(); return -1; } if (test_http_parse_uri_bad() != 1) { error_print(); return -1; } + if (test_http_get_crl() != 1) { error_print(); return -1; } printf("%s all tests passed\n", __FILE__); return 0; } diff --git a/tests/x509_crltest.c b/tests/x509_crltest.c index 808f5283..c09f53fb 100644 --- a/tests/x509_crltest.c +++ b/tests/x509_crltest.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -83,34 +84,132 @@ static int test_x509_crl_entry_ext(void) return 1; } -static int test_x509_crl_entry_exts(void) +static int test_vector_gen_uri_as_general_names(void) { - uint8_t exts[2560]; - size_t extslen = 0; - int reason = X509_cr_key_compromise; - time_t tv; - uint8_t issuer[256]; - size_t issuer_len = 0; - int critical = 1; + const char *uri = "http://www.example.com/path"; + uint8_t buf[256]; + uint8_t *p; + const uint8_t *cp; + size_t len; + const uint8_t *d; + size_t dlen; + size_t i; - uint8_t buf[5120]; - uint8_t *p = buf; - const uint8_t *cp = buf; - size_t len = 0; - - //FIXME: set issuer - issuer_len = 20; - - time(&tv); - if (x509_crl_entry_exts_add_reason(exts, &extslen, sizeof(exts), critical, reason) != 1 - //|| x509_crl_entry_exts_add_invalidity_date(exts, &extslen, sizeof(exts), critical, tv) != 1 //FIXME u_time related - || x509_crl_entry_exts_add_certificate_issuer(exts, &extslen, sizeof(exts), critical, issuer, issuer_len) != 1 - || x509_crl_entry_exts_to_der(exts, extslen, &p, &len) != 1 - ) { + cp = p = buf; len = 0; + if (x509_uri_as_general_names_to_der(uri, strlen(uri), &p, &len) != 1 + || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + printf("// generated by %s()\n", __FUNCTION__); + printf("const uint8_t cert_issuer[] = {\n\t"); + for (i = 0; i < dlen; i++) { + printf("0x%02x,", d[i]); + if ((i + 1) % 8 == 0) printf("\n\t"); + } + printf("\n};\n"); + return 1; +} + + +static int test_x509_crl_entry_exts(void) +{ + // generated by test_vector_gen_uri_as_general_names() + const uint8_t cert_issuer[] = { + 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, + 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, + 0x2f,0x70,0x61,0x74,0x68, + }; + struct { + int reason; + time_t invalid_date; + const uint8_t *cert_issuer; + size_t cert_issuer_len; + } tests[] = { + { X509_cr_key_compromise, -1, NULL, 0 }, + { -1, time(NULL), NULL, 0 }, + { -1, -1, cert_issuer, sizeof(cert_issuer) }, + { X509_cr_key_compromise, time(NULL), NULL, 0 }, + { X509_cr_key_compromise, time(NULL), cert_issuer, sizeof(cert_issuer) }, + }; + + uint8_t buf[1024]; + uint8_t *p; + const uint8_t *cp; + size_t len; + size_t i; + + int reason; + time_t invalid_date; + const uint8_t *issuer; + size_t issuer_len; + + cp = p = buf; len = 0; + if (x509_crl_entry_exts_to_der(-1, -1, NULL, 0, &p, &len) != 0) { + error_print(); + return -1; + } + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_crl_entry_exts_to_der( + tests[i].reason, + tests[i].invalid_date, + tests[i].cert_issuer, + tests[i].cert_issuer_len, &p, &len) != 1) { + error_print(); + return -1; + } + //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); + if (len > sizeof(buf)) { + error_print(); + return -1; + } + } + + { + size_t left = len; + const uint8_t *d; + size_t dlen; + cp = buf; + while (left) { + if (asn1_sequence_from_der(&d, &dlen, &cp, &left) != 1) { + error_print(); + return -1; + } + x509_crl_entry_exts_print(stderr, 0, 0, "CRLEntryExtensions", d, dlen); + + if (x509_crl_entry_exts_validate(d, dlen) != 1) { + error_print(); + return -1; + } + } + } + + cp = p = buf; + for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) { + if (x509_crl_entry_exts_from_der(&reason, &invalid_date, &issuer, &issuer_len, &cp, &len) != 1) { + error_print(); + return -1; + } + if (reason != tests[i].reason) { + error_print(); + return -1; + } + if (invalid_date != tests[i].invalid_date) { + error_print(); + return -1; + } + if (issuer_len != tests[i].cert_issuer_len || memcmp(issuer, tests[i].cert_issuer, issuer_len) != 0) { + error_print(); + return -1; + } + //printf("%s %d: test %zu passed\n", __FILE__, __LINE__, i); + } + if (len != 0) { error_print(); return -1; } - x509_crl_entry_exts_print(stderr, 0, 0, "CRLEntryExtensions", exts, extslen); printf("%s() ok\n", __FUNCTION__); return 1; @@ -118,19 +217,32 @@ static int test_x509_crl_entry_exts(void) static int test_x509_revoked_cert(void) { - uint8_t serial[20] = { 0x01,0x02 }; - time_t revoke_date; + uint8_t serial_buf[16] = { 0x01,0x02,0x00 }; + time_t revoke_date = time(NULL); + int reason = X509_cr_key_compromise; + time_t invalid_date = revoke_date; + // generated by test_vector_gen_uri_as_general_names() + const uint8_t cert_issuer_buf[] = { + 0x86,0x1b,0x68,0x74,0x74,0x70,0x3a,0x2f, + 0x2f,0x77,0x77,0x77,0x2e,0x65,0x78,0x61, + 0x6d,0x70,0x6c,0x65,0x2e,0x63,0x6f,0x6d, + 0x2f,0x70,0x61,0x74,0x68, + }; + const uint8_t *serial; + size_t serial_len; + const uint8_t *cert_issuer; + size_t cert_issuer_len; uint8_t buf[512]; - uint8_t *p = buf; - const uint8_t *cp = buf; + uint8_t *p; + const uint8_t *cp; size_t len = 0; - const uint8_t *d; size_t dlen; - time(&revoke_date); - if (x509_revoked_cert_to_der(serial, sizeof(serial), revoke_date, NULL, 0, &p, &len) != 1 + cp = p = buf; len = 0; + if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, + reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 || asn1_sequence_from_der(&d, &dlen, &cp, &len) != 1 || asn1_length_is_zero(len) != 1) { error_print(); @@ -138,9 +250,100 @@ static int test_x509_revoked_cert(void) } x509_revoked_cert_print(stderr, 0, 0, "RevokedCertificate", d, dlen); + cp = p = buf; len = 0; + if (x509_revoked_cert_to_der_ex(serial_buf, sizeof(serial_buf), revoke_date, + reason, invalid_date, cert_issuer_buf, sizeof(cert_issuer_buf), &p, &len) != 1 + || x509_revoked_cert_from_der_ex(&serial, &serial_len, &revoke_date, + &reason, &invalid_date, &cert_issuer, &cert_issuer_len, &cp, &len) != 1 + || asn1_length_is_zero(len) != 1) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); return 1; } +static int test_x509_crl_ext_id(void) +{ + int crl_ext_oids[] = { + OID_ce_authority_key_identifier, + OID_ce_issuer_alt_name, + OID_ce_crl_number, + OID_ce_delta_crl_indicator, + OID_ce_issuing_distribution_point, + OID_ce_freshest_crl, + OID_pe_authority_info_access, + }; + int oid; + + uint8_t buf[512]; + uint8_t *p; + const uint8_t *cp; + size_t len; + size_t i; + + cp = p = buf; len = 0; + for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { + if (x509_crl_ext_id_to_der(crl_ext_oids[i], &p, &len) != 1) { + error_print(); + return -1; + } + format_bytes(stderr, 0, 0, "", buf, len); + } + for (i = 0; i < sizeof(crl_ext_oids)/sizeof(crl_ext_oids[0]); i++) { + if (x509_crl_ext_id_from_der(&oid, &cp, &len) != 1) { + error_print(); + return -1; + } + printf(" %s\n", x509_crl_ext_id_name(oid)); + } + if (len) { + error_print(); + return -1; + } + + printf("%s() ok\n", __FUNCTION__); + return 1; +} + +static int test_x509_crl_exts(void) +{ + /* + uint8_t exts[1024]; + size_t extslen = 0; + + if (0 + || x509_crl_exts_add_authority_key_identifier(exts, &extslen, sizeof(exts), + X509_non_critical, key_id, sizeof(key_id), issuer, sizeof(issuer), serial, sizeof(serial)) != 1 + || x509_crl_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts), + X509_non_critical, issuer_alt_name, sizeof(issuer_alt_name)) != 1 + || x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), + X509_non_critical, 112) != 1 + || x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), + X509_non_critical, 113) != 1 + || x509_crl_exts_add_issuing_distribution_point(exts, &extslen, sizeof(exts), + X509_non_critical, dist_point_uri, strlen(dist_point_uri), + ASN1_FALSE, ASN1_FALSE, -1, ASN1_FALSE, ASN1_FALSE) != 1 + || x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), + X509_non_critical, http_uri, strlen(http_uri), ldap_uri, strlen(ldap_uri)) != 1 + || x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), + X509_non_critical, ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1) { + error_print(); + return -1; + } + + x509_crl_exts_print(stderr, 0, 0, "CRLExtensions", exts, extslen); + */ + + return 1; +} + +static int test_x509_cert_revoke(void) +{ + printf("%s() ok\n", __FUNCTION__); + return 1; +} int main(void) { @@ -148,6 +351,8 @@ int main(void) if (test_x509_crl_entry_ext() != 1) goto err; if (test_x509_crl_entry_exts() != 1) goto err; if (test_x509_revoked_cert() != 1) goto err; +// if (test_vector_gen_uri_as_general_names() != 1) goto err; + if (test_x509_crl_ext_id() != 1) goto err; printf("%s all tests passed\n", __FILE__); return 0; err: diff --git a/tools/certrevoke.c b/tools/certrevoke.c new file mode 100644 index 00000000..c6b000b5 --- /dev/null +++ b/tools/certrevoke.c @@ -0,0 +1,139 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include + +// 20220105Z + +static const char *options = "-in cert.pem [-reason str] [-invalid_date timestamp] [-out RevokedCertificate.der]"; + +static void print_options(FILE *fp, const char *prog) +{ + int i; + fprintf(fp, "Options:\n"); + fprintf(fp, " -in cert.pem Certificate in PEM format to be revoked\n"); + fprintf(fp, " -reason code Revocation reason code, avaiable codes:\n"); + for (i = 0; i <= X509_cr_aa_compromise; i++) { + fprintf(fp, " %s (%d)\n", x509_crl_reason_name(i), i); + } + fprintf(fp, " -invalid_date time Revocation timestamp in YYYYMMDDHHMMSSZ format\n"); + fprintf(fp, " Example: -invalid_date 20221231000000Z\n"); + fprintf(fp, " -out file.der Output ASN.1 RevokedCertificate in DER format\n"); + + fprintf(fp, "Examples:\n"); + fprintf(fp, " %s -in cert1.pem -reason keyCompromise -invalid_date 20221230000000Z -out revoked_certs.der\n", prog); + fprintf(fp, " %s -in cert2.pem -reason keyCompromise -invalid_date 20221231000000Z >> revoked_certs.der\n", prog); +} + +int certrevoke_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + char *outfile = NULL; + int reason = -1; + time_t invalid_date = -1; + uint8_t *cert = NULL; + size_t certlen; + uint8_t *outbuf = NULL; + uint8_t *out; + size_t outlen; + FILE *outfp = stdout; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + print_options(stdout, prog); + goto end; + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (x509_cert_new_from_file(&cert, &certlen, infile) != 1) { + fprintf(stderr, "%s: open cert file %s failure\n", prog, infile); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-reason")) { + char *name; + int i; + if (--argc < 1) goto bad; + name = *(++argv); + if (x509_crl_reason_from_name(&reason, name) != 1) { + fprintf(stderr, "%s: invalid reason '%s'\n", prog, name); + fprintf(stderr, "-reason values:\n"); + for (i = 0; i <= X509_cr_aa_compromise; i++) { + fprintf(stderr, " %s\n", x509_crl_reason_name(i)); + } + } + } else if (!strcmp(*argv, "-invalid_date")) { + char *time_str; + if (--argc < 1) goto bad; + time_str =*(++argv); + if (asn1_time_from_str(0, &invalid_date, time_str) != 1) { + fprintf(stderr, "%s: invalid time '%s', should provide 'YYYYMMDDHHMMSSZ'\n", prog, time_str); + goto bad; + } + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!infile) { + fprintf(stderr, "usage: %s %s\n", prog, options); + goto end; + } + if (x509_cert_revoke_to_der(cert, certlen, time(NULL), reason, invalid_date, NULL, 0, NULL, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (!(outbuf = malloc(outlen))) { + fprintf(stderr, "%s: malloc failure\n", prog); + goto end; + } + out = outbuf; + outlen = 0; + if (x509_cert_revoke_to_der(cert, certlen, time(NULL), reason, invalid_date, NULL, 0, &out, &outlen) != 1) { + fprintf(stderr, "%s: inner error\n", prog); + goto end; + } + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure\n", prog); + goto end; + } + ret = 0; + +end: + if (cert) free(cert); + if (outfile && outfp) fclose(outfp); + if (outbuf) free(outbuf); + return ret; +} diff --git a/tools/crlgen.c b/tools/crlgen.c new file mode 100644 index 00000000..8e772fbf --- /dev/null +++ b/tools/crlgen.c @@ -0,0 +1,161 @@ +/* + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * + * http://www.apache.org/licenses/LICENSE-2.0 + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + +static const char *options = + "-in RevokedCertificate.der" + " -key pem -pass str -cert pem" + " [-next_update timestamp] " + " [-out crl.der]"; + +int crlgen_main(int argc, char **argv) +{ + int ret = 1; + char *prog = argv[0]; + char *infile = NULL; + uint8_t *revoked_certs = NULL; + size_t revoked_certs_len = 0; + char *outfile = NULL; + FILE *outfp = stdout; + char *keyfile = NULL; + char *pass = NULL; + FILE *keyfp = NULL; + SM2_KEY sign_key; + char *cacertfile = NULL; + uint8_t *cacert = NULL; + size_t cacert_len = 0; + const uint8_t *issuer; + size_t issuer_len; + time_t next_update = -1; + + uint8_t outbuf[64 * 1024]; + uint8_t *out = outbuf; + size_t outlen = 0; + + argc--; + argv++; + + while (argc > 0) { + if (!strcmp(*argv, "-help")) { + printf("usage: %s %s\n", prog, options); + goto end; + + } else if (!strcmp(*argv, "-in")) { + if (--argc < 1) goto bad; + infile = *(++argv); + if (file_read_all(infile, &revoked_certs, &revoked_certs_len) != 1) { + fprintf(stderr, "%s: read input file failed\n", prog); + goto end; + } + } else if (!strcmp(*argv, "-out")) { + if (--argc < 1) goto bad; + outfile = *(++argv); + if (!(outfp = fopen(outfile, "wb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-key")) { + if (--argc < 1) goto bad; + keyfile = *(++argv); + if (!(keyfp = fopen(keyfile, "rb"))) { + fprintf(stderr, "%s: open '%s' failure : %s\n", prog, keyfile, strerror(errno)); + goto end; + } + } else if (!strcmp(*argv, "-pass")) { + if (--argc < 1) goto bad; + } else if (!strcmp(*argv, "-cacert")) { + if (--argc < 1) goto bad; + cacertfile = *(++argv); + if (x509_cert_new_from_file(&cacert, &cacert_len, cacertfile) != 1) { + goto end; + } + } else if (!strcmp(*argv, "-next_update")) { + if (--argc < 1) goto bad; + next_update = atoi(*(++argv)); + } else { + fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv); + goto end; +bad: + fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv); + goto end; + } + + argc--; + argv++; + } + + if (!infile) { + fprintf(stderr, "%s: '-in' option required\n", prog); + goto end; + } + + if (!cacertfile) { + fprintf(stderr, "%s: '-cacert' option required\n", prog); + goto end; + } + + if (!keyfile) { + fprintf(stderr, "%s: '-key' option required\n", prog); + goto end; + } + if (!pass) { + fprintf(stderr, "%s: '-pass' option required\n", prog); + goto end; + } + + + if (!revoked_certs || !revoked_certs_len) { + fprintf(stderr, "usage: %s %s\n", prog, options); + goto end; + } + + if (x509_cert_get_subject(cacert, cacert_len, &issuer, &issuer_len) != 1) { + fprintf(stderr, "%s: parse CA certificate failure\n", prog); + goto end; + } + if (sm2_private_key_info_decrypt_from_pem(&sign_key, pass, keyfp) != 1) { + fprintf(stderr, "%s: load private key failure\n", prog); + goto end; + } + + if (x509_crl_sign_to_der( + X509_version_v2, + OID_sm2sign_with_sm3, + issuer, issuer_len, + time(NULL), next_update, + revoked_certs, revoked_certs_len, + NULL, 0, + &sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH, + &out, &outlen) != 1) { + + // error_print(); + return -1; + } + + if (fwrite(outbuf, 1, outlen, outfp) != outlen) { + fprintf(stderr, "%s: output failure\n", prog); + return -1; + } + ret = 0; + +end: + //if (cert) free(cert); + if (outfile && outfp) fclose(outfp); + return ret; +} diff --git a/tools/gmssl.c b/tools/gmssl.c index 1612c5a0..c9040fd8 100644 --- a/tools/gmssl.c +++ b/tools/gmssl.c @@ -1,5 +1,5 @@ /* - * Copyright 2014-2022 The GmSSL Project. All Rights Reserved. + * Copyright 2014-2023 The GmSSL Project. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the License); you may * not use this file except in compliance with the License. @@ -18,6 +18,8 @@ extern int rand_main(int argc, char **argv); extern int certgen_main(int argc, char **argv); extern int certparse_main(int argc, char **argv); extern int certverify_main(int argc, char **argv); +extern int certrevoke_main(int argc, char **argv); +extern int crlgen_main(int argc, char **argv); extern int crlparse_main(int argc, char **argv); extern int crlverify_main(int argc, char **argv); extern int pbkdf2_main(int argc, char **argv); @@ -80,11 +82,13 @@ static const char *options = " reqgen Generate certificate signing request (CSR)\n" " reqsign Generate certificate from CSR\n" " reqparse Parse and print a CSR\n" + " crlgen Sign a CRL with CA certificate and private key\n" " crlparse Verify a CRL with certificate\n" " crlverify Parse and print CRL\n" " certgen Generate a self-signed certificate\n" " certparse Parse and print certificates\n" " certverify Verify certificate chain\n" + " certrevoke Revoke certificate and output RevokedCertificate in DER\n" " cmsparse Parse cryptographic message syntax (CMS)\n" " cmsencrypt Generate CMS EnvelopedData\n" " cmsdecrypt Decrypt CMS EnvelopedData\n" @@ -128,6 +132,10 @@ int main(int argc, char **argv) return certparse_main(argc, argv); } else if (!strcmp(*argv, "certverify")) { return certverify_main(argc, argv); + } else if (!strcmp(*argv, "certrevoke")) { + return certrevoke_main(argc, argv); + } else if (!strcmp(*argv, "crlgen")) { + return crlgen_main(argc, argv); } else if (!strcmp(*argv, "crlparse")) { return crlparse_main(argc, argv); } else if (!strcmp(*argv, "crlverify")) {