Update X.509 Extensions

This commit is contained in:
Zhi Guan
2023-01-31 15:57:53 +08:00
parent ec7700c17c
commit 13eae91d7d
20 changed files with 1348 additions and 497 deletions

View File

@@ -328,6 +328,7 @@ int x509_cert_get_details(const uint8_t *a, size_t alen,
const uint8_t **signature, size_t *signature_len);
int x509_cert_validate(const uint8_t *cert, size_t certlen, int cert_type, int *path_len_constraints);
/*
IssuerAndSerialNumber ::= SEQUENCE {
isser Name,
@@ -339,6 +340,8 @@ int x509_cert_get_issuer_and_serial_number(const uint8_t *a, size_t alen,
int x509_cert_get_issuer(const uint8_t *a, size_t alen, const uint8_t **name, size_t *namelen);
int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, size_t *subj_len);
int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key);
#define x509_cert_get_exts(a,alen,d,dlen) x509_cert_get_details(a,alen,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,d,dlen,NULL,NULL,NULL)
int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp);
int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp);

View File

@@ -42,7 +42,7 @@ int x509_encryption_algor_from_der(int *oid, const uint8_t **iv, size_t *ivlen,
int x509_encryption_algor_to_der(int oid, const uint8_t *iv, size_t ivlen, uint8_t **out, size_t *outlen);
int x509_encryption_algor_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
#define X509_ALGOR_ALLOW_EC_NULL_PARAM 1
#define X509_ALGOR_ALLOW_EC_NULL_PARAM 0 // FIXME: move to CMakeLists.txt
const char *x509_signature_algor_name(int oid);
int x509_signature_algor_from_name(const char *name);
int x509_signature_algor_from_der(int *oid, const uint8_t **in, size_t *inlen);

View File

@@ -166,6 +166,9 @@ int x509_general_names_add_edi_party_name(uint8_t *gns, size_t *gnslen, size_t m
int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t maxlen,
const uint32_t *nodes, size_t nodes_cnt);
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)
/*
AuthorityKeyIdentifier ::= SEQUENCE {
keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL,
@@ -468,29 +471,24 @@ ReasonFlags ::= BIT STRING {
#define X509_RF_PRIVILEGE_WITHDRAWN (1 << 7)
#define X509_RF_AA_COMPROMISE (1 << 8)
const char *x509_revoke_reason_name(int flag);
int x509_revoke_reason_from_name(int *flag, const char *name);
#define x509_revoke_reasons_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen)
#define x509_revoke_reasons_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen)
int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int bits);
const char *x509_revoke_reason_flag_name(int flag);
int x509_revoke_reason_flag_from_name(int *flag, const char *name);
#define x509_revoke_reason_flags_to_der(bits,out,outlen) asn1_bits_to_der(bits,out,outlen)
#define x509_revoke_reason_flags_from_der(bits,in,inlen) asn1_bits_from_der(bits,in,inlen)
int x509_revoke_reason_flags_print(FILE *fp, int fmt, int ind, const char *label, int bits);
/*
DistributionPointName ::= CHOICE {
fullName [0] IMPLICIT GeneralNames, -- SEQUENCE OF
nameRelativeToCRLIssuer [1] IMPLICIT RelativeDistinguishedName } -- SET OF
*/
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
#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);
int x509_distribution_point_name_to_der(int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_uri_as_distribution_point_name_from_der(const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen);
int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label,const uint8_t *a, size_t alen);
int x509_explicit_distribution_point_name_to_der(int index, int choice, const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen);
int x509_explicit_distribution_point_name_from_der(int index, int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen);
int x509_explicit_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
int x509_uri_as_explicit_distribution_point_name_to_der(int index, const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_uri_as_explicit_distribution_point_name_from_der(int index, const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen);
/*
DistributionPoint ::= SEQUENCE {
@@ -498,16 +496,10 @@ DistributionPoint ::= SEQUENCE {
reasons [1] IMPLICIT ReasonFlags OPTIONAL,
cRLIssuer [2] IMPLICIT GeneralNames OPTIONAL }
*/
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen);
int x509_distribution_points_to_der(const char *http_uri, size_t http_urilen,
const char *ldap_uri, size_t ldap_urilen, uint8_t **out, size_t *outlen);
int x509_distribution_point_to_der(
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
uint8_t **out, size_t *outlen);
int x509_distribution_point_from_der(
int *dist_point_choice, const uint8_t **dist_point, size_t *dist_point_len,
int x509_uri_as_distribution_point_from_der(const char **uri, size_t *urilen,
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen);
int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
@@ -515,9 +507,12 @@ int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label,
/*
DistributionPoints ::= SEQUENCE OF DistributionPoint
*/
int x509_distribution_points_add_distribution_point(uint8_t *d, size_t *dlen, size_t maxlen,
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len);
int x509_uri_as_distribution_points_to_der(const char *uri, size_t urilen,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
uint8_t **out, size_t *outlen);
int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen,
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen);
int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);

View File

@@ -86,7 +86,7 @@ int x509_req_sign(uint8_t *req, size_t *reqlen, size_t maxlen,
int signature_algor,
const SM2_KEY *sign_key, const char *signer_id, size_t signer_id_len);
int x509_req_verify(const uint8_t *req, size_t reqlen,
const SM2_KEY *sign_pubkey, const char *signer_id, size_t signer_id_len);
const char *signer_id, size_t signer_id_len);
int x509_req_get_details(const uint8_t *req, size_t reqlen,
int *verison,
const uint8_t **subject, size_t *subject_len,
@@ -97,6 +97,8 @@ int x509_req_get_details(const uint8_t *req, size_t reqlen,
int x509_req_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *req, size_t reqlen);
int x509_req_to_pem(const uint8_t *req, size_t reqlen, FILE *fp);
int x509_req_from_pem(uint8_t *req, size_t *reqlen, size_t maxlen, FILE *fp);
int x509_req_new_from_pem(uint8_t **req, size_t *reqlen, FILE *fp);
int x509_req_new_from_file(uint8_t **req, size_t *reqlen, const char *file);
#ifdef __cplusplus

View File

@@ -1629,6 +1629,9 @@ int asn1_utc_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *outlen)
error_print();
return -1;
}
if (a == -1) {
return 0;
}
if (asn1_time_to_str(utc_time, a, buf) != 1) {
error_print();
@@ -1704,6 +1707,9 @@ int asn1_generalized_time_to_der_ex(int tag, time_t a, uint8_t **out, size_t *ou
error_print();
return -1;
}
if (a == -1) {
return 0;
}
if (asn1_time_to_str(utc_time, a, buf) != 1) {
error_print();

View File

@@ -721,8 +721,8 @@ int cms_signer_info_print(FILE *fp, int fmt, int ind, const char *label, const u
format_print(fp, fmt, ind, "digestAlgorithm: %s\n", x509_digest_algor_name(val));
if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err;
if (ret) x509_attributes_print(fp, fmt, ind, "authenticatedAttributes", p, len);
if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err;
format_print(fp, fmt, ind, "digestEncryptionAlgorithm: %s\n", x509_signature_algor_name(val));
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
x509_signature_algor_print(fp, fmt, ind, "digestEncryptionAlgorithm", p, len);
if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err;
format_bytes(fp, fmt, ind, "encryptedDigest", p, len);
if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err;

View File

@@ -59,6 +59,32 @@ int x509_digest_algor_from_name(const char *name)
return info->oid;
}
/*
from RFC 5754 Using SHA2 Algorithms with Cryptographic Message Syntax
2. Message Digest Algorithms
The AlgorithmIdentifier parameters field is OPTIONAL.
Implementations MUST accept SHA2 AlgorithmIdentifiers with absent
parameters. Implementations MUST accept SHA2 AlgorithmIdentifiers
with NULL parameters. Implementations MUST generate SHA2
AlgorithmIdentifiers with absent parameters.
from RFC 5758 Internet X.509 Public Key Infrastructure:
Additional Algorithms and Identifiers for DSA and ECDSA
2. Hash Functions
id-sha224
id-sha256
id-sha384
id-sha512
When one of these OIDs appears in an AlgorithmIdentifier, all
implementations MUST accept both NULL and absent parameters as legal
and equivalent encodings.
*/
int x509_digest_algor_to_der(int oid, uint8_t **out, size_t *outlen)
{
const ASN1_OID_INFO *info;
@@ -234,6 +260,59 @@ static uint32_t oid_rsasign_with_sha384[] = { 1,2,840,113549,1,1,12 };
static uint32_t oid_rsasign_with_sha512[] = { 1,2,840,113549,1,1,13 };
/*
from RFC 3447 Public-Key Cryptography Standards (PKCS) #1: RSA Cryptography
Specifications Version 2.1
Appendix C. ASN.1 module
-- When rsaEncryption is used in an AlgorithmIdentifier the
-- parameters MUST be present and MUST be NULL.
-- When the following OIDs are used in an AlgorithmIdentifier the
-- parameters MUST be present and MUST be NULL.
--
md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
sha1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
from RFC 5754 Using SHA2 Algorithms with Cryptographic Message Syntax
3.3. ECDSA
When any of these four object identifiers appears within an
^ ecdsa-with-SHA224/SHA256/SHA384/SHA512
AlgorithmIdentifier, the parameters field MUST be absent. That is,
the AlgorithmIdentifier SHALL be a SEQUENCE of one component: the OID
ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or ecdsa-
with-SHA512.
from RFC 5758 Internet X.509 Public Key Infrastructure:
Additional Algorithms and Identifiers for DSA and ECDSA
3.1. DSA Signature Algorithm
When the id-dsa-with-sha224 or id-dsa-with-sha256 algorithm
identifier appears in the algorithm field as an AlgorithmIdentifier,
the encoding SHALL omit the parameters field. That is, the
AlgorithmIdentifier SHALL be a SEQUENCE of one component, the OID id-
dsa-with-sha224 or id-dsa-with-sha256.
3.2. ECDSA Signature Algorithm
When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or
ecdsa-with-SHA512 algorithm identifier appears in the algorithm field
as an AlgorithmIdentifier, the encoding MUST omit the parameters
field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one
component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-
SHA384, or ecdsa-with-SHA512.
*/
static const ASN1_OID_INFO x509_sign_algors[] = {
{ OID_sm2sign_with_sm3, "sm2sign-with-sm3", oid_sm2sign_with_sm3, sizeof(oid_sm2sign_with_sm3)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), 1 },

View File

@@ -448,7 +448,12 @@ int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen,
{
size_t len = 0;
uint8_t *p = d + *dlen;
if (!val && !more) {
if (!val) {
if (more) {
error_print();
return -1;
}
return 0;
}
if (x509_rdn_to_der(oid, tag, val, vlen, NULL, 0, NULL, &len) != 1
@@ -546,7 +551,7 @@ int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen,
*dlen = 0;
if (x509_name_add_country_name(d, dlen, maxlen, country) < 0
|| x509_name_add_state_or_province_name(d, dlen, maxlen, x509_name_tag(state), (uint8_t *)state, strlen(state)) < 0
|| x509_name_add_state_or_province_name(d, dlen, maxlen, x509_name_tag(state), (uint8_t *)state, _strlen(state)) < 0
|| x509_name_add_locality_name(d, dlen, maxlen, x509_name_tag(locality), (uint8_t *)locality, _strlen(locality)) < 0
|| x509_name_add_organization_name(d, dlen, maxlen, x509_name_tag(org), (uint8_t *)org, _strlen(org)) < 0
|| x509_name_add_organizational_unit_name(d, dlen, maxlen, x509_name_tag(org_unit), (uint8_t *)org_unit, _strlen(org_unit)) < 0
@@ -1118,8 +1123,8 @@ int x509_certificate_print(FILE *fp, int fmt, int ind, const char *label, const
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
x509_tbs_cert_print(fp, fmt, ind, "tbsCertificate", p, len);
if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err;
format_print(fp, fmt, ind, "signatureAlgorithm: %s\n", x509_signature_algor_name(val));
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len);
if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err;
format_bytes(fp, fmt, ind, "signatureValue", p, len);
if (asn1_length_is_zero(dlen) != 1) goto err;

View File

@@ -818,7 +818,7 @@ int x509_issuing_distribution_point_print(FILE *fp, int fmt, int ind, const char
if (!ret) val = 0;
format_print(fp, fmt, ind, "onlyContainsCACerts: %s\n", asn1_boolean_name(val));
if ((ret = asn1_implicit_bits_from_der(3, &val, &d, &dlen)) < 0) goto end;
if (ret) x509_revoke_reasons_print(fp, fmt, ind, "onlySomeReasons", val);
if (ret) x509_revoke_reason_flags_print(fp, fmt, ind, "onlySomeReasons", val);
if ((ret = asn1_implicit_boolean_from_der(4, &val, &d, &dlen)) < 0) goto end;
if (!ret) val = 0;
format_print(fp, fmt, ind, "indirectCRL: %s\n", asn1_boolean_name(val));
@@ -1299,8 +1299,8 @@ int x509_cert_list_print(FILE *fp, int fmt, int ind, const char *label, const ui
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
x509_tbs_crl_print(fp, fmt, ind, "tbsCertList", p, len);
if (x509_signature_algor_from_der(&val, &d, &dlen) != 1) goto err;
format_print(fp, fmt, ind, "signatureAlgorithm: %s\n", x509_signature_algor_name(val));
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err;
x509_signature_algor_print(fp, fmt, ind, "signatureAlgorithm", p, len);
if (asn1_bit_octets_from_der(&p, &len, &d, &dlen) != 1) goto err;
format_bytes(fp, fmt, ind, "signatureValue", p, len);
if (asn1_length_is_zero(dlen) != 1) goto err;

View File

@@ -318,7 +318,7 @@ int x509_exts_add_ext_key_usage(uint8_t *exts, size_t *extslen, size_t maxlen,
}
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, int critical, const char *uri, size_t urilen, const char *ldap_uri, size_t ldap_urilen)
{
size_t curlen = *extslen;
uint8_t val[256];
@@ -326,9 +326,9 @@ int x509_exts_add_crl_distribution_points_ex(uint8_t *exts, size_t *extslen, siz
size_t vlen = 0;
size_t len = 0;
if (x509_distribution_points_to_der(http_uri, http_urilen, ldap_uri, ldap_urilen, NULL, &len) != 1
if (x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, 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) {
|| x509_uri_as_distribution_points_to_der(uri, urilen, -1, NULL, 0, &p, &vlen) != 1) {
error_print();
return -1;
}
@@ -679,6 +679,77 @@ int x509_general_names_add_registered_id(uint8_t *gns, size_t *gnslen, size_t ma
return 1;
}
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
int choice = X509_gn_uniform_resource_identifier;
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_general_name_to_der(choice, (uint8_t *)uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der_ex(tag, len, out, outlen) != 1
|| x509_general_name_to_der(choice, (uint8_t *)uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
/*
int x509_uri_as_general_names_from_der_ex(int tag, const uint8_t **uri, size_t *urilen,
const uint8_t **in, size_t *inlen)
{
int choice = X509_gn_uniform_resource_identifier;
int ret;
const uint8_t *d;
size_t dlen;
if ((ret = asn1_sequence_from_der_ex(tag, &d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (x509_general_names_get_first(d, dlen, NULL, choice, uri, urilen) < 0) {
error_print();
return -1;
}
return 1;
}
*/
int x509_general_names_get_next(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen)
{
if (*ptr > gns + gns_len) {
error_print();
return -1;
}
gns_len -= (*ptr - gns);
while (gns_len) {
int tag;
if (x509_general_name_from_der(&tag, d, dlen, ptr, &gns_len) != 1) {
error_print();
return -1;
}
if (tag == choice) {
return 1;
}
}
return 0;
}
int x509_general_names_get_first(const uint8_t *gns, size_t gns_len, const uint8_t **ptr, int choice, const uint8_t **d, size_t *dlen)
{
int ret;
*ptr = gns;
if ((ret = x509_general_names_get_next(gns, gns_len, ptr, choice, d, dlen)) < 0) {
error_print();
return - 1;
}
return ret;
}
int x509_general_names_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)
{
int choice;
@@ -1843,7 +1914,7 @@ CRL Distribution Points
必须包含 DN, certificateRevocationList 应包含host部分
*/
static const char *x509_revoke_reasons[] = {
static const char *x509_revoke_reason_flags[] = {
"unused",
"keyCompromise",
"cACompromise",
@@ -1855,30 +1926,30 @@ static const char *x509_revoke_reasons[] = {
"aACompromise",
};
static size_t x509_revoke_reasons_count =
sizeof(x509_revoke_reasons)/sizeof(x509_revoke_reasons[0]);
static size_t x509_revoke_reason_flags_count =
sizeof(x509_revoke_reason_flags)/sizeof(x509_revoke_reason_flags[0]);
const char *x509_revoke_reason_name(int flag)
const char *x509_revoke_reason_flag_name(int flag)
{
int i;
for (i = 0; i < x509_revoke_reasons_count; i++) {
for (i = 0; i < x509_revoke_reason_flags_count; i++) {
if (flag & 1) {
if (flag >> 1) {
error_print();
return NULL;
}
return x509_revoke_reasons[i];
return x509_revoke_reason_flags[i];
}
flag >>= 1;
}
return NULL;
}
int x509_revoke_reason_from_name(int *flag, const char *name)
int x509_revoke_reason_flag_from_name(int *flag, const char *name)
{
int i;
for (i = 0; i < x509_revoke_reasons_count; i++) {
if (strcmp(name, x509_revoke_reasons[i]) == 0) {
for (i = 0; i < x509_revoke_reason_flags_count; i++) {
if (strcmp(name, x509_revoke_reason_flags[i]) == 0) {
*flag = 1 << i;
return 1;
}
@@ -1888,104 +1959,59 @@ int x509_revoke_reason_from_name(int *flag, const char *name)
return -1;
}
int x509_revoke_reasons_print(FILE *fp, int fmt, int ind, const char *label, int bits)
int x509_revoke_reason_flags_print(FILE *fp, int fmt, int ind, const char *label, int bits)
{
return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reasons, x509_revoke_reasons_count, bits);
return asn1_bits_print(fp, fmt, ind, label, x509_revoke_reason_flags, x509_revoke_reason_flags_count, bits);
}
int x509_uri_as_general_names_to_der_ex(int tag, const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
int choice = X509_gn_uniform_resource_identifier;
size_t len = 0;
/*
Example CRLDistributionPoints extension
1 DistributionPoint in CRLDistributionPoints
distributionPoint choice: fullName
2 GeneralName in fullName(GeneralNames), same CRL with different URI
Extension
extnID: CRLDistributionPoints (2.5.29.31)
CRLDistributionPoints
DistributionPoint
distributionPoint
fullName
GeneralName
URI: http://mscrl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
GeneralName
URI: http://crl.microsoft.com/pki/mscorp/crl/Microsoft%20RSA%20TLS%20CA%2002.crl
*/
if (!uri || !urilen) {
return 0;
}
if (x509_general_name_to_der(choice, (uint8_t *)uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der_ex(tag, len, out, outlen) != 1
|| x509_general_name_to_der(choice, (uint8_t *)uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_name_to_der(const char *uri, size_t urilen,
uint8_t **out, size_t *outlen)
{
int ret;
if ((ret = x509_uri_as_general_names_to_der_ex(ASN1_TAG_EXPLICIT(0), uri, urilen, out, outlen)) != 1) {
error_print();
return -1;
if (ret < 0) error_print();
return ret;
}
return 1;
}
int x509_uri_as_explicit_distribution_point_name_to_der(int index,
const char *uri, size_t urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_distribution_point_name_to_der(uri, urilen, NULL, &len) != 1
|| asn1_explicit_header_to_der(index, len, out, outlen) != 1
|| x509_uri_as_distribution_point_name_to_der(uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, NULL, &len) != 1
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_distribution_points_to_der(const char *http_uri, size_t http_urilen,
const char *ldap_uri, size_t ldap_urilen, uint8_t **out, size_t *outlen)
{
size_t len = 0;
if ((!http_uri || !http_urilen) && (!ldap_uri || !ldap_urilen)) {
return 0;
}
if (x509_uri_as_distribution_point_to_der(http_uri, http_urilen, NULL, &len) < 0
|| x509_uri_as_distribution_point_to_der(ldap_uri, ldap_urilen, NULL, &len) < 0
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_distribution_point_to_der(http_uri, http_urilen, out, outlen) < 0
|| x509_uri_as_distribution_point_to_der(ldap_uri, ldap_urilen, out, outlen) < 0) {
error_print();
return -1;
}
return 1;
}
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen, const uint8_t **in, size_t *inlen)
int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t *dlen,
const uint8_t **in, size_t *inlen)
{
int ret;
int tag;
if ((ret = asn1_any_type_from_der(&tag, d, dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return -1;
return ret;
}
switch (tag) {
case ASN1_TAG_EXPLICIT(0):
*choice = 0;
break;
case ASN1_TAG_EXPLICIT(1):
*choice = 1;
break;
default:
error_print();
@@ -1994,6 +2020,25 @@ int x509_distribution_point_name_from_der(int *choice, const uint8_t **d, size_t
return 1;
}
int x509_uri_as_distribution_point_name_from_der(const char **uri, size_t *urilen,
const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *d;
size_t dlen;
int choice;
if ((ret = x509_distribution_point_name_from_der(&choice, &d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (choice == 0) {
*uri = (char *)d;
*urilen = dlen;
}
return 1;
}
int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
{
int tag;
@@ -2017,34 +2062,68 @@ int x509_distribution_point_name_print(FILE *fp, int fmt, int ind, const char *l
return 1;
}
// 这个如何使用?如何准备完整的数据呢?
int x509_distribution_point_to_der(
int dist_point_choice, const uint8_t *dist_point, size_t dist_point_len,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
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)
{
/*
size_t len = 0;
if (x509_explicit_distribution_point_name_to_der(0, dist_point_choice, dist_point, dist_point_len, NULL, &len) < 0
|| asn1_implicit_bits_to_der(1, reasons, NULL, &len) < 0
|| asn1_implicit_sequence_to_der(2, crl_issuer, crl_issuer_len, 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
|| asn1_implicit_bits_to_der(1, reasons, out, outlen) < 0
|| asn1_implicit_sequence_to_der(2, crl_issuer, crl_issuer_len, out, outlen) < 0) {
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_distribution_point_name_to_der(uri, urilen, NULL, &len) != 1
|| asn1_explicit_header_to_der(index, len, out, outlen) != 1
|| x509_uri_as_distribution_point_name_to_der(uri, urilen, out, outlen) != 1) {
error_print();
return -1;
}
*/
return 1;
}
int x509_distribution_point_from_der(
int *dist_point_choice, const uint8_t **dist_point, size_t *dist_point_len,
int x509_uri_as_explicit_distribution_point_name_from_der(int index,
const char **uri, size_t *urilen, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *a;
size_t alen;
if ((ret = asn1_explicit_from_der(index, &a, &alen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (x509_uri_as_distribution_point_name_from_der(uri, urilen, &a, &alen) != 1
|| asn1_length_is_zero(alen) != 1) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_to_der(const char *uri, size_t urilen,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
uint8_t **out, size_t *outlen)
{
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, NULL, &len) != 1
|| x509_revoke_reason_flags_to_der(reasons, NULL, &len) < 0
|| x509_general_names_to_der(crl_issuer, crl_issuer_len, NULL, &len) < 0
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_explicit_distribution_point_name_to_der(0, uri, urilen, out, outlen) != 1
|| x509_revoke_reason_flags_to_der(reasons, out, outlen) < 0
|| x509_general_names_to_der(crl_issuer, crl_issuer_len, out, outlen) < 0) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_point_from_der(const char **uri, size_t *urilen,
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen)
{
/*
int ret;
const uint8_t *d;
size_t dlen;
@@ -2053,14 +2132,13 @@ int x509_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_bits_from_der(1, reasons, &d, &dlen) < 0
|| asn1_implicit_sequence_from_der(2, crl_issuer, crl_issuer_len, &d, &dlen) < 0
if (x509_uri_as_explicit_distribution_point_name_from_der(0, uri, urilen, &d, &dlen) != 1
|| x509_revoke_reason_flags_from_der(reasons, &d, &dlen) < 0
|| x509_general_names_from_der(crl_issuer, crl_issuer_len, &d, &dlen) < 0
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
*/
return 1;
}
@@ -2078,7 +2156,7 @@ int x509_distribution_point_print(FILE *fp, int fmt, int ind, const char *label,
if (ret) x509_distribution_point_name_print(fp, fmt, ind, "distributionPoint", p, len);
if ((ret = asn1_implicit_bits_from_der(1, &bits, &d, &dlen)) < 0) goto err;
if (ret) x509_revoke_reasons_print(fp, fmt, ind, "reasons", bits);
if (ret) x509_revoke_reason_flags_print(fp, fmt, ind, "reasons", bits);
if ((ret = asn1_implicit_sequence_from_der(2, &p, &len, &d, &dlen)) < 0) goto err;
if (ret) x509_general_names_print(fp, fmt, ind, "cRLIssuer", p, len);
@@ -2089,9 +2167,53 @@ err:
return -1;
}
int x509_distribution_points_validate(const uint8_t *d, size_t dlen)
int x509_uri_as_distribution_points_to_der(const char *uri, size_t urilen,
int reasons, const uint8_t *crl_issuer, size_t crl_issuer_len,
uint8_t **out, size_t *outlen)
{
return -1;
size_t len = 0;
if (!uri || !urilen) {
return 0;
}
if (x509_uri_as_distribution_point_to_der(uri, urilen,
reasons, crl_issuer, crl_issuer_len, NULL, &len) < 0
|| asn1_sequence_header_to_der(len, out, outlen) != 1
|| x509_uri_as_distribution_point_to_der(uri, urilen,
reasons, crl_issuer, crl_issuer_len, out, outlen) < 0) {
error_print();
return -1;
}
return 1;
}
int x509_uri_as_distribution_points_from_der(const char **uri, size_t *urilen,
int *reasons, const uint8_t **crl_issuer, size_t *crl_issuer_len,
const uint8_t **in, size_t *inlen)
{
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;
}
*uri = NULL;
*urilen = 0;
while (dlen) {
if (x509_uri_as_distribution_point_from_der(uri, urilen, reasons, crl_issuer, crl_issuer_len, &d, &dlen) != 1) {
error_print();
return -1;
}
if (*uri) {
return 1;
}
}
return 1;
}
int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
@@ -229,51 +229,19 @@ int x509_req_sign(
return 1;
}
int x509_req_verify(const uint8_t *req, size_t reqlen, const SM2_KEY *sign_pubkey, const char *signer_id, size_t signer_id_len)
int x509_req_verify(const uint8_t *req, size_t reqlen, const char *signer_id, size_t signer_id_len)
{
int ret;
const uint8_t *d;
size_t dlen;
const uint8_t *p;
size_t len;
const uint8_t *req_info;
size_t req_info_len;
int signature_algor;
const uint8_t *sig;
size_t siglen;
SM2_SIGN_CTX sign_ctx;
SM2_KEY public_key;
if (asn1_sequence_from_der(&d, &dlen, &req, &reqlen) != 1
|| asn1_length_is_zero(reqlen) != 1) {
if (x509_req_get_details(req, reqlen, NULL, NULL, NULL, &public_key, NULL, NULL, NULL, NULL, NULL) != 1) {
error_print();
return -1;
}
req_info = d;
req_info_len = dlen;
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) {
if (x509_signed_verify(req, reqlen, &public_key, signer_id, signer_id_len) != 1) {
error_print();
return -1;
}
req_info_len -= dlen;
if (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;
}
if (signature_algor != OID_sm2sign_with_sm3) {
error_print();
return -1;
}
if (sm2_verify_init(&sign_ctx, sign_pubkey, signer_id, signer_id_len) != 1
|| sm2_verify_update(&sign_ctx, req_info, req_info_len) != 1
|| (ret = sm2_verify_finish(&sign_ctx, sig, siglen)) != 1) {
error_print();
return -1;
}
return ret;
return 1;
}
int x509_req_get_details(const uint8_t *req, size_t reqlen,
@@ -343,3 +311,50 @@ int x509_req_from_pem(uint8_t *req, size_t *reqlen, size_t maxlen, FILE *fp)
}
return 1;
}
#include <gmssl/file.h>
int x509_req_new_from_pem(uint8_t **out, size_t *outlen, FILE *fp)
{
uint8_t *req;
size_t reqlen;
size_t maxlen;
if (!out || !outlen || !fp) {
error_print();
return -1;
}
if (file_size(fp, &maxlen) != 1) {
error_print();
return -1;
}
if (!(req = malloc(maxlen))) {
error_print();
return -1;
}
if (x509_req_from_pem(req, &reqlen, maxlen, fp) != 1) {
free(req);
error_print();
return -1;
}
*out = req;
*outlen = reqlen;
return 1;
}
int x509_req_new_from_file(uint8_t **req, size_t *reqlen, const char *file)
{
FILE *fp = NULL;
if (!(fp = fopen(file, "rb"))) {
error_print();
return -1;
}
if (x509_req_new_from_pem(req, reqlen, fp) != 1) {
error_print();
fclose(fp);
return -1;
}
fclose(fp);
return 1;
}

View File

@@ -720,19 +720,19 @@ static int test_x509_revoke_reasons(void)
int i;
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
if (x509_revoke_reasons_to_der(tests[i], &p, &len) != 1) {
if (x509_revoke_reason_flags_to_der(tests[i], &p, &len) != 1) {
error_print();
return -1;
}
format_bytes(stderr, 0, 4, "", buf, len);
}
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
if (x509_revoke_reasons_from_der(&bits, &cp, &len) != 1
if (x509_revoke_reason_flags_from_der(&bits, &cp, &len) != 1
|| asn1_check(bits == tests[i]) != 1) {
error_print();
return -1;
}
x509_revoke_reasons_print(stderr, 0, 4, "ReasonFlags", bits);
x509_revoke_reason_flags_print(stderr, 0, 4, "ReasonFlags", bits);
}
(void)asn1_length_is_zero(len);

View File

@@ -173,7 +173,7 @@ static int test_x509_req(void)
error_print();
return -1;
}
if (x509_req_verify(req, reqlen, &sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
if (x509_req_verify(req, reqlen, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
error_print();
return -1;
}

View File

@@ -16,6 +16,7 @@
#include <gmssl/rand.h>
#include <gmssl/pkcs8.h>
#include <gmssl/error.h>
#include <gmssl/hex.h>
#include <gmssl/x509.h>
#include <gmssl/x509_oid.h>
#include <gmssl/x509_ext.h>
@@ -23,8 +24,10 @@
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str"
" -serial_len num"
" -days num"
" -key file -pass pass"
" -key pem -pass pass"
" [-sm2_id str | -sm2_id_hex hex]"
" [-gen_authority_key_id]"
" [-gen_subject_key_id]"
" [-key_usage str]*"
@@ -35,7 +38,7 @@ static const char *options =
" [-crl_http_uri uri] [-crl_ldap_uri uri]"
" [-inhibit_any_policy num]"
" [-ca_issuers_uri uri] [-ocsp_uri uri uri]"
" [-out file]";
" [-out pem]";
static char *usage =
"Options\n"
@@ -44,6 +47,12 @@ static char *usage =
" -days num Validity peroid in days\n"
" -key file Private key file in PEM format\n"
" -pass pass Password for decrypting private key file\n"
" -sm2_id str Signer's ID in SM2 signature algorithm\n"
" -sm2_id_hex hex Signer's ID in hex format\n"
" When `-sm2_id` or `-sm2_id_hex` is specified,\n"
" must use the same ID in other commands explicitly.\n"
" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n"
" the default string '1234567812345678' is used\n"
" -out file Output certificate file in PEM format\n"
"\n"
" Subject and Issuer options\n"
@@ -62,15 +71,15 @@ static char *usage =
" -key_usage str Add KeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" digitalSignature\n"
" nonRepudiation\n"
" keyEncipherment\n"
" dataEncipherment\n"
" keyAgreement\n"
" keyCertSign\n"
" cRLSign\n"
" encipherOnly\n"
" decipherOnly\n"
" * digitalSignature\n"
" * nonRepudiation\n"
" * keyEncipherment\n"
" * dataEncipherment\n"
" * keyAgreement\n"
" * keyCertSign\n"
" * cRLSign\n"
" * encipherOnly\n"
" * decipherOnly\n"
" -subject_dns_name str Add DNS name to SubjectAltName extension\n"
" this option can be called multi-times\n"
" -issuer_dns_name str Add DNS name to IssuerAltName extension\n"
@@ -80,13 +89,13 @@ static char *usage =
" -ext_key_usage str Set ExtKeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" anyExtendedKeyUsage\n"
" serverAuth\n"
" clientAuth\n"
" codeSigning\n"
" emailProtection\n"
" timeStamping\n"
" OCSPSigning\n"
" * anyExtendedKeyUsage\n"
" * serverAuth\n"
" * clientAuth\n"
" * codeSigning\n"
" * emailProtection\n"
" * timeStamping\n"
" * OCSPSigning\n"
" -crl_http_uri uri Set HTTP URI of CRL of CRLDistributionPoints extension\n"
" -crl_ldap_uri uri Set LDAP URI of CRL of CRLDistributionPoints extension\n"
" -inhibit_any_policy num Set skipCerts number of InhibitAnyPolicy extension\n"
@@ -95,6 +104,8 @@ static char *usage =
"\n"
"Examples\n"
"\n"
" gmssl sm2keygen -pass P@ssw0rd -out rootcakey.pem\n"
"\n"
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n"
" -key rootcakey.pem -pass P@ssw0rd \\\n"
" -ca -path_len_constraints 6 \\\n"
@@ -142,10 +153,11 @@ int certgen_main(int argc, char **argv)
time_t not_after;
// Private Key
char *keyfile = NULL;
char *pass = NULL;
FILE *keyfp = NULL;
char *pass = NULL;
SM2_KEY sm2_key;
char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t signer_id_len = 0;
uint8_t cert[4096];
size_t certlen;
@@ -204,14 +216,14 @@ int certgen_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: gmssl %s %s\n\n", prog, options);
printf(usage, prog);
printf("%s\n", usage);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-serial_len")) {
if (--argc < 1) goto bad;
serial_len = atoi(*(++argv));
if (serial_len <= 0 || serial_len > sizeof(serial)) {
fprintf(stderr, "%s: invalid '-serial_len' value, need a number less than %zu\n", prog, sizeof(serial));
fprintf(stderr, "%s: invalid `-serial_len` value, need a number less than %zu\n", prog, sizeof(serial));
goto end;
}
} else if (!strcmp(*argv, "-CN")) {
@@ -246,15 +258,35 @@ int certgen_main(int argc, char **argv)
} 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));
str = *(++argv);
if (!(keyfp = fopen(str, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-pass")) {
if (--argc < 1) goto bad;
pass = *(++argv);
} else if (!strcmp(*argv, "-sm2_id")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > sizeof(signer_id) - 1) {
fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog);
goto end;
}
strncpy(signer_id, str, sizeof(signer_id));
signer_id_len = strlen(str);
} else if (!strcmp(*argv, "-sm2_id_hex")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > (sizeof(signer_id) - 1) * 2) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog);
goto end;
}
if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-gen_authority_key_id")) {
gen_authority_key_id = 1;
} else if (!strcmp(*argv, "-gen_subject_key_id")) {
@@ -287,7 +319,7 @@ int certgen_main(int argc, char **argv)
} else if (!strcmp(*argv, "-path_len_constraints")) {
if (--argc < 1) goto bad;
path_len_constraints = atoi(*(++argv));
if (path_len_constraints <= 0) {
if (path_len_constraints < 0) {
fprintf(stderr, "%s: invalid `-path_len_constraints` value\n", prog);
goto end;
}
@@ -344,24 +376,33 @@ bad:
if (!common_name) {
fprintf(stderr, "%s: option `-CN` required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!days) {
fprintf(stderr, "%s: option `-days` required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!keyfile) {
if (!keyfp) {
fprintf(stderr, "%s: option `-key` required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: option `-pass` required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
fprintf(stderr, "%s: load private key failed\n", prog);
goto end;
}
if (!signer_id_len) {
strcpy(signer_id, SM2_DEFAULT_ID);
signer_id_len = strlen(SM2_DEFAULT_ID);
}
// Serial
if (rand_bytes(serial, sizeof(serial)) != 1) {
@@ -418,7 +459,7 @@ bad:
}
}
// no SubjectDirectoryAttributes
if (path_len_constraints) {
if (ca >= 0 || path_len_constraints >= 0) {
if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts),
X509_critical, ca, path_len_constraints) != 1) {
fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog);
@@ -440,7 +481,6 @@ bad:
crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0,
crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) {
fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog);
error_print();
return -1;
}
}
@@ -463,7 +503,7 @@ bad:
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
X509_version_v3,
serial, sizeof(serial),
serial, serial_len,
OID_sm2sign_with_sm3,
name, namelen,
not_before, not_after,
@@ -472,7 +512,7 @@ bad:
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
&sm2_key, signer_id, signer_id_len) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
@@ -16,7 +16,20 @@
#include <gmssl/x509.h>
static const char *options = "[-in file] [-out file]";
static const char *options = "[-in pem] [-out file]";
static char *usage =
"Options\n"
"\n"
" [-in pem]|stdin Input certificates in PEM format.\n"
" This command supports continuous multiple certificates\n"
" Do not include blank line or comments between PEM data\n"
" [-out file]stdout Output file\n"
"\n"
"Examples\n"
"\n"
" gmssl certparse -in certs.pem\n"
"\n";
int certparse_main(int argc, char **argv)
{
@@ -34,7 +47,8 @@ int certparse_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
printf("usage: gmssl %s %s\n\n", prog, options);
printf("%s\n", usage);
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
@@ -51,10 +65,10 @@ int certparse_main(int argc, char **argv)
goto end;
}
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
goto end;
}

View File

@@ -16,90 +16,99 @@
#include <gmssl/x509.h>
#include <gmssl/x509_crl.h>
// 20220105Z
static const char *options = "-in cert.pem [-reason str] [-invalid_date timestamp] [-out RevokedCertificate.der]";
static const char *options =
" -in pem"
" [-reason str]"
" [-invalid_date time]"
" [-out 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");
static char *usage =
"Options\n"
"\n"
" -in pem Certificate in PEM format to be revoked\n"
" -reason str Revocation reason code, avaiable codes:\n"
" * unspecified\n"
" * keyCompromise\n"
" * cACompromise\n"
" * affiliationChanged\n"
" * superseded\n"
" * cessationOfOperation\n"
" * certificateHold\n"
" * notAssigned\n"
" * removeFromCRL\n"
" * privilegeWithdrawn\n"
" * aACompromise\n"
" -invalid_date time The date on which it is known or suspected the certificate became invalid\n"
" Time in `YYYYMMDDHHMMSSZ` format such as 20221231000000Z\n"
" The last 'Z' means it is Zulu (GMT) time\n"
" -out der | stdout Output X.509 RevokedCertificate in DER-encoding\n"
" This file stores multiple RevokedCertificates, used as input by `crlsign`\n"
"\n"
"Examples\n"
"\n"
" gmssl certrevoke -in cert1.pem -reason keyCompromise -invalid_date 20221230000000Z -out revoked_certs.der\n"
" gmssl certrevoke -in cert1.pem -reason keyCompromise -invalid_date 20221230000000Z >> revoked_certs.der\n"
"\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;
char *str;
uint8_t *cert = NULL;
size_t certlen;
int reason = -1;
time_t invalid_date = -1;
char *outfile = NULL;
FILE *outfp = stdout;
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);
printf("usage: gmssl %s %s\n\n", prog, options);
printf("%s", usage);
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);
str = *(++argv);
if (x509_cert_new_from_file(&cert, &certlen, str) != 1) {
fprintf(stderr, "%s: open cert file '%s' failure\n", prog, str);
goto end;
}
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
outfile = *(++argv);
if (!(outfp = fopen(outfile, "wb"))) {
if (!(outfp = fopen(outfile, "ab"))) {
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));
}
str = *(++argv);
if (x509_crl_reason_from_name(&reason, str) != 1) {
fprintf(stderr, "%s: invalid reason '%s'\n", prog, str);
goto end;
}
} 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;
str =*(++argv);
if (asn1_time_from_str(0, &invalid_date, str) != 1) {
fprintf(stderr, "%s: invalid time '%s', should in 'YYYYMMDDHHMMSSZ' format\n", prog, str);
goto end;
}
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
goto end;
}
@@ -107,8 +116,9 @@ bad:
argv++;
}
if (!infile) {
fprintf(stderr, "usage: %s %s\n", prog, options);
if (!cert) {
fprintf(stderr, "%s: option `-in` missing\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (x509_cert_revoke_to_der(cert, certlen, time(NULL), reason, invalid_date, NULL, 0, NULL, &outlen) != 1) {

View File

@@ -12,52 +12,76 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/hex.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/x509_ext.h>
#include <gmssl/x509_crl.h>
#include <gmssl/file.h>
#include <gmssl/error.h>
static const char *usage = "-in revoked_certs.der -key pem -pass str -cacert pem [-next_update time] "
"[-gen_authority_key_id] [-crl_num num] [-delta_crl_indicator num] [-ca_issuers_uri uri] [-ocsp_uri uri] [-out crl.der]";
static void print_options(const char *prog)
{
printf("Options\n");
printf("\n");
printf(" -in revoked_certs.der To be revoked certificate list\n");
printf(" This input file format is DER-encoding of SEQUENCE OF RevokedCertificate\n");
printf(" revoked_certs.der can be generated by `gmssl certrevoke`\n");
printf("\n");
printf(" -key pkcs8.pem The issuer private key.\n");
printf("\n");
printf(" -cacert cert.pem The issuer certificate.\n");
printf("\n");
printf(" -next_update time Optional CRL attribute.\n");
printf("\n");
printf(" -out crl.der Output CRL in DER-encoding\n");
}
static const char *usage =
" -in revoked_certs"
" -cacert pem -key pem -pass pass [-sm2_id str | -sm2_id_hex hex]"
" [-next_update time] "
" [-gen_authority_key_id]"
" [-crl_num num]"
" [-delta_crl_indicator num]"
" [-ca_issuers_uri uri]"
" [-ocsp_uri uri]"
" [-out der]\n";
static const char *options =
"Options\n"
"\n"
" -in revoked_certs To be revoked certificate list\n"
" This input file format is DER-encoding of SEQUENCE OF RevokedCertificate\n"
" revoked_certs.der can be generated by `gmssl certrevoke`\n"
" -cacert pem The issuer certificate\n"
" -key pem The issuer private key\n"
" -pass pass Password for decrypting private key file\n"
" -sm2_id str Authority's ID in SM2 signature algorithm\n"
" -sm2_id_hex hex Authority's ID in hex format\n"
" When `-sm2_id` or `-sm2_id_hex` is specified,\n"
" must use the same ID in other commands explicitly.\n"
" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n"
" the default string '1234567812345678' is used\n"
" -next_update time Optional CRL attribute\n"
" -out der | stdout Output CRL in DER-encoding\n"
"\n"
"Examples\n"
"\n"
" gmssl crlgen -in revoked_certs.der -cacert cacert.pem -key cakey.pem -pass P@ssw0rd -gen_authority_key_id -crl_num 1\n"
" gmssl crlgen -in revoked_certs.der -cacert cacert.pem -key cakey.pem -pass P@ssw0rd -gen_authority_key_id -crl_num 2\n"
"\n";
int crlgen_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
char *str;
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 *outbuf = NULL;
uint8_t *out;
size_t outlen = 0;
uint8_t *cacert = NULL;
size_t cacert_len = 0;
FILE *keyfp = NULL;
char *pass = NULL;
SM2_KEY sign_key;
char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t signer_id_len = 0;
const uint8_t *issuer;
size_t issuer_len;
time_t this_update = time(NULL);
time_t next_update = -1;
uint8_t exts[512];
@@ -70,25 +94,21 @@ int crlgen_main(int argc, char **argv)
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
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, usage);
printf("\n");
print_options(prog);
printf("usage: %s %s\n\n", prog, usage);
printf("%s\n", options);
ret = 0;
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);
str = *(++argv);
if (file_read_all(str, &revoked_certs, &revoked_certs_len) != 1) {
fprintf(stderr, "%s: read input file '%s' failed\n", prog, str);
goto end;
}
} else if (!strcmp(*argv, "-out")) {
@@ -98,25 +118,51 @@ int crlgen_main(int argc, char **argv)
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-cacert")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_cert_new_from_file(&cacert, &cacert_len, str) != 1) {
fprintf(stderr, "%s: open certificate '%s' failure\n", prog, str);
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));
str = *(++argv);
if (!(keyfp = fopen(str, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-pass")) {
if (--argc < 1) goto bad;
} else if (!strcmp(*argv, "-cacert")) {
pass = *(++argv);
} else if (!strcmp(*argv, "-sm2_id")) {
if (--argc < 1) goto bad;
cacertfile = *(++argv);
if (x509_cert_new_from_file(&cacert, &cacert_len, cacertfile) != 1) {
str = *(++argv);
if (strlen(str) > sizeof(signer_id) - 1) {
fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog);
goto end;
}
strncpy(signer_id, str, sizeof(signer_id));
signer_id_len = strlen(str);
} else if (!strcmp(*argv, "-sm2_id_hex")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > (sizeof(signer_id) - 1) * 2) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog);
goto end;
}
if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-next_update")) {
if (--argc < 1) goto bad;
if (asn1_time_from_str(0, &next_update, *(++argv)) != 1) {
fprintf(stderr, "%s: invalid time format for '-next_update', should be 'YYYYMMDDHHMMSSZ'\n", prog);
str = *(++argv);
if (asn1_time_from_str(0, &next_update, str) != 1) {
fprintf(stderr, "%s: invalid time '%s' for `-next_update`\n", prog, str);
goto bad;
}
} else if (!strcmp(*argv, "-gen_authority_key_id")) {
@@ -139,10 +185,10 @@ int crlgen_main(int argc, char **argv)
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
fprintf(stderr, "%s: illegal option `%s`\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
goto end;
}
@@ -150,56 +196,78 @@ bad:
argv++;
}
if (!infile) {
fprintf(stderr, "%s: '-in' option required\n", prog);
if (!revoked_certs) {
fprintf(stderr, "%s: `-in` option required\n", prog);
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
goto end;
} else {
const uint8_t *d = revoked_certs;
size_t dlen = revoked_certs_len;
const uint8_t *serial;
size_t serial_len;
time_t revoke_date;
const uint8_t *exts;
size_t exts_len;
while (dlen) {
if (x509_revoked_cert_from_der(&serial, &serial_len, &revoke_date, &exts, &exts_len, &d, &dlen) != 1) {
fprintf(stderr, "%s: invalid input\n", prog);
goto end;
}
format_bytes(stderr, 0, 4, "Revoked Certificate SN", serial, serial_len);
}
}
if (!cacert) {
fprintf(stderr, "%s: `-cacert` option required\n", prog);
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
goto end;
}
if (!cacertfile) {
fprintf(stderr, "%s: '-cacert' option required\n", prog);
goto end;
}
if (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
if (!keyfp) {
fprintf(stderr, "%s: `-key` option required\n", prog);
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
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, usage);
goto end;
}
if (x509_cert_get_subject(cacert, cacert_len, &issuer, &issuer_len) != 1) {
fprintf(stderr, "%s: parse CA certificate failure\n", prog);
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
fprintf(stderr, "%s: `-pass` option required\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 (!signer_id_len) {
strcpy(signer_id, SM2_DEFAULT_ID);
signer_id_len = strlen(SM2_DEFAULT_ID);
}
if (x509_cert_get_subject(cacert, cacert_len, &issuer, &issuer_len) != 1) {
fprintf(stderr, "%s: parse CA certificate failure\n", prog);
goto end;
}
// Extensions
if (gen_authority_key_id) {
if (x509_crl_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sign_key) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
}
if (x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), -1, crl_num) < 0
|| x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), X509_critical, delta_crl_indicator) < 0) {
fprintf(stderr, "%s: inner error\n", prog);
if (x509_crl_exts_add_crl_number(exts, &extslen, sizeof(exts), -1, crl_num) < 0) {
fprintf(stderr, "%s: add CRLNumber error\n", prog);
goto end;
}
if (x509_crl_exts_add_delta_crl_indicator(exts, &extslen, sizeof(exts), X509_critical, delta_crl_indicator) < 0) {
fprintf(stderr, "%s: add DeltaCRLIndicator error\n", prog);
goto end;
}
if (ca_issuers_uri || ocsp_uri) {
if (x509_crl_exts_add_authority_info_acess(exts, &extslen, sizeof(exts), -1,
ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0,
ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
fprintf(stderr, "%s: add AuthorityInfoAccess error\n", prog);
goto end;
}
}
@@ -207,7 +275,7 @@ bad:
if (x509_crl_exts_add_freshest_crl(exts, &extslen, sizeof(exts), -1,
http_uri, http_uri ? strlen(http_uri) : 0,
ldap_uri, ldap_uri ? strlen(ldap_uri) : 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
fprintf(stderr, "%s: add FreshestCRL error\n", prog);
goto end;
}
}
@@ -216,16 +284,32 @@ bad:
X509_version_v2,
OID_sm2sign_with_sm3,
issuer, issuer_len,
time(NULL), next_update,
this_update, next_update,
revoked_certs, revoked_certs_len,
extslen ? exts : NULL, extslen,
&sign_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH,
&out, &outlen) != 1) {
// error_print();
return -1;
&sign_key, signer_id, signer_id_len,
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_crl_sign_to_der(
X509_version_v2,
OID_sm2sign_with_sm3,
issuer, issuer_len,
this_update, next_update,
revoked_certs, revoked_certs_len,
extslen ? exts : NULL, extslen,
&sign_key, signer_id, signer_id_len,
&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);
return -1;
@@ -233,7 +317,10 @@ bad:
ret = 0;
end:
//if (cert) free(cert);
if (revoked_certs) free(revoked_certs);
if (keyfp) fclose(keyfp);
if (cacert) free(cacert);
if (outfile && outfp) fclose(outfp);
if (outbuf) free(outbuf);
return ret;
}

91
tools/crlget.c Normal file
View File

@@ -0,0 +1,91 @@
/*
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/http.h>
static const char *usage = "[-in pem] [-out file]\n";
static const char *options =
"Options\n"
"\n"
" -in pem | stdin Input certificates in PEM format.\n"
" -out der | stdout Output CRL file in DER-encoding\n"
"\n"
"Examples\n"
"\n"
" gmssl crlget -in cert.pem -out crl.der\n"
"\n";
int certparse_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
char *outfile = NULL;
FILE *infp = stdin;
FILE *outfp = stdout;
uint8_t cert[18192];
size_t certlen;
argc--;
argv++;
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: gmssl %s %s\n\n", prog, options);
printf("%s\n", usage);
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
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 {
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 (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1) {
goto end;
}
if (x509_cert_get_exts(cert, certlen, &exts, &extslen) != 1) {
goto end;
}
if (x509_exts_get_ext_by_oid(exts, extslen, OID_ce_crl_
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2022 The GmSSL Project. All Rights Reserved.
* Copyright 2014-2023 The GmSSL Project. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
@@ -13,37 +13,77 @@
#include <string.h>
#include <stdlib.h>
#include <gmssl/mem.h>
#include <gmssl/hex.h>
#include <gmssl/rand.h>
#include <gmssl/pkcs8.h>
#include <gmssl/x509.h>
#include <gmssl/x509_req.h>
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num"
" -key file [-pass pass] [-out file]";
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str"
" -key pem -pass pass"
" [-sm2_id str | -sm2_id_hex hex]"
" [-out pem]";
static char *usage =
"Options\n"
"\n"
" -key file Private key file in PEM format\n"
" -pass pass Password for decrypting private key file\n"
" -sm2_id str Signer's ID in SM2 signature algorithm\n"
" -sm2_id_hex hex Signer's ID in hex format\n"
" When `-sm2_id` or `-sm2_id_hex` is specified,\n"
" must use the same ID in other commands explicitly.\n"
" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n"
" the default string '1234567812345678' is used\n"
" -out file Output Certificate Request (CSR) file in PEM format\n"
"\n"
" Subject options\n"
"\n"
" -C str Country\n"
" -ST str State or province name\n"
" -L str Locality\n"
" -O str Organization\n"
" -OU str Organizational unit\n"
" -CN str Common name\n"
"\n"
"Examples\n"
"\n"
" gmssl sm2keygen -pass P@ssw0rd -out key.pem\n"
" gmssl reqgen -CN www.gmssl.org -key key.pem -pass P@ssw0rd -out req.pem\n"
"\n";
int reqgen_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *str;
// Subject
uint8_t name[256];
size_t namelen = 0;
char *country = NULL;
char *state = NULL;
char *locality = NULL;
char *org = NULL;
char *org_unit = NULL;
char *common_name = NULL;
int days = 0;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
uint8_t name[256];
size_t namelen = 0;
// Private Key
FILE *keyfp = NULL;
char *pass = NULL;
SM2_KEY sm2_key;
char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t signer_id_len = 0;
// Output
char *outfile = NULL;
FILE *outfp = stdout;
uint8_t req[1024];
size_t reqlen = 0;
SM2_KEY sm2_key;
argc--;
argv++;
@@ -55,7 +95,8 @@ int reqgen_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
printf("usage: gmssl %s %s\n\n", prog, options);
printf("%s\n", usage);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-C")) {
@@ -76,23 +117,38 @@ int reqgen_main(int argc, char **argv)
} else if (!strcmp(*argv, "-CN")) {
if (--argc < 1) goto bad;
common_name = *(++argv);
} else if (!strcmp(*argv, "-days")) {
if (--argc < 1) goto bad;
days = atoi(*(++argv));
if (days <= 0) {
fprintf(stderr, "%s: invalid '-days' value\n", prog);
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));
str = *(++argv);
if (!(keyfp = fopen(str, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-pass")) {
if (--argc < 1) goto bad;
pass = *(++argv);
} else if (!strcmp(*argv, "-sm2_id")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > sizeof(signer_id) - 1) {
fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog);
goto end;
}
strncpy(signer_id, str, sizeof(signer_id));
signer_id_len = strlen(str);
} else if (!strcmp(*argv, "-sm2_id_hex")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > (sizeof(signer_id) - 1) * 2) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog);
goto end;
}
if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
outfile = *(++argv);
@@ -104,7 +160,7 @@ int reqgen_main(int argc, char **argv)
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
fprintf(stderr, "%s: `%s` option value missing\n", prog, *argv);
goto end;
}
@@ -113,19 +169,18 @@ bad:
}
if (!common_name) {
fprintf(stderr, "%s: '-CN' option required\n", prog);
fprintf(stderr, "%s: `-CN` option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!days) {
fprintf(stderr, "%s: '-days' option required\n", prog);
goto end;
}
if (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
if (!keyfp) {
fprintf(stderr, "%s: `-key` option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
fprintf(stderr, "%s: `-pass` option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
@@ -133,16 +188,23 @@ bad:
fprintf(stderr, "%s: load private key failed\n", prog);
goto end;
}
if (!signer_id_len) {
strcpy(signer_id, SM2_DEFAULT_ID);
signer_id_len = strlen(SM2_DEFAULT_ID);
}
if (x509_name_set(name, &namelen, sizeof(name),
country, state, locality, org, org_unit, common_name) != 1
|| x509_req_sign(req, &reqlen, sizeof(req),
X509_version_v1,
name, namelen,
&sm2_key,
NULL, 0,
OID_sm2sign_with_sm3,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
if (x509_name_set(name, &namelen, sizeof(name), country, state, locality, org, org_unit, common_name) != 1) {
fprintf(stderr, "%s: set Subject Name error\n", prog);
goto end;
}
if (x509_req_sign(req, &reqlen, sizeof(req),
X509_version_v1,
name, namelen,
&sm2_key,
NULL, 0,
OID_sm2sign_with_sm3,
&sm2_key, signer_id, signer_id_len) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}

View File

@@ -12,16 +12,123 @@
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/hex.h>
#include <gmssl/mem.h>
#include <gmssl/rand.h>
#include <gmssl/x509.h>
#include <gmssl/x509_ext.h>
#include <gmssl/x509_req.h>
#include <gmssl/x509_oid.h>
static const char *options = "[-in pem] -days num -cacert pem -key pem [-pass str] [-out pem] "
"-key_usage oid -path_len_constraint num -crl_uri uri "
"-ca_issuers_uri uri -ocsp_uri uri\n";
static const char *options =
" [-in pem]"
" [-req_sm2_id str | -req_sm2_id_hex hex]"
" [-serial_len num]"
" -days num"
" -cacert pem -key file -pass pass"
" [-sm2_id str | -sm2_id_hex hex]"
" [-gen_authority_key_id]"
" [-gen_subject_key_id]"
" [-key_usage str]*"
" [-subject_dns_name str]*"
" [-issuer_dns_name str]*"
" [-ca -path_len_constraints num]"
" [-ext_key_usage str]*"
" [-crl_http_uri uri] [-crl_ldap_uri uri]"
" [-inhibit_any_policy num]"
" [-ca_issuers_uri uri] [-ocsp_uri uri uri]"
" [-out pem]";
static char *usage =
"Options\n"
"\n"
" -in pem Input CSR file in PEM format\n"
" -req_sm2_id str CSR Owner's ID in SM2 signature algorithm\n"
" -req_sm2_id_hex hex CSR Owner's ID in hex format\n"
" When `-req_sm2_id` or `-req_sm2_id_hex` is specified,\n"
" must use the same ID in other commands explicitly.\n"
" If neither `-req_sm2_id` nor `-req_sm2_id_hex` is specified,\n"
" the default string '1234567812345678' is used\n"
" -serial_len num Serial number length in bytes\n"
" -days num Validity peroid in days\n"
" -cacert pem Issuer CA certificate\n"
" -key pem Issuer private key file in PEM format\n"
" -sm2_id str Authority's ID in SM2 signature algorithm\n"
" -sm2_id_hex hex Authority's ID in hex format\n"
" When `-sm2_id` or `-sm2_id_hex` is specified,\n"
" must use the same ID in other commands explicitly.\n"
" If neither `-sm2_id` nor `-sm2_id_hex` is specified,\n"
" the default string '1234567812345678' is used\n"
" -pass pass Password for decrypting private key file\n"
" -out pem Output certificate file in PEM format\n"
"\n"
" Extension options\n"
"\n"
" -gen_authority_key_id Generate AuthorityKeyIdentifier extension use SM3\n"
" -gen_subject_key_id Generate SubjectKeyIdentifier extension use SM3\n"
" -key_usage str Add KeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" digitalSignature\n"
" nonRepudiation\n"
" keyEncipherment\n"
" dataEncipherment\n"
" keyAgreement\n"
" keyCertSign\n"
" cRLSign\n"
" encipherOnly\n"
" decipherOnly\n"
" -subject_dns_name str Add DNS name to SubjectAltName extension\n"
" this option can be called multi-times\n"
" -issuer_dns_name str Add DNS name to IssuerAltName extension\n"
" this option can be called multi-times\n"
" -ca Set cA of BasicConstaints extension\n"
" -path_len_constraints num Set pathLenConstaints of BasicConstaints extension\n"
" -ext_key_usage str Set ExtKeyUsage extension\n"
" this option can be called multi-times\n"
" avaiable values:\n"
" anyExtendedKeyUsage\n"
" serverAuth\n"
" clientAuth\n"
" codeSigning\n"
" emailProtection\n"
" timeStamping\n"
" OCSPSigning\n"
" -crl_http_uri uri Set HTTP URI of CRL of CRLDistributionPoints extension\n"
" -crl_ldap_uri uri Set LDAP URI of CRL of CRLDistributionPoints extension\n"
" -inhibit_any_policy num Set skipCerts number of InhibitAnyPolicy extension\n"
" -ca_issuers_uri uri Set URI of the CA certificate in DER-encoding o FreshestCRL extension\n"
" -ocsp_uri uri Set OCSP URI of FreshestCRL extension\n"
"\n"
"Examples\n"
"\n"
" # Generate self-signed root CA certificate\n"
"\n"
" gmssl sm2keygen -pass P@ssw0rd -out rootcakey.pem\n"
" gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN ROOTCA -days 3650 \\\n"
" -key rootcakey.pem -pass P@ssw0rd \\\n"
" -ca -path_len_constraints 6 \\\n"
" -key_usage keyCertSign -key_usage cRLSign \\\n"
" -crl_http_uri http://pku.edu.cn/ca.crl \\\n"
" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n"
" -out rootcacert.pem\n"
"\n"
" # Generate sub-CA certificate request\n"
"\n"
" gmssl sm2keygen -pass P@ssw0rd -out cakey.pem\n"
" gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN CA -key cakey.pem -pass P@ssw0rd -out careq.pem\n"
"\n"
" # Sign certificate request to generate sub-CA certificate\n"
"\n"
" gmssl reqsign -in careq.pem -serial_len 12 -days 365 \\\n"
" -cacert rootcacert.pem -key rootcakey.pem -pass P@ssw0rd \\\n"
" -ca -path_len_constraints 0 \\\n"
" -key_usage keyCertSign -key_usage cRLSign \\\n"
" -crl_http_uri http://pku.edu.cn/ca.crl \\\n"
" -ca_issuers_uri http://pku.edu.cn/ca.crt -ocsp_uri http://ocsp.pku.edu.cn \\\n"
" -out cacert.pem\n"
"\n";
static int ext_key_usage_set(int *usages, const char *usage_name)
{
@@ -37,42 +144,89 @@ int reqsign_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
int days = 0;
char *crl_uri = NULL;
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
char *cacertfile = NULL;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
FILE *infp = stdin;
FILE *cacertfp = NULL;
FILE *keyfp = NULL;
FILE *outfp = stdout;
char *str;
// Input Req/CSR
char *infile = NULL;
FILE *infp = stdin;
uint8_t req[512];
size_t reqlen;
char req_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t req_id_len = 0;
// SerialNumber
uint8_t serial[20];
int serial_len = 12;
// Validity
int days = 0;
time_t not_before;
time_t not_after;
// Subject from Req
const uint8_t *subject;
size_t subject_len;
SM2_KEY subject_public_key;
uint8_t cacert[1024];
// CA certficate and Private Key
uint8_t *cacert = NULL;
size_t cacertlen;
FILE *keyfp = NULL;
char *pass = NULL;
SM2_KEY sm2_key;
char signer_id[SM2_MAX_ID_LENGTH + 1] = {0};
size_t signer_id_len = 0;
// Issuer from CA certificate
const uint8_t *issuer;
size_t issuer_len;
SM2_KEY issuer_public_key;
SM2_KEY sm2_key;
uint8_t cert[1024];
// Output
char *outfile = NULL;
FILE *outfp = stdout;
uint8_t cert[4096];
size_t certlen;
uint8_t serial[12];
time_t not_before, not_after;
uint8_t exts[512];
// Extensions
uint8_t exts[4096];
size_t extslen = 0;
// AuthorityKeyIdentifier
int gen_authority_key_id = 0;
// SubjectKeyIdentifier
int gen_subject_key_id = 0;
// KeyUsage
int key_usage = 0;
int path_len_constraint = -1;
// SubjectAltName
uint8_t subject_alt_name[2048];
size_t subject_alt_name_len = 0;
// IssuerAltName
uint8_t issuer_alt_name[512];
size_t issuer_alt_name_len = 0;
// BasicConstraints
int ca = -1;
int path_len_constraints = -1;
// ExtKeyUsageSyntax
int ext_key_usages[12];
size_t ext_key_usages_cnt = 0;
// CRLDistributionPoints
char *crl_http_uri = NULL;
char *crl_ldap_uri = NULL;
// InhibitAnyPolicy
int inhibit_any_policy = -1;
// FreshestCRL
char *ca_issuers_uri = NULL;
char *ocsp_uri = NULL;
argc--;
argv++;
@@ -84,62 +238,38 @@ int reqsign_main(int argc, char **argv)
while (argc >= 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
printf("usage: gmssl %s %s\n\n", prog, options);
printf("%s\n", usage);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-days")) {
} else if (!strcmp(*argv, "-req_sm2_id")) {
if (--argc < 1) goto bad;
days = atoi(*(++argv));
if (days <= 0) {
fprintf(stderr, "%s: invalid '-days' value\n", prog);
str = *(++argv);
if (strlen(str) > sizeof(req_id) - 1) {
fprintf(stderr, "%s: invalid `-req_sm2_id` length\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-key_usage")) {
strncpy(req_id, str, sizeof(req_id));
req_id_len = strlen(str);
} else if (!strcmp(*argv, "-req_sm2_id_hex")) {
if (--argc < 1) goto bad;
if (ext_key_usage_set(&key_usage, *(++argv)) != 1) {
fprintf(stderr, "%s: set KeyUsage extenstion failure\n", prog);
str = *(++argv);
if (strlen(str) > (sizeof(req_id) - 1) * 2) {
fprintf(stderr, "%s: invalid `-req_sm2_id_hex` length\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-path_len_constraint")) {
if (--argc < 1) goto bad;
path_len_constraint = atoi(*(++argv));
if (path_len_constraint < 0) {
fprintf(stderr, "%s: invalid value for '-path_len_constraint'\n", prog);
if (hex_to_bytes(str, strlen(str), (uint8_t *)req_id, &req_id_len) != 1) {
fprintf(stderr, "%s: invalid `-req_sm2_id_hex` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-crl_uri")) {
if (--argc < 1) goto bad;
crl_uri = *(++argv);
} else if (!strcmp(*argv, "-ca_issuers_uri")) {
if (--argc < 1) goto bad;
ca_issuers_uri = *(++argv);
} else if (!strcmp(*argv, "-ocsp_uri")) {
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else if (!strcmp(*argv, "-cacert")) {
if (--argc < 1) goto bad;
cacertfile = *(++argv);
if (!(cacertfp = fopen(cacertfile, "rb"))) {
fprintf(stderr, "%s: invalid -key_usage value\n", prog);
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;
pass = *(++argv);
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
outfile = *(++argv);
@@ -147,6 +277,129 @@ int reqsign_main(int argc, char **argv)
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-serial_len")) {
if (--argc < 1) goto bad;
serial_len = atoi(*(++argv));
if (serial_len <= 0 || serial_len > sizeof(serial)) {
fprintf(stderr, "%s: invalid `-serial_len` value, need a number less than %zu\n", prog, sizeof(serial));
goto end;
}
} else if (!strcmp(*argv, "-days")) {
if (--argc < 1) goto bad;
days = atoi(*(++argv));
if (days <= 0) {
fprintf(stderr, "%s: invalid `-days` value, need a positive number\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-cacert")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_cert_new_from_file(&cacert, &cacertlen, str) != 1) {
fprintf(stderr, "%s: load ca certificate '%s' failure\n", prog, str);
goto end;
}
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (!(keyfp = fopen(str, "rb"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, str, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-pass")) {
if (--argc < 1) goto bad;
pass = *(++argv);
} else if (!strcmp(*argv, "-sm2_id")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > sizeof(signer_id) - 1) {
fprintf(stderr, "%s: invalid `-sm2_id` length\n", prog);
goto end;
}
strncpy(signer_id, str, sizeof(signer_id));
signer_id_len = strlen(str);
} else if (!strcmp(*argv, "-sm2_id_hex")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (strlen(str) > (sizeof(signer_id) - 1) * 2) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` length\n", prog);
goto end;
}
if (hex_to_bytes(str, strlen(str), (uint8_t *)signer_id, &signer_id_len) != 1) {
fprintf(stderr, "%s: invalid `-sm2_id_hex` value\n", prog);
goto end;
}
// following copy from certgen.c
} else if (!strcmp(*argv, "-gen_authority_key_id")) {
gen_authority_key_id = 1;
} else if (!strcmp(*argv, "-gen_subject_key_id")) {
gen_subject_key_id = 1;
} else if (!strcmp(*argv, "-key_usage")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (ext_key_usage_set(&key_usage, str) != 1) {
fprintf(stderr, "%s: invalid `-key_usage` value '%s'\n", prog, str);
goto end;
}
} else if (!strcmp(*argv, "-subject_dns_name")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_general_names_add_dns_name(
subject_alt_name, &subject_alt_name_len, sizeof(subject_alt_name), str) != 1) {
fprintf(stderr, "%s: inner error on processing `-subject_dns_name`\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-issuer_dns_name")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_general_names_add_dns_name(
issuer_alt_name, &issuer_alt_name_len, sizeof(issuer_alt_name), str) != 1) {
fprintf(stderr, "%s: inner error on processing `-issuer_dns_name`\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ca")) {
ca = 1;
} else if (!strcmp(*argv, "-path_len_constraints")) {
if (--argc < 1) goto bad;
path_len_constraints = atoi(*(++argv));
if (path_len_constraints < 0) {
fprintf(stderr, "%s: invalid `-path_len_constraints` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ext_key_usage")) {
if (--argc < 1) goto bad;
str = *(++argv);
if (x509_key_purpose_from_name(str) <= 0) {
fprintf(stderr, "%s: invalid `-ext_key_usage` value '%s'\n", prog, str);
goto end;
}
if (ext_key_usages_cnt >= sizeof(ext_key_usages)/sizeof(ext_key_usages[0])) {
fprintf(stderr, "%s: too much `-ext_key_usage` options\n", prog);
goto end;
}
ext_key_usages[ext_key_usages_cnt++] = x509_key_purpose_from_name(str);
} else if (!strcmp(*argv, "-crl_http_uri")) {
if (--argc < 1) goto bad;
crl_http_uri = *(++argv);
} else if (!strcmp(*argv, "-crl_ldap_uri")) {
if (--argc < 1) goto bad;
crl_ldap_uri = *(++argv);
} else if (!strcmp(*argv, "-inhibit_any_policy")) {
if (--argc < 1) goto bad;
inhibit_any_policy = atoi(*(++argv));
if (inhibit_any_policy < 0) {
fprintf(stderr, "%s: invalid `-inhibit_any_policy` value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-ca_issuers_uri")) {
if (--argc < 1) goto bad;
ca_issuers_uri = *(++argv);
} else if (!strcmp(*argv, "-ocsp_uri")) {
if (--argc < 1) goto bad;
ocsp_uri = *(++argv);
} else {
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
goto end;
@@ -161,37 +414,49 @@ bad:
if (!days) {
fprintf(stderr, "%s: '-days' option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!cacertfile) {
if (!cacert) {
fprintf(stderr, "%s: '-cacert' option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!keyfile) {
if (!keyfp) {
fprintf(stderr, "%s: '-key' option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
printf("usage: gmssl %s %s\n\n", prog, options);
goto end;
}
if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1
|| x509_req_get_details(req, reqlen,
NULL, &subject, &subject_len, &subject_public_key,
NULL, NULL, NULL, NULL, NULL) != 1) {
if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1) {
fprintf(stderr, "%s: parse CSR failure\n", prog);
goto end;
}
if (!req_id_len) {
strcpy(req_id, SM2_DEFAULT_ID);
req_id_len = strlen(SM2_DEFAULT_ID);
}
if (x509_req_verify(req, reqlen, req_id, req_id_len) != 1) {
fprintf(stderr, "%s: signature verification failure\n", prog);
goto end;
}
if (x509_req_get_details(req, reqlen,
NULL, &subject, &subject_len, &subject_public_key,
NULL, NULL, NULL, NULL, NULL) != 1) {
fprintf(stderr, "%s: parse CSR failure\n", prog);
goto end;
}
if (x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), cacertfp) != 1
|| x509_cert_get_subject(cacert, cacertlen, &issuer, &issuer_len) != 1
if (x509_cert_get_subject(cacert, cacertlen, &issuer, &issuer_len) != 1
|| x509_cert_get_subject_public_key(cacert, cacertlen, &issuer_public_key) != 1) {
fprintf(stderr, "%s: parse CA certificate failure\n", prog);
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
fprintf(stderr, "%s: load private key failure\n", prog);
goto end;
@@ -200,58 +465,114 @@ bad:
fprintf(stderr, "%s: private key and CA certificate not match\n", prog);
goto end;
}
if (!signer_id_len) {
strcpy(signer_id, SM2_DEFAULT_ID);
signer_id_len = strlen(SM2_DEFAULT_ID);
}
if (rand_bytes(serial, sizeof(serial)) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
if (rand_bytes(serial, serial_len) != 1) {
fprintf(stderr, "%s: random number generator error\n", prog);
goto end;
}
time(&not_before);
if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), 1, key_usage) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
if (x509_validity_add_days(&not_after, not_before, days) != 1) {
fprintf(stderr, "%s: set Validity failure\n", prog);
goto end;
}
if (path_len_constraint >= 0) {
if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts), 1, 1, path_len_constraint) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
// following code copy from certgen.c
// Extensions
if (gen_authority_key_id) {
if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) {
fprintf(stderr, "%s: set AuthorityKeyIdentifier extension failure\n", prog);
goto end;
}
}
if (x509_exts_add_default_authority_key_identifier(exts, &extslen, sizeof(exts), &sm2_key) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
if (gen_subject_key_id) {
if (x509_exts_add_subject_key_identifier_ex(exts, &extslen, sizeof(exts), -1, &sm2_key) != 1) {
fprintf(stderr, "%s: set SubjectKeyIdentifier extension failure\n", prog);
goto end;
}
}
if (crl_uri) {
if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts), 0,
crl_uri, strlen(crl_uri), NULL, 0) != 1) {
fprintf(stderr, "%s: process -crl_uri error\n", prog);
if (key_usage) {
if (x509_exts_add_key_usage(exts, &extslen, sizeof(exts), X509_critical, key_usage) != 1) {
fprintf(stderr, "%s: set KeyUsage extension failure\n", prog);
goto end;
}
}
// no CertificatePolicies
// no PolicyMappings
if (subject_alt_name_len) {
if (x509_exts_add_subject_alt_name(exts, &extslen, sizeof(exts),
-1, subject_alt_name, subject_alt_name_len) != 1) {
fprintf(stderr, "%s: set SubjectAltName extension failure\n", prog);
goto end;
}
}
if (issuer_alt_name_len) {
if (x509_exts_add_issuer_alt_name(exts, &extslen, sizeof(exts),
-1, issuer_alt_name, issuer_alt_name_len) != 1) {
fprintf(stderr, "%s: set IssuerAltName extension failure\n", prog);
goto end;
}
}
// no SubjectDirectoryAttributes
if (ca >= 0 || path_len_constraints >= 0) {
if (x509_exts_add_basic_constraints(exts, &extslen, sizeof(exts),
X509_critical, ca, path_len_constraints) != 1) {
fprintf(stderr, "%s: set BasicConstraints extension failure\n", prog);
goto end;
}
}
// no NameConstraints
// no PolicyConstraints
if (ext_key_usages_cnt) {
if (x509_exts_add_ext_key_usage(exts, &extslen, sizeof(exts),
-1, ext_key_usages, ext_key_usages_cnt) != 1) {
fprintf(stderr, "%s: set ExtKeyUsage extension failure\n", prog);
goto end;
}
}
if (crl_http_uri || crl_ldap_uri) {
if (x509_exts_add_crl_distribution_points(exts, &extslen, sizeof(exts),
-1,
crl_http_uri, crl_http_uri ? strlen(crl_http_uri) : 0,
crl_ldap_uri, crl_ldap_uri ? strlen(crl_ldap_uri) : 0) != 1) {
fprintf(stderr, "%s: set CRLDistributionPoints extension failure\n", prog);
return -1;
}
}
if (inhibit_any_policy >= 0) {
if (x509_exts_add_inhibit_any_policy(exts, &extslen, sizeof(exts),
X509_critical, inhibit_any_policy) != 1) {
fprintf(stderr, "%s: set InhibitAnyPolicy extension failure\n", prog);
goto end;
}
}
if (ca_issuers_uri || ocsp_uri) {
if (x509_exts_add_authority_info_access(exts, &extslen, sizeof(exts), 0,
ca_issuers_uri, strlen(ca_issuers_uri), ocsp_uri, strlen(ocsp_uri)) != 1) {
fprintf(stderr, "%s: process -ca_issuers_uri -ocsp_uri error\n", prog);
ca_issuers_uri, ca_issuers_uri ? strlen(ca_issuers_uri) : 0,
ocsp_uri, ocsp_uri ? strlen(ocsp_uri) : 0) != 1) {
fprintf(stderr, "%s: set AuthorityInfoAccess extension failure\n", prog);
goto end;
}
}
if (x509_validity_add_days(&not_after, not_before, days) != 1
|| x509_cert_sign(
cert, &certlen, sizeof(cert),
X509_version_v3,
serial, sizeof(serial),
OID_sm2sign_with_sm3,
issuer, issuer_len,
not_before, not_after,
subject, subject_len,
&subject_public_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
if (x509_cert_sign(
cert, &certlen, sizeof(cert),
X509_version_v3,
serial, serial_len,
OID_sm2sign_with_sm3,
issuer, issuer_len,
not_before, not_after,
subject, subject_len,
&subject_public_key,
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, signer_id, signer_id_len) != 1) {
fprintf(stderr, "%s: certificate generation failure\n", prog);
goto end;
}
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {
@@ -262,7 +583,6 @@ bad:
end:
gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
if (keyfp) fclose(keyfp);
if (cacertfp) fclose(cacertfp);
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
return ret;