Update Tools

This commit is contained in:
Zhi Guan
2022-05-26 23:57:32 +08:00
parent 9eee1cc35d
commit 767dae98ab
38 changed files with 2090 additions and 505 deletions

14
demos/certdemo.sh Executable file
View File

@@ -0,0 +1,14 @@
#!/bin/bash -x
# generate sm2 keypair and encrypt with password
gmssl sm2keygen -pass 1234 -out sm2.pem -pubout sm2pub.pem
# generate a self-signed certificate
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -days 365 -key sm2.pem -pass 1234 \
-key_usage "digitalSignature" -key_usage "keyCertSign" -key_usage cRLSign \
-out cert.pem
gmssl certparse -in cert.pem

17
demos/cmsdemo.sh Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
gmssl sm2keygen -pass 1234 -out key.pem -pubout keypub.pem
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -days 365 -key key.pem -pass 1234 -out cert.pem
echo "<html>The plaintext message.</html>" > plain.txt
gmssl cmsencrypt -in plain.txt -rcptcert cert.pem -out enveloped_data.pem
gmssl cmsparse -in enveloped_data.pem
gmssl cmsdecrypt -key key.pem -pass 1234 -cert cert.pem -in enveloped_data.pem
gmssl cmssign -key key.pem -pass 1234 -cert cert.pem -in plain.txt -out signed_data.pem
gmssl cmsparse -in signed_data.pem
gmssl cmsverify -in signed_data.pem -out signed_data.txt
cat signed_data.txt

19
demos/reqdemo.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash -x
# generate self-signed CA certificate
gmssl sm2keygen -pass 1234 -out cakey.pem -pubout pubkey.pem
gmssl certgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN CA -days 365 -key cakey.pem -pass 1234 -out cacert.pem
gmssl certparse -in cacert.pem
# generate a req and sign by CA certificate
gmssl sm2keygen -pass 1234 -out signkey.pem -pubout pubkey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -days 365 -key signkey.pem -pass 1234 -out signreq.pem
gmssl reqsign -in signreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out signcert.pem
gmssl certparse -in signcert.pem
# sign a encryption certificate with the same DN, different KeyUsage extension
gmssl sm2keygen -pass 1234 -out enckey.pem -pubout pubkey.pem
gmssl reqgen -C CN -ST Beijing -L Haidian -O PKU -OU CS -CN Alice -days 365 -key enckey.pem -pass 1234 -out encreq.pem
gmssl reqsign -in encreq.pem -days 365 -key_usage digitalSignature -cacert cacert.pem -key cakey.pem -pass 1234 -out enccert.pem
gmssl certparse -in enccert.pem

16
demos/sm234demo.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/bin/bash
ENC_KEY=`gmssl rand -outlen 16 -hex`
MAC_KEY=`gmssl rand -outlen 32 -hex`
IV=`gmssl rand -outlen 16 -hex`
gmssl sm2keygen -pass 1234 -out sm2.pem -pubout sm2pub.pem
echo "$ENC_KEY$MAC_KEY" | xxd -p -r | gmssl sm2encrypt -pubkey sm2pub.pem | xxd -p > out.bin
echo $IV >> out.bin
echo "plaintext" | gmssl sm4 -cbc -encrypt -key $ENC_KEY -iv $IV | xxd -p >> out.bin
# gmssl sm2decrypt -key sm2.pem -pass 1234 -in sm2.der

View File

@@ -327,6 +327,8 @@ RecipientInfo ::= SEQUENCE {
keyEncryptionAlgorithm AlgorithmIdentifier,
encryptedKey OCTET STRING -- DER-encoding of SM2Cipher
}
由于encryptedKey的类型为SM2Cipher, 而SM2Cipher中有2个INTEGER因此长度是不固定的。
因此不能预先确定输出长度
*/
int cms_recipient_info_to_der(
int version,
@@ -574,6 +576,11 @@ int cms_set_key_agreement_info(
const uint8_t *user_cert, size_t user_cert_len,
const uint8_t *user_id, size_t user_id_len);
#define PEM_CMS "CMS"
int cms_to_pem(const uint8_t *cms, size_t cms_len, FILE *fp);
int cms_from_pem(uint8_t *cms, size_t *cms_len, size_t maxlen, FILE *fp);
int cms_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen);

View File

@@ -75,7 +75,7 @@ typedef struct DIGEST_CTX DIGEST_CTX;
struct DIGEST_CTX {
union {
SM3_CTX sm3_ctx;
MD5_CTX md5_ctx;
// MD5_CTX md5_ctx;
SHA1_CTX sha1_ctx;
SHA224_CTX sha224_ctx;
SHA256_CTX sha256_ctx;
@@ -96,7 +96,7 @@ struct DIGEST {
};
const DIGEST *DIGEST_sm3(void);
const DIGEST *DIGEST_md5(void);
//const DIGEST *DIGEST_md5(void);
const DIGEST *DIGEST_sha1(void);
const DIGEST *DIGEST_sha224(void);
const DIGEST *DIGEST_sha256(void);

View File

@@ -103,6 +103,7 @@ enum {
OID_at_serial_number,
OID_at_pseudonym,
OID_domain_component,
OID_email_address,
// Cert Extensions
OID_ce_authority_key_identifier,
@@ -120,6 +121,7 @@ enum {
OID_ce_crl_distribution_points,
OID_ce_inhibit_any_policy,
OID_ce_freshest_crl,
OID_netscape_cert_type,
OID_netscape_cert_comment,
OID_cert_authority_info_access,
OID_ct_precertificate_scts,

View File

@@ -336,6 +336,7 @@ typedef struct {
uint8_t s[32];
} SM2_SIGNATURE;
int sm2_do_sign_ex(const SM2_KEY *key, int flags, const uint8_t dgst[32], SM2_SIGNATURE *sig);
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig);
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig);
@@ -344,6 +345,7 @@ int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATUR
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen);
int sm2_signature_from_der(SM2_SIGNATURE *sig, const uint8_t **in, size_t *inlen);
int sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *sig, size_t siglen);
int sm2_sign_ex(const SM2_KEY *key, int flags, const uint8_t dgst[32], uint8_t *sig, size_t *siglen);
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen);
int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen);
@@ -387,6 +389,7 @@ typedef struct {
uint8_t ciphertext[SM2_MAX_PLAINTEXT_SIZE];
} SM2_CIPHERTEXT;
int sm2_do_encrypt_ex(const SM2_KEY *key, int flags, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out);
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out);
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen);
@@ -395,6 +398,7 @@ int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, s
int sm2_ciphertext_to_der(const SM2_CIPHERTEXT *c, uint8_t **out, size_t *outlen);
int sm2_ciphertext_from_der(SM2_CIPHERTEXT *c, const uint8_t **in, size_t *inlen);
int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen);
int sm2_encrypt_ex(const SM2_KEY *key, int flags, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);
int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen);

View File

@@ -76,7 +76,6 @@ X509 Public API
x509_name_to_der
x509_name_from_der
x509_name_print
x509_name_get_printable
x509_name_get_value_by_type
x509_name_get_common_name
@@ -171,6 +170,16 @@ int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
/*
Name ::= SEQUENCE OF RelativeDistinguishedName
Example:
SEQUENCE LEN
SET LEN
SEQUENCE LEN OID=countryName, String=CN
SET LEN
SEQUENCE LEN OID=stateName, String=CN
SEQUENCE LEN OID=unknown, String=ABC
SET LEN
SEQUENCE LEN OID=commonNmame, String=ABC
*/
int x509_name_add_rdn(uint8_t *d, size_t *dlen, size_t maxlen, int oid, int tag, const uint8_t *val, size_t vlen, const uint8_t *more, size_t mlen);
int x509_name_add_country_name(uint8_t *d, size_t *dlen, int maxlen, const char val[2] ); // val: PrintableString SIZE(2)
@@ -188,7 +197,6 @@ int x509_name_set(uint8_t *d, size_t *dlen, size_t maxlen,
#define x509_name_to_der(d,dlen,out,outlen) asn1_sequence_to_der(d,dlen,out,outlen)
#define x509_name_from_der(d,dlen,in,inlen) asn1_sequence_from_der(d,dlen,in,inlen)
int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen);
int x509_name_get_printable(const uint8_t *d, size_t dlen, char *str, size_t maxlen);
int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen);
int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen);
@@ -348,7 +356,7 @@ int x509_cert_get_subject(const uint8_t *a, size_t alen, const uint8_t **subj, s
int x509_cert_get_subject_public_key(const uint8_t *a, size_t alen, SM2_KEY *public_key);
int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp);
int x509_certs_from_pem(const uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp);
int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp);
int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt);
int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen);
int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen);

View File

@@ -80,6 +80,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
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

@@ -268,6 +268,10 @@ 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,

View File

@@ -554,6 +554,24 @@ FreshestCRL ::= CRLDistributionPoints
#define x509_freshest_crl_from_der(d,dlen,in,inlen) x509_crl_distribution_points_from_der(d,dlen,in,inlen)
#define x509_freshest_crl_print(fp,fmt,ind,label,d,dlen) x509_crl_distribution_points_print(fp,fmt,ind,label,d,dlen)
/*
Netscape-Defined Certificate Extensions
https://docs.oracle.com/cd/E19957-01/816-5533-10/ext.htm#1023061
NetscapeCertType ::= BIT STRING
bit 0: SSL Client certificate
bit 1: SSL Server certificate
bit 2: S/MIME certificate
bit 3: Object-signing certificate
bit 4: Reserved for future use
bit 5: SSL CA certificate
bit 6: S/MIME CA certificate
bit 7: Object-signing CA certificate
NetscapeCertComment ::= IA5String
*/
int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits);
#ifdef __cplusplus
}

View File

@@ -738,6 +738,7 @@ const ASN1_OID_INFO *asn1_oid_info_from_oid(const ASN1_OID_INFO *infos, size_t c
return NULL;
}
// 如果一个正确解析的OID并不在infos列表中那么仍然返回1但是调用方必须检查返回的info是否为空
int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_t *nodes_cnt,
const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen)
{
@@ -753,27 +754,30 @@ int asn1_oid_info_from_der_ex(const ASN1_OID_INFO **info, uint32_t *nodes, size_
if (*nodes_cnt == infos[i].nodes_cnt
&& memcmp(nodes, infos[i].nodes, (*nodes_cnt) * sizeof(int)) == 0) {
*info = &infos[i];
return 1;
goto end;
}
}
// 注意此时虽然返回1但是*info == NULL因此调用方应该显式的判断info
end:
return 1;
}
// 和ex版本不同的是如果在infos列表中未找到OID返回错误
int asn1_oid_info_from_der(const ASN1_OID_INFO **info, const ASN1_OID_INFO *infos, size_t count, const uint8_t **in, size_t *inlen)
{
int ret;
uint32_t nodes[32];
size_t nodes_cnt;
if ((ret = asn1_oid_info_from_der_ex(info, nodes, &nodes_cnt, infos, count, in, inlen)) < 0) {
error_print();
return -1;
} else if (ret > 1) {
if ((ret = asn1_oid_info_from_der_ex(info, nodes, &nodes_cnt, infos, count, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if (*info == NULL) {
asn1_object_identifier_print(stderr, 0, 0, "Unknown OID", NULL, nodes, nodes_cnt);
error_print();
return -1;
}
return ret;
return 1;
}
@@ -1355,7 +1359,7 @@ int asn1_object_identifier_print(FILE *fp, int format, int indent, const char *l
const uint32_t *nodes, size_t nodes_cnt)
{
size_t i;
format_print(fp, format, indent, "%s: %s", label, name);
format_print(fp, format, indent, "%s: %s", label, name ? name : "(unknown)");
if (nodes) {
fprintf(fp, " (");
for (i = 0; i < nodes_cnt - 1; i++) {

259
src/cms.c
View File

@@ -63,6 +63,7 @@
#include <gmssl/x509_ext.h>
#include <gmssl/x509_crl.h>
#include <gmssl/rand.h>
#include <gmssl/pem.h>
#include <gmssl/cms.h>
@@ -110,14 +111,15 @@ int cms_content_type_from_name(const char *name)
int cms_content_type_to_der(int oid, uint8_t **out, size_t *outlen)
{
const ASN1_OID_INFO *info;
size_t len = 0;
if (oid == -1) {
return 0;
}
if (!(info = asn1_oid_info_from_oid(cms_content_types, cms_content_types_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
|| asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
if (asn1_object_identifier_to_der(info->nodes, info->nodes_cnt, out, outlen) != 1) {
error_print();
return -1;
}
@@ -127,18 +129,11 @@ int cms_content_type_to_der(int oid, uint8_t **out, size_t *outlen)
int cms_content_type_from_der(int *oid, const uint8_t **in, size_t *inlen)
{
int ret;
const uint8_t *p;
size_t len;
const ASN1_OID_INFO *info;
*oid = 0;
if ((ret = asn1_sequence_from_der(&p, &len, in, inlen)) != 1) {
if ((ret = asn1_oid_info_from_der(&info, cms_content_types, cms_content_types_count, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
if ((ret = asn1_oid_info_from_der(&info, cms_content_types, cms_content_types_count, &p, &len)) != 1
|| asn1_length_is_zero(len) != 1) {
error_print();
else *oid = -1;
return ret;
}
*oid = info->oid;
@@ -164,12 +159,13 @@ static int cms_content_info_data_header_to_der(size_t dlen, uint8_t **out, size_
int cms_content_info_header_to_der(int content_type, size_t content_len, uint8_t **out, size_t *outlen)
{
size_t len = 0;
size_t len = content_len; // 注意由于header_to_der没有输出数据因此需要加上数据的长度header length 才是正确的值
/*
if (content_type == OID_cms_data) {
return cms_content_info_data_header_to_der(content_len, out, outlen);
}
*/
if (cms_content_type_to_der(content_type, NULL, &len) != 1
|| asn1_explicit_header_to_der(0, content_len, NULL, &len) < 0
|| asn1_sequence_header_to_der(len, out, outlen) != 1
@@ -254,23 +250,43 @@ int cms_content_info_print(FILE *fp, int fmt, int ind, const char *label, const
if (cms_content_type_from_der(&content_type, &d, &dlen) != 1) goto err;
format_print(fp, fmt, ind, "contentType: %s\n", cms_content_type_name(content_type));
if ((ret = asn1_explicit_from_der(0, &content, &content_len, &d, &dlen)) < 0) goto err;
if (ret) {
/*
if (content_type == OID_cms_data) {
if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1) goto err;
} else {
if (asn1_sequence_from_der(&p, &len, &content, &content_len) != 1) goto err;
}
switch (content_type) {
case OID_cms_data: format_bytes(fp, fmt, ind, "content", p, len); break;
case OID_cms_signed_data: cms_signed_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_enveloped_data: cms_enveloped_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_signed_and_enveloped_data: cms_signed_and_enveloped_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_encrypted_data: cms_encrypted_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_key_agreement_info: cms_key_agreement_info_print(fp, fmt, ind, "content", p, len); break;
*/
//format_bytes(stderr, 0, 0, "content", d, dlen);
if ((ret = asn1_explicit_from_der(0, &content, &content_len, &d, &dlen)) < 0) { error_print(); goto err; }
if (ret == 0) { error_print(); goto err; }
if (content_type == OID_cms_data) {
if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1
|| asn1_length_is_zero(content_len) != 1) {
error_print();
return -1;
}
if (asn1_length_is_zero(content_len) != 1) goto err;
format_bytes(fp, fmt, ind, "content", p, len);
return 1;
}
if (asn1_sequence_from_der(&p, &len, &content, &content_len) != 1) { error_print(); goto err; }
switch (content_type) {
//case OID_cms_data: format_bytes(fp, fmt, ind, "content", p, len); break;
case OID_cms_signed_data: cms_signed_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_enveloped_data: cms_enveloped_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_signed_and_enveloped_data: cms_signed_and_enveloped_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_encrypted_data: cms_encrypted_data_print(fp, fmt, ind, "content", p, len); break;
case OID_cms_key_agreement_info: cms_key_agreement_info_print(fp, fmt, ind, "content", p, len); break;
}
if (asn1_length_is_zero(content_len) != 1) goto err;
if (asn1_length_is_zero(dlen) != 1) goto err;
return 1;
err:
@@ -367,8 +383,8 @@ int cms_enced_content_info_encrypt_to_der(
{
int ret;
SM4_KEY sm4_key;
uint8_t enced_content[32 + content_len];
size_t enced_content_len;
uint8_t enced_content[32 + content_len]; // FIXME: 如果content_len 过长会直接导致segment fault
size_t enced_content_len = 100;
if (enc_algor != OID_sm4_cbc || keylen != 16 || ivlen != 16) {
error_print();
@@ -759,6 +775,7 @@ int cms_signer_info_sign_to_der(
uint8_t **out, size_t *outlen)
{
SM3_CTX ctx = *sm3_ctx;
int fixed_outlen = 1;
uint8_t dgst[SM3_DIGEST_SIZE];
uint8_t sig[SM2_MAX_SIGNATURE_SIZE];
size_t siglen;
@@ -766,11 +783,12 @@ int cms_signer_info_sign_to_der(
sm3_update(&ctx, authed_attrs, authed_attrs_len);
sm3_finish(&ctx, dgst);
if (sm2_sign(sign_key, dgst, sig, &siglen) != 1) {
if (sm2_sign_ex(sign_key, fixed_outlen, dgst, sig, &siglen) != 1) {
error_print();
return -1;
}
if (cms_signer_info_to_der(CMS_version_v1,
issuer, issuer_len, serial_number, serial_number_len,
OID_sm3, authed_attrs, authed_attrs_len,
@@ -1206,6 +1224,7 @@ int cms_signed_data_verify_from_der(
&authed_attrs, &authed_attrs_len,
&unauthed_attrs, &unauthed_attrs_len,
&signer_infos, &signer_infos_len) != 1) {
error_print();
return -1;
}
@@ -1264,7 +1283,8 @@ int cms_recipient_info_from_der(
serial_number, serial_number_len, &d, &dlen) != 1
|| x509_public_key_encryption_algor_from_der(pke_algor, params, params_len, &d, &dlen) != 1
|| asn1_octet_string_from_der(enced_key, enced_key_len, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
// || asn1_length_is_zero(dlen) != 1
) {
error_print();
return -1;
}
@@ -1317,12 +1337,14 @@ int cms_recipient_info_encrypt_to_der(
int pke_algor = OID_sm2encrypt;
uint8_t enced_key[SM2_MAX_CIPHERTEXT_SIZE];
size_t enced_key_len;
int fixed_outlen = 1;
if (pke_algor != OID_sm2encrypt) {
error_print();
return -1;
}
if (sm2_encrypt(public_key, in, inlen, enced_key, &enced_key_len) != 1) {
if (sm2_encrypt_ex(public_key, fixed_outlen, in, inlen, enced_key, &enced_key_len) != 1) {
error_print();
return -1;
}
@@ -1554,7 +1576,6 @@ int cms_enveloped_data_encrypt_to_der(
return -1;
}
}
len = 0;
if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1
|| asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1
@@ -2048,9 +2069,20 @@ int cms_set_data(uint8_t *cms, size_t *cmslen, const uint8_t *d, size_t dlen)
int oid = OID_cms_data;
size_t len = 0;
if (asn1_octet_string_to_der(d, dlen, NULL, &len) < 0) {
error_print();
return -1;
}
*cmslen = 0;
if (asn1_octet_string_to_der(d, dlen, NULL, &len) < 0
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| asn1_octet_string_to_der(d, dlen, &cms, cmslen) < 0) {
error_print();
return -1;
@@ -2067,14 +2099,25 @@ int cms_encrypt(uint8_t *cms, size_t *cmslen,
int oid = OID_cms_encrypted_data;
size_t len = 0;
*cmslen = 0;
if (cms_encrypted_data_encrypt_to_der(
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1) {
error_print();
return -1;
}
*cmslen = 0;
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| cms_encrypted_data_encrypt_to_der(
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
@@ -2125,13 +2168,24 @@ int cms_sign(uint8_t *cms, size_t *cmslen,
int oid = OID_cms_signed_data;
size_t len = 0;
*cmslen = 0;
if (cms_signed_data_sign_to_der(
signers, signers_cnt,
content_type, content, content_len,
crls, crls_len,
NULL, &len) != 1
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
signers, signers_cnt,
content_type, content, content_len,
crls, crls_len,
NULL, &len) != 1) {
error_print();
return -1;
}
*cmslen = 0;
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| cms_signed_data_sign_to_der(
signers, signers_cnt,
content_type, content, content_len,
@@ -2156,12 +2210,19 @@ int cms_verify(const uint8_t *cms, size_t cmslen,
size_t cms_content_len;
if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1
|| asn1_check(cms_type != OID_cms_signed_data) != 1
|| asn1_check(cms_content && cms_content_len) != 1
|| asn1_length_is_zero(cmslen) != 1) {
error_print();
return -1;
}
if (cms_type != OID_cms_signed_data) {
error_print();
return -1;
}
if (cms_content_len <= 0) {
error_print();
return -1;
}
if (cms_signed_data_verify_from_der(
extra_certs, extra_certs_len,
extra_crls, extra_crls_len,
@@ -2188,15 +2249,26 @@ int cms_envelop(
int oid = OID_cms_enveloped_data;
size_t len = 0;
*cmslen = 0;
if (cms_enveloped_data_encrypt_to_der(
rcpt_certs, rcpt_certs_len,
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
rcpt_certs, rcpt_certs_len,
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1) {
error_print();
return -1;
}
*cmslen = 0;
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| cms_enveloped_data_encrypt_to_der(
rcpt_certs, rcpt_certs_len,
enc_algor, key, keylen, iv, ivlen,
@@ -2272,17 +2344,28 @@ int cms_sign_and_envelop(uint8_t *cms, size_t *cmslen,
int oid = OID_cms_signed_and_enveloped_data;
size_t len = 0;
*cmslen = 0;
if (cms_signed_and_enveloped_data_encipher_to_der(
signers, signers_cnt,
rcpt_certs, rcpt_certs_len,
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
crls, crls_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
signers, signers_cnt,
rcpt_certs, rcpt_certs_len,
enc_algor, key, keylen, iv, ivlen,
content_type, content, content_len,
crls, crls_len,
shared_info1, shared_info1_len,
shared_info2, shared_info2_len,
NULL, &len) != 1) {
error_print();
return -1;
}
*cmslen = 0;
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| cms_signed_and_enveloped_data_encipher_to_der(
signers, signers_cnt,
rcpt_certs, rcpt_certs_len,
@@ -2372,10 +2455,21 @@ int cms_set_key_agreement_info(
int oid = OID_cms_key_agreement_info;
size_t len = 0;
*cmslen = 0;
if (cms_key_agreement_info_to_der(CMS_version_v1, temp_public_key_r,
user_cert, user_cert_len, user_id, user_id_len, NULL, &len) != 1
|| cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
user_cert, user_cert_len, user_id, user_id_len, NULL, &len) != 1) {
error_print();
return -1;
}
*cmslen = 0;
if (!cms) {
uint8_t data[1];
if (cms_content_info_to_der(oid, data, len, NULL, cmslen) != 1) {
error_print();
return -1;
}
return 1;
}
if (cms_content_info_header_to_der(oid, len, &cms, cmslen) != 1
|| cms_key_agreement_info_to_der(CMS_version_v1, temp_public_key_r,
user_cert, user_cert_len, user_id, user_id_len, &cms, cmslen) != 1) {
error_print();
@@ -2384,16 +2478,41 @@ int cms_set_key_agreement_info(
return 1;
}
int cms_to_pem(const uint8_t *cms, size_t cms_len, FILE *fp)
{
if (pem_write(fp, PEM_CMS, cms, cms_len) != 1) {
error_print();
return -1;
}
return 1;
}
int cms_from_pem(uint8_t *cms, size_t *cms_len, size_t maxlen, FILE *fp)
{
int ret;
if ((ret = pem_read(fp, PEM_CMS, cms, cms_len, maxlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
int cms_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
{
const uint8_t *d;
size_t dlen;
if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) goto err;
cms_content_info_print(fp, fmt, ind, label, d, dlen);
if (asn1_length_is_zero(alen) != 1) goto err;
//if (asn1_length_is_zero(alen) != 1) goto err;
return 1;
err:
error_print();
return -1;
}

View File

@@ -62,7 +62,7 @@ typedef struct {
DIGEST_TABLE digest_table[] = {
{ OID_sm3, "sm3", "SM3" },
{ OID_md5, "md5", "MD5" },
// { OID_md5, "md5", "MD5" },
{ OID_sha1, "sha1", "SHA-1" },
{ OID_sha224, "sha224", "SHA-224" },
{ OID_sha256, "sha256", "SHA-256" },
@@ -131,8 +131,10 @@ const DIGEST *digest_from_name(const char *name)
{
if (!strcmp(name, "sm3") || !strcmp(name, "SM3")) {
return DIGEST_sm3();
/*
} else if (!strcmp(name, "md5") || !strcmp(name, "MD5")) {
return DIGEST_md5();
*/
} else if (!strcmp(name, "sha1") || !strcmp(name, "SHA1")) {
return DIGEST_sha1();
} else if (!strcmp(name, "sha224") || !strcmp(name, "SHA224")) {
@@ -196,7 +198,7 @@ const DIGEST *DIGEST_sm3(void)
return &sm3_digest_object;
}
/*
#include <gmssl/md5.h>
static int md5_digest_init(DIGEST_CTX *ctx)
@@ -243,6 +245,7 @@ const DIGEST *DIGEST_md5(void)
{
return &md5_digest_object;
}
*/
#include <gmssl/sha1.h>
@@ -292,7 +295,6 @@ const DIGEST *DIGEST_sha1(void)
return &sha1_digest_object;
}
#include <gmssl/sha2.h>
static int sha224_digest_init(DIGEST_CTX *ctx)

View File

@@ -97,6 +97,10 @@ int pem_read(FILE *fp, const char *name, uint8_t *data, size_t *datalen, size_t
if (strcmp(line, begin_line) != 0) {
// FIXME: 这里是不是应该容忍一些错误呢?
fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, line);
fprintf(stderr, "%s %d: %s\n", __FILE__, __LINE__, begin_line);
error_print();
return -1;
}

View File

@@ -697,12 +697,6 @@ void sm2_fn_mul(SM2_BN r, const SM2_BN a, const SM2_BN b)
uint64_t c[9] = {0,0,0,0,0,0,0,0,0x100000000};
sm2_bn288_sub(q, c, q);
sm2_bn288_add(zl, q, zl);
printf("******\n");
printf("******\n");
printf("******\n");
printf("******\n");
printf("******\n");
}
//printf("r = "); for (i = 8; i >= 0; i--) printf("%08x", (uint32_t)zl[i]); printf("\n");

View File

@@ -50,6 +50,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/mem.h>
#include <gmssl/sm2.h>
#include <gmssl/sm3.h>
#include <gmssl/asn1.h>
@@ -58,7 +59,7 @@
#define print_bn(str,a) sm2_bn_print(stderr,0,4,str,a)
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
int sm2_do_sign_ex(const SM2_KEY *key, int fixed_outlen, const uint8_t dgst[32], SM2_SIGNATURE *sig)
{
SM2_JACOBIAN_POINT _P, *P = &_P;
SM2_BN d;
@@ -68,12 +69,12 @@ int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
SM2_BN r;
SM2_BN s;
retry:
sm2_bn_from_bytes(d, key->private_key);
// e = H(M)
sm2_bn_from_bytes(e, dgst); //print_bn("e", e);
retry:
// e被重用了注意retry的位置
// rand k in [1, n - 1]
do {
@@ -107,17 +108,31 @@ retry:
sm2_fn_inv(e, e); //print_bn("(1+d)^-1", e);
sm2_fn_mul(s, e, k); //print_bn("s = ((1 + d)^-1 * (k - r * d)) mod n", s);
sm2_bn_clean(d);
sm2_bn_clean(k);
sm2_bn_to_bytes(r, sig->r); //print_bn("r", r);
sm2_bn_to_bytes(s, sig->s); //print_bn("s", s);
if (fixed_outlen) {
uint8_t buf[72];
uint8_t *p = buf;
size_t len = 0;
sm2_signature_to_der(sig, &p, &len);
if (len != 71) {
goto retry;
}
}
sm2_bn_clean(d);
sm2_bn_clean(k);
gmssl_secure_clear(d, sizeof(d));
gmssl_secure_clear(e, sizeof(e));
gmssl_secure_clear(k, sizeof(k));
gmssl_secure_clear(x, sizeof(x));
return 1;
}
int sm2_do_sign(const SM2_KEY *key, const uint8_t dgst[32], SM2_SIGNATURE *sig)
{
return sm2_do_sign_ex(key, 0, dgst, sig);
}
int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATURE *sig)
{
SM2_JACOBIAN_POINT _P, *P = &_P;
@@ -161,12 +176,12 @@ int sm2_do_verify(const SM2_KEY *key, const uint8_t dgst[32], const SM2_SIGNATUR
sm2_bn_from_bytes(e, dgst); //print_bn("e = H(M)", e);
sm2_fn_add(e, e, x); //print_bn("e + x (mod n)", e);
// check if r == r'
if (sm2_bn_cmp(e, r) == 0) {
return 1;
} else {
if (sm2_bn_cmp(e, r) != 0) {
return 0;
}
return 1;
}
int sm2_signature_to_der(const SM2_SIGNATURE *sig, uint8_t **out, size_t *outlen)
@@ -231,7 +246,7 @@ int sm2_signature_print(FILE *fp, int fmt, int ind, const char *label, const uin
#define SM2_SIGNATURE_MAX_DER_SIZE 77
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen)
int sm2_sign_ex(const SM2_KEY *key, int fixed_outlen, const uint8_t dgst[32], uint8_t *sig, size_t *siglen)
{
SM2_SIGNATURE signature;
uint8_t *p;
@@ -246,7 +261,7 @@ int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *s
p = sig;
*siglen = 0;
if (sm2_do_sign(key, dgst, &signature) != 1
if (sm2_do_sign_ex(key, fixed_outlen, dgst, &signature) != 1
|| sm2_signature_to_der(&signature, &p, siglen) != 1) {
error_print();
return -1;
@@ -254,6 +269,11 @@ int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *s
return 1;
}
int sm2_sign(const SM2_KEY *key, const uint8_t dgst[32], uint8_t *sig, size_t *siglen)
{
return sm2_sign_ex(key, 0, dgst, sig, siglen);
}
int sm2_verify(const SM2_KEY *key, const uint8_t dgst[32], const uint8_t *sig, size_t siglen)
{
int ret;
@@ -497,7 +517,7 @@ int sm2_kdf(const uint8_t *in, size_t inlen, size_t outlen, uint8_t *out)
return 1;
}
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
int sm2_do_encrypt_ex(const SM2_KEY *key, int fixed_outlen, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
{
SM2_BN k;
SM2_JACOBIAN_POINT _P, *P = &_P;
@@ -505,15 +525,22 @@ int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPH
uint8_t buf[64];
int i;
retry:
// rand k in [1, n - 1]
do {
sm2_bn_rand_range(k, SM2_N);
} while (sm2_bn_is_zero(k));
sm2_bn_rand_range(k, SM2_N);
if (sm2_bn_is_zero(k)) goto retry;
// C1 = k * G = (x1, y1)
sm2_jacobian_point_mul_generator(P, k);
sm2_jacobian_point_to_bytes(P, (uint8_t *)&out->point);
if (fixed_outlen) {
size_t xlen = 0, ylen = 0;
asn1_integer_to_der(out->point.x, 32, NULL, &xlen);
if (xlen != 34) goto retry;
asn1_integer_to_der(out->point.y, 32, NULL, &ylen);
if (ylen != 34) goto retry;
}
// Q = k * P = (x2, y2)
sm2_jacobian_point_from_bytes(P, (uint8_t *)&key->public_key);
@@ -543,6 +570,11 @@ int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPH
return 1;
}
int sm2_do_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, SM2_CIPHERTEXT *out)
{
return sm2_do_encrypt_ex(key, 0, in, inlen, out);
}
int sm2_do_decrypt(const SM2_KEY *key, const SM2_CIPHERTEXT *in, uint8_t *out, size_t *outlen)
{
uint32_t inlen;
@@ -683,7 +715,7 @@ int sm2_ciphertext_print(FILE *fp, int fmt, int ind, const char *label, const ui
return 1;
}
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
int sm2_encrypt_ex(const SM2_KEY *key, int fixed_outlen, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
SM2_CIPHERTEXT C;
@@ -695,7 +727,7 @@ int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *ou
error_print();
return -1;
}
if (sm2_do_encrypt(key, in, inlen, &C) != 1) {
if (sm2_do_encrypt_ex(key, fixed_outlen, in, inlen, &C) != 1) {
error_print();
return -1;
}
@@ -707,6 +739,11 @@ int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *ou
return 1;
}
int sm2_encrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
return sm2_encrypt_ex(key, 0, in, inlen, out, outlen);
}
int sm2_decrypt(const SM2_KEY *key, const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
{
SM2_CIPHERTEXT C;

View File

@@ -53,8 +53,7 @@
#include <gmssl/oid.h>
#include <gmssl/asn1.h>
#include <gmssl/error.h>
#include <gmssl/x509_alg.h>
static uint32_t oid_sm3[] = { 1,2,156,10197,1,401 };
@@ -271,21 +270,20 @@ static uint32_t oid_rsasign_with_sha256[] = { 1,2,840,113549,1,1,11 };
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 };
#define X509_ALGOR_OPT_NULL_PARAM 1
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), 0 },
{ OID_rsasign_with_sm3, "rsasign-with-sm3", oid_rsasign_with_sm3, sizeof(oid_rsasign_with_sm3)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM },
{ OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), 0 },
{ OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), 0} ,
{ OID_ecdsa_with_sha256, "ecdsa-with-sha256", oid_ecdsa_with_sha256, sizeof(oid_ecdsa_with_sha256)/sizeof(int), 0},
{ OID_ecdsa_with_sha384, "ecdsa-with-sha384", oid_ecdsa_with_sha384, sizeof(oid_ecdsa_with_sha384)/sizeof(int), 0 },
{ OID_ecdsa_with_sha512, "ecdsa-with-sha512", oid_ecdsa_with_sha512, sizeof(oid_ecdsa_with_sha512)/sizeof(int), 0 },
{ OID_rsasign_with_sha1, "sha1WithRSAEncryption", oid_rsasign_with_sha1, sizeof(oid_rsasign_with_sha1)/sizeof(int), 0 },
{ OID_rsasign_with_sha224, "sha224WithRSAEncryption", oid_rsasign_with_sha224, sizeof(oid_rsasign_with_sha224)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM },
{ OID_rsasign_with_sha256, "sha256WithRSAEncryption", oid_rsasign_with_sha256, sizeof(oid_rsasign_with_sha256)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM },
{ OID_rsasign_with_sha384, "sha384WithRSAEncryption", oid_rsasign_with_sha384, sizeof(oid_rsasign_with_sha384)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM },
{ OID_rsasign_with_sha512, "sha512WithRSAEncryption", oid_rsasign_with_sha512, sizeof(oid_rsasign_with_sha512)/sizeof(int), X509_ALGOR_OPT_NULL_PARAM },
{ 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 },
{ OID_ecdsa_with_sha1, "ecdsa-with-sha1", oid_ecdsa_with_sha1, sizeof(oid_ecdsa_with_sha1)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_ecdsa_with_sha224, "ecdsa-with-sha224", oid_ecdsa_with_sha224, sizeof(oid_ecdsa_with_sha224)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM } ,
{ OID_ecdsa_with_sha256, "ecdsa-with-sha256", oid_ecdsa_with_sha256, sizeof(oid_ecdsa_with_sha256)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_ecdsa_with_sha384, "ecdsa-with-sha384", oid_ecdsa_with_sha384, sizeof(oid_ecdsa_with_sha384)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_ecdsa_with_sha512, "ecdsa-with-sha512", oid_ecdsa_with_sha512, sizeof(oid_ecdsa_with_sha512)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_rsasign_with_sha1, "sha1WithRSAEncryption", oid_rsasign_with_sha1, sizeof(oid_rsasign_with_sha1)/sizeof(int), X509_ALGOR_ALLOW_EC_NULL_PARAM },
{ OID_rsasign_with_sha224, "sha224WithRSAEncryption", oid_rsasign_with_sha224, sizeof(oid_rsasign_with_sha224)/sizeof(int), 1 },
{ OID_rsasign_with_sha256, "sha256WithRSAEncryption", oid_rsasign_with_sha256, sizeof(oid_rsasign_with_sha256)/sizeof(int), 1 },
{ OID_rsasign_with_sha384, "sha384WithRSAEncryption", oid_rsasign_with_sha384, sizeof(oid_rsasign_with_sha384)/sizeof(int), 1 },
{ OID_rsasign_with_sha512, "sha512WithRSAEncryption", oid_rsasign_with_sha512, sizeof(oid_rsasign_with_sha512)/sizeof(int), 1 },
};
static const int x509_sign_algors_count =

View File

@@ -329,16 +329,26 @@ int x509_attr_type_and_value_print(FILE *fp, int fmt, int ind, const char *label
if (fmt & ASN1_FMT_FULL) {
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
}
if (x509_name_type_from_der(&oid, &d, &dlen) != 1) goto err;
if (fmt & ASN1_FMT_FULL)
if (x509_name_type_from_der(&oid, &d, &dlen) != 1) goto err;
asn1_object_identifier_print(fp, fmt, ind, "type", x509_name_type_name(oid), NULL, 0);
if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err;
if (fmt & ASN1_FMT_FULL)
x509_directory_name_print(fp, fmt, ind, "value", tag, val, vlen);
else x509_directory_name_print(fp, fmt, ind, x509_name_type_name(oid), tag, val, vlen);
if (oid == OID_email_address) {
if (asn1_ia5_string_from_der((const char **)&val, &vlen, &d, &dlen) != 1) goto err;
format_string(fp, fmt, ind, "value", val, vlen);
} else {
if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err;
x509_directory_name_print(fp, fmt, ind, "value", tag, val, vlen);
}
} else {
if (x509_name_type_from_der(&oid, &d, &dlen) != 1) { error_print(); goto err; }
if (oid == OID_email_address) {
if (asn1_ia5_string_from_der((const char **)&val, &vlen, &d, &dlen) != 1) goto err;
format_string(fp, fmt, ind, "emailAddress", val, vlen);
} else {
if (x509_directory_name_from_der(&tag, &val, &vlen, &d, &dlen) != 1) goto err;
x509_directory_name_print(fp, fmt, ind, x509_name_type_name(oid), tag, val, vlen);
}
}
if (asn1_length_is_zero(dlen) != 1) goto err;
return 1;
err:
@@ -398,12 +408,17 @@ int x509_rdn_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
}
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) {
error_print();
return -1;
}
x509_attr_type_and_value_print(fp, fmt, ind, "AttributeTypeAndValue", p, len);
while (dlen) {
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) {
error_print();
return -1;
}
x509_attr_type_and_value_print(fp, fmt, ind, "AttributeTypeAndValue", p, len);
x509_attr_type_and_value_print(fp, fmt, ind + 4, "AttributeTypeAndValue", p, len);
}
return 1;
}
@@ -532,21 +547,43 @@ int x509_name_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
return 1;
}
int x509_name_get_printable(const uint8_t *d, size_t dlen, char *str, size_t maxlen)
{
error_print();
return -1;
}
int x509_name_get_value_by_type(const uint8_t *d, size_t dlen, int oid, int *tag, const uint8_t **val, size_t *vlen)
{
error_print();
return -1;
const uint8_t *rdn_d;
size_t rdn_dlen;
while (dlen) {
int attr_oid;
int attr_tag;
const uint8_t *attr_val;
size_t attr_vlen;
if (asn1_set_from_der(&rdn_d, &rdn_dlen, &d, &dlen) != 1) {
error_print();
return -1;
}
while (rdn_dlen) {
if (x509_attr_type_and_value_from_der(&attr_oid, &attr_tag, &attr_val, &attr_vlen,
&rdn_d, &rdn_dlen) != 1) {
error_print();
return -1;
}
}
if (attr_oid == oid) {
*tag = attr_tag;
*val = attr_val;
*vlen = attr_vlen;
return 1;
}
}
return 0;
}
int x509_name_get_common_name(const uint8_t *d, size_t dlen, int *tag, const uint8_t **val, size_t *vlen)
{
error_print();
int ret;
ret = x509_name_get_value_by_type(d, dlen, OID_at_common_name, tag, val, vlen);
if (ret < 0) error_print();
return -1;
}
@@ -653,6 +690,7 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
}
break;
case OID_ce_key_usage:
case OID_netscape_cert_type:
if (asn1_bits_from_der(&ival, &val, &vlen) != 1) {
error_print();
return -1;
@@ -665,6 +703,11 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
}
break;
case OID_netscape_cert_comment:
if (asn1_ia5_string_from_der((const char **)&p, &len, &val, &vlen) != 1) {
error_print();
return -1;
}
break;
case OID_ct_precertificate_scts:
case OID_undef:
p = val;
@@ -700,6 +743,7 @@ int x509_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
case OID_ce_crl_distribution_points: return x509_crl_distribution_points_print(fp, fmt, ind, name, p, len);
case OID_ce_inhibit_any_policy: format_print(fp, fmt, ind, "%s: %d\n", name, ival);
case OID_ce_freshest_crl: return x509_freshest_crl_print(fp, fmt, ind, name, p, len);
case OID_netscape_cert_type: return x509_netscape_cert_type_print(fp, fmt, ind, name, ival);
case OID_netscape_cert_comment: return format_string(fp, fmt, ind, name, p, len);
default: format_bytes(fp, fmt, ind, "extnValue", p, len);
}
@@ -1132,12 +1176,15 @@ int x509_cert_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1
|| asn1_length_is_zero(alen) != 1) {
if (asn1_sequence_from_der(&d, &dlen, &a, &alen) != 1) {
error_print();
return -1;
}
x509_certificate_print(fp, fmt, ind, label, d, dlen);
if (asn1_length_is_zero(alen) != 1) {
error_print();
return -1;
}
return 1;
}
@@ -1307,10 +1354,27 @@ int x509_certs_to_pem(const uint8_t *d, size_t dlen, FILE *fp)
return 1;
}
int x509_certs_from_pem(const uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp)
int x509_certs_from_pem(uint8_t *d, size_t *dlen, size_t maxlen, FILE *fp)
{
error_print();
return -1;
int ret;
size_t len, total_len = 0;
for (;;) {
if ((ret = x509_cert_from_pem(d, &len, maxlen, fp)) < 0) {
error_print();
return -1;
} else if (ret == 0) {
break;
}
d += len;
total_len += len;
maxlen -= len;
}
*dlen = total_len;
if (!total_len) {
return 0;
}
return 1;
}
int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt)
@@ -1324,15 +1388,42 @@ int x509_certs_get_count(const uint8_t *d, size_t dlen, size_t *cnt)
int x509_certs_get_cert_by_index(const uint8_t *d, size_t dlen, int index, const uint8_t **cert, size_t *certlen)
{
error_print();
return -1;
const uint8_t *a;
size_t alen;
int ret, i;
for (i = 0; i <= index; i++) {
if ((ret = x509_cert_from_der(&a, &alen, &d, &dlen)) != 1) {
if (ret < 0) error_print();
else error_print();
return -1;
}
}
*cert = a;
*certlen = alen;
return 1;
}
int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen,
const uint8_t *subject, size_t subject_len, const uint8_t **cert, size_t *certlen)
{
error_print();
return -1;
const uint8_t *a;
size_t alen;
const uint8_t *subj;
size_t subj_len;
while (dlen) {
if (x509_cert_from_der(&a, &alen, &d, &dlen) != 1) {
error_print();
return -1;
}
if (subj_len == subject_len && memcmp(subj, subject, subj_len) == 0) {
*cert = a;
*certlen = alen;
return 1;
}
}
return 0;
}
int x509_certs_get_cert_by_issuer_and_serial_number(

View File

@@ -416,7 +416,6 @@ const char *x509_crl_ext_id_name(int oid)
{
const ASN1_OID_INFO *info;
if (!(info = asn1_oid_info_from_oid(x509_crl_exts, x509_crl_exts_count, oid))) {
error_print();
return NULL;
}
return info->name;
@@ -449,7 +448,7 @@ int x509_crl_ext_id_to_der(int oid, uint8_t **out, size_t *outlen)
return 1;
}
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)
{
int ret;
const uint8_t *p;
@@ -457,11 +456,13 @@ int x509_crl_ext_id_from_der(int *oid, const uint8_t **in, size_t *inlen)
const ASN1_OID_INFO *info;
*oid = 0;
if ((ret = asn1_oid_info_from_der(&info, x509_crl_exts, x509_crl_exts_count, in, inlen)) != 1) {
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;
}
*oid = info->oid;
if (info) {
*oid = info->oid;
}
return ret;
}
@@ -635,13 +636,15 @@ int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint
size_t vlen;
const uint8_t *p;
size_t len;
uint32_t nodes[32];
size_t nodes_cnt;
int num;
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
if (x509_crl_ext_id_from_der(&oid, &d, &dlen) != 1) goto err;
format_print(fp, fmt, ind, "extnID: %s\n", x509_crl_ext_id_name(oid));
if (x509_crl_ext_id_from_der_ex(&oid, nodes, &nodes_cnt, &d, &dlen) != 1) goto err;
asn1_object_identifier_print(fp, fmt, ind, "extnID", x509_crl_ext_id_name(oid), nodes, nodes_cnt);
if ((ret = asn1_boolean_from_der(&critical, &d, &dlen)) < 0) goto err;
if (ret) format_print(fp, fmt, ind, "critical: %s\n", asn1_boolean_name(critical));
if (asn1_octet_string_from_der(&v, &vlen, &d, &dlen) != 1) goto err;
@@ -664,6 +667,11 @@ int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint
return -1;
}
break;
default:
if (asn1_any_from_der(&p, &len, &v, &vlen) != 1) {
error_print();
return -1;
}
}
name = x509_crl_ext_id_name(oid);
@@ -676,6 +684,7 @@ int x509_crl_ext_print(FILE *fp, int fmt, int ind, const char *label, const uint
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;
default: format_bytes(fp, fmt, ind, "value", p, len);
}
if (asn1_length_is_zero(vlen) != 1) goto err;
return 1;
@@ -873,12 +882,22 @@ err:
// FIXME: 这两个函数应该检查CRL格式是否正确
int x509_crl_to_der(const uint8_t *a, size_t alen, uint8_t **out, size_t *outlen)
{
return asn1_any_to_der(a, alen, out, outlen);
int ret;
if ((ret = asn1_any_to_der(a, alen, out, outlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
int x509_crl_from_der(const uint8_t **a, size_t *alen, const uint8_t **in, size_t *inlen)
{
return asn1_any_from_der(a, alen, in, inlen);
int ret;
if ((ret = asn1_any_from_der(a, alen, in, inlen)) != 1) {
if (ret < 0) error_print();
return ret;
}
return 1;
}
int x509_crl_to_pem(const uint8_t *a, size_t alen, FILE *fp)
@@ -900,6 +919,44 @@ 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) {
error_print();
return -1;
}
return 1;
}
int x509_crl_from_fp(uint8_t *a, size_t *alen, size_t maxlen, FILE *fp)
{
size_t len;
const uint8_t *d = a;
size_t dlen;
const uint8_t *crl;
size_t crl_len;
if (!(len = fread(a, 1, maxlen, fp))) {
if (feof(fp)) {
return 0;
} else {
error_print();
return -1;
}
}
dlen = len;
if (x509_crl_from_der(&crl, &crl_len, &d, &dlen) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
*alen = len;
return 1;
}
int x509_crl_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen)
{
const uint8_t *d;

View File

@@ -463,16 +463,17 @@ int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, con
return ret;
}
switch (tag) {
case ASN1_TAG_IMPLICIT(0): *choice = 0; break;
case ASN1_TAG_EXPLICIT(0): *choice = 0; break;
case ASN1_TAG_IMPLICIT(1): *choice = 1; break;
case ASN1_TAG_IMPLICIT(2): *choice = 2; break;
case ASN1_TAG_IMPLICIT(3): *choice = 3; break;
case ASN1_TAG_IMPLICIT(4): *choice = 4; break;
case ASN1_TAG_IMPLICIT(5): *choice = 5; break;
case ASN1_TAG_EXPLICIT(3): *choice = 3; break;
case ASN1_TAG_EXPLICIT(4): *choice = 4; break;
case ASN1_TAG_EXPLICIT(5): *choice = 5; break;
case ASN1_TAG_IMPLICIT(6): *choice = 6; break;
case ASN1_TAG_IMPLICIT(7): *choice = 7; break;
case ASN1_TAG_IMPLICIT(8): *choice = 8; break;
default:
fprintf(stderr, "%s %d: tag = %x\n", __FILE__, __LINE__, tag);
error_print();
return -1;
}
@@ -481,9 +482,24 @@ int x509_general_name_from_der(int *choice, const uint8_t **d, size_t *dlen, con
int x509_general_name_print(FILE *fp, int fmt, int ind, const char *label, int choice, const uint8_t *d, size_t dlen)
{
const uint8_t *p;
size_t len;
format_print(fp, fmt, ind, "%s\n", label);
ind += 4;
switch (choice) {
case 0:
case 3:
case 4:
case 5:
if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) {
error_print();
return -1;
}
d = p;
dlen = len;
}
switch (choice) {
case 0: return x509_other_name_print(fp, fmt, ind, "otherName", d, dlen);
case 1: return asn1_string_print(fp, fmt, ind, "rfc822Name", ASN1_TAG_IA5String, d, dlen);
@@ -1211,19 +1227,18 @@ int x509_basic_constraints_from_der(int *ca, int *path_len_cons, const uint8_t *
if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) {
if (ret < 0) error_print();
else {
*ca = -1;
*path_len_cons = -1;
};
return ret;
}
if (asn1_boolean_from_der(ca, &d, &dlen) < 0
|| asn1_int_from_der(path_len_cons, &d, &dlen) < 0
|| asn1_check(ca >= 0 || path_len_cons >= 0) != 1
|| asn1_length_is_zero(dlen) != 1) {
error_print();
return -1;
}
if (*ca < 0 && *path_len_cons < 0) {
error_print();
return -1;
}
if (*ca < 0) *ca = 0;
return 1;
}
@@ -1237,6 +1252,7 @@ int x509_basic_constraints_print(FILE *fp, int fmt, int ind, const char *label,
if ((ret = asn1_boolean_from_der(&val, &d, &dlen)) < 0) goto err;
if (ret) format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(val));
else format_print(fp, fmt, ind, "cA: %s\n", asn1_boolean_name(0)); // 特殊对待无论cA值是否编码均输出结果
if ((ret = asn1_int_from_der(&val, &d, &dlen)) < 0) goto err;
if (ret) format_print(fp, fmt, ind, "pathLenConstraint: %d\n", val);
if (asn1_length_is_zero(dlen) != 1) goto err;
@@ -1748,3 +1764,21 @@ int x509_distribution_points_print(FILE *fp, int fmt, int ind, const char *label
}
return 1;
}
static const char *netscape_cert_types[] = {
"SSL Client certificate",
"SSL Server certificate",
"S/MIME certificate",
"Object-signing certificate",
"Reserved for future use",
"SSL CA certificate",
"S/MIME CA certificate",
"Object-signing CA certificate",
};
int x509_netscape_cert_type_print(FILE *fp, int fmt, int ind, const char *label, int bits)
{
return asn1_bits_print(fp, fmt, ind, label, netscape_cert_types,
sizeof(netscape_cert_types)/sizeof(netscape_cert_types[0]), bits);
}

View File

@@ -75,6 +75,7 @@ static uint32_t oid_at_country_name[] = { oid_at,6 };
static uint32_t oid_at_serial_number[] = { oid_at,5 };
static uint32_t oid_at_pseudonym[] = { oid_at,65 };
static uint32_t oid_domain_component[] = { 0,9,2342,19200300,100,1,25 };
static uint32_t oid_email_address[] = { 1,2,840,113549,1,9,1 };
#define OID_AT_CNT (sizeof(oid_at_name)/sizeof(int))
@@ -95,6 +96,7 @@ static const ASN1_OID_INFO x509_name_types[] = {
{ OID_at_serial_number, "serialNumber", oid_at_serial_number, OID_AT_CNT },
{ OID_at_pseudonym, "pseudonym", oid_at_pseudonym, OID_AT_CNT },
{ OID_domain_component, "domainComponent", oid_domain_component, sizeof(oid_domain_component)/sizeof(int) },
{ OID_email_address, "emailAddress", oid_email_address, sizeof(oid_email_address)/sizeof(int) },
};
static const int x509_name_types_count
@@ -168,6 +170,7 @@ static uint32_t oid_ce_crl_reasons[] = { oid_ce,21 }; // crl_entry_ext
static uint32_t oid_ce_invalidity_date[] = { oid_ce,24 }; // crl_entry_ext
static uint32_t oid_ce_certificate_issuer[] = { oid_ce,29 }; // crl_entry_ext
#define OID_CE_CNT sizeof(oid_ce_subject_directory_attributes)/sizeof(int)
static uint32_t oid_netscape_cert_type[] = { 2,16,840,1,113730,1,1 };
static uint32_t oid_netscape_cert_comment[] = { 2,16,840,1,113730,1,13 };
static uint32_t oid_cert_authority_info_access[] = { 1,3,6,1,5,5,7,1,1 };
static uint32_t oid_ct_precertificate_scts[] = { 1,3,6,1,4,1,11129,2,4,2 };
@@ -191,6 +194,7 @@ static const ASN1_OID_INFO x509_ext_ids[] = {
{ OID_ce_crl_reasons, "CRLReasons", oid_ce_crl_reasons, OID_CE_CNT },
{ OID_ce_invalidity_date, "InvalidityDate", oid_ce_invalidity_date, OID_CE_CNT },
{ OID_ce_certificate_issuer, "CertificateIssuer", oid_ce_certificate_issuer, OID_CE_CNT },
{ OID_netscape_cert_type, "NetscapeCertType", oid_netscape_cert_type, sizeof(oid_netscape_cert_type)/sizeof(int) },
{ OID_netscape_cert_comment, "NetscapeCertComment", oid_netscape_cert_comment, sizeof(oid_netscape_cert_comment)/sizeof(int) },
{ OID_cert_authority_info_access, "CertificateAuthorityInformationAccess", oid_cert_authority_info_access, sizeof(oid_cert_authority_info_access)/sizeof(int) },
{ OID_ct_precertificate_scts, "CT-PrecertificateSCTs", oid_ct_precertificate_scts, sizeof(oid_ct_precertificate_scts)/sizeof(int) },

View File

@@ -53,7 +53,7 @@
#include <gmssl/digest.h>
const char *digests[] = {
"md5",
// "md5",
"sha1",
"sm3",
"sha224",

View File

@@ -47,14 +47,22 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/mem.h>
#include <gmssl/rand.h>
#include <gmssl/pkcs8.h>
#include <gmssl/error.h>
#include <gmssl/x509.h>
#include <gmssl/x509_ext.h>
#include <gmssl/pkcs8.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num "
"-key file [-pass pass] "
"[-key_usage str]* [-out file]";
static int ext_key_usage_set(int *usages, const char *usage_name)
{
@@ -67,18 +75,6 @@ static int ext_key_usage_set(int *usages, const char *usage_name)
return 1;
}
#ifndef WIN32
#include <pwd.h>
#include <unistd.h>
#endif
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num "
"-key file [-pass pass] "
"[-key_usage str]*";
int certgen_main(int argc, char **argv)
{
int ret = 1;
@@ -91,12 +87,10 @@ int certgen_main(int argc, char **argv)
char *common_name = NULL;
int days = 0;
int key_usage = 0;
char *file = NULL;
FILE *outfp = stdout;
FILE *keyfp = NULL;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
SM2_KEY sm2_key;
uint8_t serial[12];
uint8_t name[256];
size_t namelen;
@@ -105,17 +99,25 @@ int certgen_main(int argc, char **argv)
uint8_t uniq_id[32];
uint8_t exts[512];
size_t extslen = 0;
FILE *keyfp = NULL;
SM2_KEY sm2_key;
uint8_t cert[1024];
size_t certlen;
FILE *outfp = stdout;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
help:
printf("usage: %s %s\n", prog, options);
return 0;
ret = 0;
goto end;
} else if (!strcmp(*argv, "-CN")) {
if (--argc < 1) goto bad;
common_name = *(++argv);
@@ -137,64 +139,66 @@ help:
} 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_usage")) {
if (--argc < 1) goto bad;
if (ext_key_usage_set(&key_usage, *(++argv)) != 1) {
error_print();
return -1;
fprintf(stderr, "%s: invalid -key_usage value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
file = *(++argv);
if (!(keyfp = fopen(file, "r"))) {
error_print();
return -1;
keyfile = *(++argv);
if (!(keyfp = fopen(keyfile, "r"))) {
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;
file = *(++argv);
if (!(outfp = fopen(file, "w"))) {
error_print();
return -1;
outfile = *(++argv);
if (!(outfp = fopen(outfile, "w"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
goto end;
}
} else {
bad:
fprintf(stderr, "%s: illegal option '%s'\n", prog, *argv);
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (!common_name || days <= 0) {
fprintf(stderr, "%s: missing options\n", prog);
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
if (!common_name) {
fprintf(stderr, "%s: '-CN' option required\n", prog);
goto end;
}
if (!days) {
fprintf(stderr, "%s: '-days' option required\n", prog);
goto end;
}
if (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
goto end;
}
if (!pass) {
pass = getpass("Encryption Password : ");
}
if (!pass || strlen(pass) == 0) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
error_print();
return -1;
}
if (keyfp == NULL) {
error_print();
return -1;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
error_print();
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;
}
time(&not_before);
if (rand_bytes(serial, sizeof(serial)) != 1
|| x509_name_set(name, &namelen, sizeof(name),
@@ -213,14 +217,19 @@ bad:
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1
|| x509_cert_to_pem(cert, certlen, outfp) != 1) {
error_print();
return -1;
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {
fprintf(stderr, "%s: output certificate failed\n", prog);
goto end;
}
ret = 0;
end:
memset(&sm2_key, 0, sizeof(SM2_KEY));
gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
if (keyfp) fclose(keyfp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -47,20 +47,23 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/error.h>
static const char *options = "[-in file]";
static const char *options = "[-in file] [-out file]";
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;
@@ -70,38 +73,49 @@ int certparse_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
return 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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: llegal option '%s'\n", prog, *argv);
printf("usage: %s %s\n", prog, options);
return 1;
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (infile) {
if (!(infp = fopen(infile, "r"))) {
error_print();
return -1;
for (;;) {
int rv;
if ((rv = x509_cert_from_pem(cert, &certlen, sizeof(cert), infp)) != 1) {
if (rv < 0) fprintf(stderr, "%s: read certificate failure\n", prog);
else ret = 0;
goto end;
}
x509_cert_print(outfp, 0, 0, "Certificate", cert, certlen);
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {
fprintf(stderr, "%s: output certficate failure\n", prog);
goto end;
}
}
for (;;) {
int ret;
if ((ret = x509_cert_from_pem(cert, &certlen, sizeof(cert), infp)) < 0) {
error_print();
return -1;
} else if (!ret) {
break;
}
x509_cert_print(stdout, 0, 0, "Certificate", cert, certlen);
x509_cert_to_pem(cert, certlen, stdout);
}
return 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -47,94 +47,98 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/pkcs8.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
// 验证证书链是一个重量级的功能,应准备相应的文档,列举所有验证项目
// 比如最基本的是证书中的签名、有效期、各个扩展等
// 外部相关的证书链、CRL等
static const char *options = "[-in pem] -cacert pem (-id str)\n";
int certverify_main(int argc, char **argv)
{
int ret = 0;
int ret = 1;
char *prog = argv[0];
char *certfile = NULL;
FILE *certfp = NULL;
char *infile = NULL;
char *cacertfile = NULL;
FILE *infp = stdin;
FILE *cacertfp = NULL;
uint8_t cert[1024];
size_t certlen;
const uint8_t *issuer;
size_t issuer_len;
uint8_t cacert[1024];
size_t cacertlen;
char *signer_id = SM2_DEFAULT_ID;
SM2_KEY ca_pubkey;
int rv;
argc--;
argv++;
while (argc >= 1) {
if (!strcmp(*argv, "-help")) {
printf("Usage: %s [-cert pem] -cacert pem\n", prog);
return 0;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-cert")) {
if (--argc < 1) goto bad;
certfile = *(++argv);
if (!(certfp = fopen(certfile, "r"))) {
error_print();
return -1;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-cacert")) {
if (--argc < 1) goto bad;
cacertfile = *(++argv);
if (!(cacertfp = fopen(cacertfile, "r"))) {
error_print();
return -1;
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, cacertfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-id")) {
if (--argc < 1) goto bad;
signer_id = *(++argv);
} else {
printf("Usage: %s [-cert pem] -cacert pem\n", prog);
return 0;
break;
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 (!certfp || !cacertfp) {
error_print();
return -1;
if (!cacertfile) {
fprintf(stderr, "%s: '-cacert' option required\n", prog);
goto end;
}
if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) {
error_print();
return -1;
if (x509_cert_from_pem(cert, &certlen, sizeof(cert), infp) != 1) {
fprintf(stderr, "%s: read certificate failure\n", prog);
goto end;
}
if (x509_cert_from_pem(cacert, &cacertlen, sizeof(cacert), cacertfp) != 1) {
error_print();
return -1;
if (x509_cert_get_subject(cert, certlen, &issuer, &issuer_len) != 1) {
fprintf(stderr, "%s: parse certificate error\n", prog);
goto end;
}
if (x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, signer_id, strlen(signer_id)) != 1) {
error_print();
return -1;
if (x509_cert_from_pem_by_subject(cacert, &cacertlen, sizeof(cacert), issuer, issuer_len, cacertfp) != 1) {
fprintf(stderr, "%s: load CA certificate failure\n", prog);
goto end;
}
ret = 1;
printf("Verification %s\n", ret ? "success" : "failure");
if ((rv = x509_cert_verify_by_ca_cert(cert, certlen, cacert, cacertlen, signer_id, strlen(signer_id))) < 0) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
printf("Verification %s\n", rv ? "success" : "failure");
ret = 0;
goto end;
bad:
fprintf(stderr, "%s: commands should not be used together\n", prog);
end:
if (infile && infp) fclose(infp);
if (cacertfp) fclose(cacertfp);
return ret;
}

215
tools/cmsdecrypt.c Normal file
View File

@@ -0,0 +1,215 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <gmssl/x509.h>
#include <gmssl/cms.h>
static const char *options = "-key file -pass str -cert file -in file [-out file]";
int cmsdecrypt_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *keyfile = NULL;
char *pass = NULL;
char *certfile = NULL;
char *infile = NULL;
char *outfile = NULL;
FILE *keyfp = NULL;
FILE *certfp = NULL;
FILE *infp = NULL;
FILE *outfp = stdout;
uint8_t cert[1024];
size_t certlen;
struct stat st;
uint8_t *cms = NULL;
size_t cmslen, cms_maxlen;
SM2_KEY key;
int content_type;
uint8_t *content = NULL;
size_t content_len;
const uint8_t *rcpt_infos;
size_t rcpt_infos_len;
const uint8_t *shared_info1;
const uint8_t *shared_info2;
size_t shared_info1_len, shared_info2_len;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
keyfile = *(++argv);
if (!(keyfp = fopen(keyfile, "r"))) {
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, "-cert")) {
if (--argc < 1) goto bad;
certfile = *(++argv);
if (!(certfp = fopen(certfile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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 (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
goto end;
}
if (!certfile) {
fprintf(stderr, "%s: '-cert' option required\n", prog);
goto end;
}
if (!infile) {
fprintf(stderr, "%s: '-in' option required\n", prog);
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) {
fprintf(stderr, "%s: private key decryption failure\n", prog);
goto end;
}
if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) {
fprintf(stderr, "%s: load certificate failure\n", prog);
goto end;
}
fstat(fileno(infp), &st);
cms_maxlen = (st.st_size * 3)/4 + 1;
if (!(cms = malloc(cms_maxlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) {
fprintf(stderr, "%s: read CMS failure\n", prog);
goto end;
}
if (!(content = malloc(cmslen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_deenvelop(cms, cmslen,
&key, cert, certlen,
&content_type, content, &content_len,
&rcpt_infos, &rcpt_infos_len,
&shared_info1, &shared_info1_len,
&shared_info2, &shared_info2_len) != 1) {
fprintf(stderr, "%s: decryption failure\n", prog);
goto end;
}
if (content_type != OID_cms_data) {
fprintf(stderr, "%s: invalid CMS content type: %s\n", prog, cms_content_type_name(content_type));
goto end;
}
if (fwrite(content, 1, content_len, outfp) != content_len) {
fprintf(stderr, "%s: output failure : %s\n", prog, strerror(errno));
goto end;
}
ret = 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
if (keyfile && keyfp) fclose(keyfp);
if (cms) free(cms);
if (content) free(content);
return ret;
}

270
tools/cmsencrypt.c Normal file
View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <gmssl/cms.h>
#include <gmssl/x509.h>
#include <gmssl/rand.h>
/*
签名的时候要提供签名者的证书,并且提供签名私钥
但是验证的时候假定CMS中已经包含签名者的证书了但是我们要提供CA证书库
加密的时候要指定接收者的证书,并且可以有多个接收者
解密的时候只提供一个解密私钥,但是最好配合解密者的证书,从这个证书中找到解密者的名字
如果即加密又签名那么输出的是SignedAndEnveloped
CMS有PEM吗
cms -encrypt -rcpt a.pem -rcpt b.pem -rcpt c.pem -in file -sign -signcert a.pem -signcert b.pem
-rcptcert -rcpt_cert -sign_cert b.pem -signkey
首先接收者可以有多个证书
这里面有个问题,因为我们要输出一个加密的对象,因此我们必须把输入的内容读取进来。
EnvelopedData 是一个封装的SEQUENCE中因此必须读取所有的内容。
如果是一个文件就需要读取所有的文件内容如果是一个stream ,也需要读取完整的内容到一个足够大的buffer中如何设置这个buffer的大小呢
对于输入文件如果输入有文件名的话可以直接通过stat获取文件长度
但是如果对于stream的话实际上我们是没有办法获得输入长度的那么就直接准备一个buffer好了。
不要给自己找麻烦了,直接只支持文件输入吧
encrypt
*/
static const char *options = "-encrypt (-rcptcert pem)* -in file -out file";
static int get_files_size(int argc, char **argv, const char *option, size_t *len)
{
char *prog = argv[0];
char *file = NULL;
FILE *fp = NULL;
struct stat st;
argc--;
argv++;
*len = 0;
while (argc > 1) {
if (!strcmp(*argv, option)) {
if (--argc < 1) {
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
return -1;
}
file = *(++argv);
if (!(fp = fopen(file, "r"))) {
fprintf(stderr, "%s: open '%s' failed : %s\n", prog, file, strerror(errno));
return -1;
}
if (fstat(fileno(fp), &st) < 0) {
fprintf(stderr, "%s: access '%s' failed : %s\n", prog, file, strerror(errno));
fclose(fp);
return -1;
}
*len += st.st_size;
fclose(fp);
}
argc--;
argv++;
}
return 1;
}
int cmsencrypt_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
int op = 0;
char *infile = NULL;
char *outfile = NULL;
FILE *infp = stdin;
FILE *outfp = stdout;
uint8_t *rcpt_certs = NULL;
size_t rcpt_certs_len;
uint8_t key[16];
uint8_t iv[16];
uint8_t *inbuf = NULL;
size_t inlen;
uint8_t *cms = NULL;
size_t cmslen;
uint8_t *cert;
if (argc < 2) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
// 预先统计证书缓冲大小和输入大小
if (get_files_size(argc, argv, "-rcptcert", &rcpt_certs_len) != 1) {
goto end;
}
if (rcpt_certs_len <= 0) {
fprintf(stderr, "%s: invalid cert length\n", prog);
goto end;
}
rcpt_certs_len = (rcpt_certs_len * 3)/4;
if (!(rcpt_certs = malloc(rcpt_certs_len))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
cert = rcpt_certs;
if (get_files_size(argc, argv, "-in", &inlen) != 1) {
goto end;
}
if (inlen <= 0) {
fprintf(stderr, "%s: invalid input length\n", prog);
goto end;
}
if (!(inbuf = malloc(inlen))) {
fprintf(stderr, "%s: %s\n", prog, strerror(errno));
goto end;
}
argc--;
argv++;
while (argc > 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-rcptcert")) {
char *certfile;
FILE *certfp;
size_t certlen;
if (--argc < 1) goto bad;
certfile = *(++argv);
if (!(certfp = fopen(certfile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
goto end;
}
if (x509_cert_from_pem(cert, &certlen, rcpt_certs_len, certfp) != 1) {
fprintf(stderr, "%s: error\n", prog);
fclose(certfp);
goto end;
}
cert += certlen;
fclose(certfp);
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, strerror(errno));
goto end;
}
if ((inlen = fread(inbuf, 1, inlen, infp)) <= 0) {
fprintf(stderr, "%s: read data error: %s\n", prog, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
outfile = *(++argv);
if (!(outfp = fopen(outfile, "w"))) {
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++;
}
rcpt_certs_len = cert - rcpt_certs;
if (rand_bytes(key, sizeof(key)) != 1
|| rand_bytes(iv, sizeof(iv)) != 1
|| cms_envelop(NULL, &cmslen, rcpt_certs, rcpt_certs_len,
OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv),
OID_cms_data, inbuf, inlen, NULL, 0, NULL, 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
if (!(cms = malloc(cmslen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_envelop(cms, &cmslen, rcpt_certs, rcpt_certs_len,
OID_sm4_cbc, key, sizeof(key), iv, sizeof(iv),
OID_cms_data, inbuf, inlen, NULL, 0, NULL, 0) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
if (cms_to_pem(cms, cmslen, outfp) != 1) {
fprintf(stderr, "%s: output CMS failure\n", prog);
goto end;
}
ret = 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
if (rcpt_certs) free(rcpt_certs);
if (cms) free(cms);
return ret;
}

126
tools/cmsparse.c Normal file
View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <gmssl/cms.h>
#include <gmssl/x509.h>
#include <gmssl/rand.h>
static const char *options = "-in file";
int cmsparse_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
FILE *infp = stdin;
struct stat st;
uint8_t *cms = NULL;
size_t cms_maxlen, cmslen;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, infile, 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 (!infile) {
fprintf(stderr, "%s: option '-in' required'\n", prog);
goto end;
}
if (fstat(fileno(infp), &st) < 0) {
fprintf(stderr, "%s: access '%s' failed : %s\n", prog, infile, strerror(errno));
goto end;
}
cms_maxlen = (st.st_size * 3)/4 + 1;
if (!(cms = malloc(cms_maxlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) {
fprintf(stderr, "%s: parse CMS error\n", prog);
goto end;
}
cms_print(stdout, 0, 0, "CMS", cms, cmslen);
ret = 0;
end:
if (infp) fclose(infp);
if (cms) free(cms);
return ret;
}

246
tools/cmssign.c Normal file
View File

@@ -0,0 +1,246 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <gmssl/x509.h>
#include <gmssl/cms.h>
#include <gmssl/error.h>
/*
302 typedef struct {
303 uint8_t *certs;
304 size_t certs_len;
305 SM2_KEY *sign_key;
306 } CMS_CERTS_AND_KEY;
输出长度主要由输入长度和
*/
static const char *options = "-key file -pass str -cert file -in file [-out file]";
int cmssign_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *keyfile = NULL;
char *pass = NULL;
char *certfile = NULL;
char *infile = NULL;
char *outfile = NULL;
FILE *keyfp = NULL;
FILE *certfp = NULL;
FILE *infp = NULL;
FILE *outfp = stdout;
SM2_KEY key;
uint8_t cert[1024];
size_t certlen;
struct stat st;
uint8_t *in = NULL;
size_t inlen;
uint8_t *cms = NULL;
size_t cmslen, cms_maxlen;
CMS_CERTS_AND_KEY cert_and_key;
int content_type;
uint8_t *content = NULL;
size_t content_len;
const uint8_t *rcpt_infos;
size_t rcpt_infos_len;
const uint8_t *shared_info1;
const uint8_t *shared_info2;
size_t shared_info1_len, shared_info2_len;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
keyfile = *(++argv);
if (!(keyfp = fopen(keyfile, "r"))) {
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, "-cert")) {
if (--argc < 1) goto bad;
certfile = *(++argv);
if (!(certfp = fopen(certfile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, certfile, strerror(errno));
goto end;
}
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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 (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
goto end;
}
if (!pass) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
goto end;
}
if (!certfile) {
fprintf(stderr, "%s: '-cert' option required\n", prog);
goto end;
}
if (!infile) {
fprintf(stderr, "%s: '-in' option required\n", prog);
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) {
fprintf(stderr, "%s: private key decryption failure\n", prog);
goto end;
}
if (x509_cert_from_pem(cert, &certlen, sizeof(cert), certfp) != 1) {
fprintf(stderr, "%s: load certificate failure\n", prog);
goto end;
}
{
SM2_KEY public_key;
if (x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) {
fprintf(stderr, "%s: parse certficate failure\n", prog);
goto end;
}
if (sm2_public_key_equ(&key, &public_key) != 1) {
fprintf(stderr, "%s: key and cert are not match!\n", prog);
goto end;
}
}
cert_and_key.certs = cert;
cert_and_key.certs_len = certlen;
cert_and_key.sign_key = &key;
if (fstat(fileno(infp), &st) < 0) {
fprintf(stderr, "%s: access file error : %s\n", prog, strerror(errno));
goto end;
}
if ((inlen = st.st_size) <= 0) {
fprintf(stderr, "%s: invalid input length\n", prog);
goto end;
}
if (!(in = malloc(inlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (fread(in, 1, inlen, infp) != inlen) {
fprintf(stderr, "%s: read file error : %s\n", prog, strerror(errno));
goto end;
}
cms_maxlen = (inlen * 4)/3 + 4096; // 主要由SignerInfos其中的DN长度决定
if (!(cms = malloc(cms_maxlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_sign(cms, &cmslen, &cert_and_key, 1, OID_cms_data, in, inlen, NULL, 0) != 1) {
fprintf(stderr, "%s: sign failure\n", prog);
goto end;
}
if (cms_to_pem(cms, cmslen, outfp) != 1) {
fprintf(stderr, "%s: output failure\n", prog);
goto end;
}
ret = 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
if (keyfile && keyfp) fclose(keyfp);
if (cms) free(cms);
if (in) free(in);
return ret;
}

177
tools/cmsverify.c Normal file
View File

@@ -0,0 +1,177 @@
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. All advertising materials mentioning features or use of this
* software must display the following acknowledgment:
* "This product includes software developed by the GmSSL Project.
* (http://gmssl.org/)"
*
* 4. The name "GmSSL Project" must not be used to endorse or promote
* products derived from this software without prior written
* permission. For written permission, please contact
* guanzhi1980@gmail.com.
*
* 5. Products derived from this software may not be called "GmSSL"
* nor may "GmSSL" appear in their names without prior written
* permission of the GmSSL Project.
*
* 6. Redistributions of any form whatsoever must retain the following
* acknowledgment:
* "This product includes software developed by the GmSSL Project
* (http://gmssl.org/)"
*
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <gmssl/cms.h>
#include <gmssl/x509.h>
#include <gmssl/rand.h>
static const char *options = "-in file [-out file]";
int cmsverify_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
char *outfile = NULL;
FILE *infp = NULL;
FILE *outfp = NULL;
struct stat st;
uint8_t *cms = NULL;
size_t cmslen, cms_maxlen;
int content_type;
const uint8_t *content;
size_t content_len;
const uint8_t *certs;
size_t certslen;
const uint8_t *crls;
size_t crlslen;
const uint8_t *signer_infos;
size_t signer_infos_len;
int rv;
argc--;
argv++;
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 1) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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 (!infile) {
fprintf(stderr, "%s: '-in' option required\n", prog);
goto end;
}
fstat(fileno(infp), &st);
cms_maxlen = (st.st_size * 3)/4 + 1;
if (!(cms = malloc(cms_maxlen))) {
fprintf(stderr, "%s: malloc failure\n", prog);
goto end;
}
if (cms_from_pem(cms, &cmslen, cms_maxlen, infp) != 1) {
fprintf(stderr, "%s: read CMS failure\n", prog);
goto end;
}
if ((rv = cms_verify(cms, cmslen, NULL, 0, NULL, 0,
&content_type, &content, &content_len,
&certs, &certslen, &crls, &crlslen,
&signer_infos, &signer_infos_len)) < 0) {
fprintf(stderr, "%s: verify error\n", prog);
goto end;
}
printf("verify %s\n", rv ? "success" : "failure");
ret = rv ? 0 : 1;
if (outfile) {
const uint8_t *p;
size_t len;
if (content_type == OID_cms_data) {
if (asn1_octet_string_from_der(&p, &len, &content, &content_len) != 1
|| asn1_length_is_zero(content_len) != 1) {
fprintf(stderr, "%s: invalid CMS\n", prog);
goto end;
}
if (len != fwrite(p, 1, len, outfp)) {
fprintf(stderr, "%s: output error : %s\n", prog, strerror(errno));
goto end;
}
} else {
fprintf(stderr, "%s: error\n", prog);
goto end;
}
}
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
if (cms) free(cms);
return ret;
}

View File

@@ -47,22 +47,24 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/x509_crl.h>
#include <gmssl/error.h>
static const char *options = "[-in file]";
static const char *options = "[-in file] [-out file]";
int crlparse_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *infile = NULL;
char *outfile = NULL;
FILE *infp = stdin;
uint8_t crl[18192];
FILE *outfp = stdout;
uint8_t crl[64 * 1024];
size_t crllen;
argc--;
@@ -71,38 +73,50 @@ int crlparse_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
return 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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: llegal option '%s'\n", prog, *argv);
printf("usage: %s %s\n", prog, options);
return 1;
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (infile) {
if (!(infp = fopen(infile, "r"))) {
error_print();
return -1;
for (;;) {
int rv;
if ((rv = x509_crl_from_fp(crl, &crllen, sizeof(crl), infp)) != 1) {
if (rv < 0) fprintf(stderr, "%s: read CRL failure\n", prog);
else ret = 0;
goto end;
}
x509_crl_print(outfp, 0, 0, "CRL", crl, crllen);
if (x509_crl_to_pem(crl, crllen, outfp) != 1) {
fprintf(stderr, "%s: output CRL failure\n", prog);
goto end;
}
}
for (;;) {
int ret;
if ((ret = x509_crl_from_pem(crl, &crllen, sizeof(crl), infp)) < 0) {
error_print();
return -1;
} else if (!ret) {
break;
}
x509_crl_print(stdout, 0, 0, "CRL", crl, crllen);
// x509_crl_to_pem(crl, crllen, stdout);
}
return 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -76,6 +76,11 @@ extern int sm9sign_main(int argc, char **argv);
extern int sm9verify_main(int argc, char **argv);
extern int sm9encrypt_main(int argc, char **argv);
extern int sm9decrypt_main(int argc, char **argv);
extern int cmsparse_main(int argc, char **argv);
extern int cmsencrypt_main(int argc, char **argv);
extern int cmsdecrypt_main(int argc, char **argv);
extern int cmssign_main(int argc, char **argv);
extern int cmsverify_main(int argc, char **argv);
extern int tlcp_client_main(int argc, char **argv);
extern int tlcp_server_main(int argc, char **argv);
extern int tls12_client_main(int argc, char **argv);
@@ -90,18 +95,18 @@ static const char *options =
"command [options]\n"
"\n"
"Commands:\n"
" help Print commands list or help for one command\n"
" help Print this help message\n"
" version Print version\n"
" rand Generate random bytes\n"
" sm2keygen Generate SM2 keypair\n"
" sm2sign Generate SM2 signature\n"
" sm2verify Verify SM2 signature\n"
" sm2encrypt SM2 public key encryption\n"
" sm2decrypt SM2 decryption\n"
" sm2encrypt Encrypt with SM2 public key\n"
" sm2decrypt Decrypt with SM2 private key\n"
" sm3 Generate SM3 hash\n"
" sm3hmac Generate HMAC-SM3 MAC tag\n"
" sm4 Encrypt or decrypt data with SM4\n"
" zuc Encrypt or decrypt data with ZUC\n"
" sm3hmac Generate SM3 HMAC tag\n"
" sm4 Encrypt or decrypt with SM4\n"
" zuc Encrypt or decrypt with ZUC\n"
" sm9setup Generate SM9 master secret\n"
" sm9keygen Generate SM9 private key\n"
" sm9sign Generate SM9 signature\n"
@@ -109,21 +114,26 @@ static const char *options =
" sm9encrypt SM9 public key encryption\n"
" sm9decrypt SM9 decryption\n"
" pbkdf2 Generate key from password\n"
" reqgen Generate PKCS #10 certificate signing request (CSR)\n"
" reqsign Generate a certificate from PKCS #10 CSR\n"
" reqparse Parse and print a PKCS #10 CSR\n"
" reqgen Generate certificate signing request (CSR)\n"
" reqsign Generate certificate from CSR\n"
" reqparse Parse and print a CSR\n"
" crlparse Parse and print CRL\n"
" certgen Generate a self-signed X.509 certificate in PEM format\n"
" certparse Parse and print certificates in a PEM file\n"
" certverify Verify certificate chain in a PEM file\n"
" certgen Generate a self-signed certificate\n"
" certparse Parse and print certificates\n"
" certverify Verify certificate chain\n"
" cmsparse Parse cryptographic message syntax (CMS)\n"
" cmsencrypt Generate CMS EnvelopedData\n"
" cmsdecrypt Decrypt CMS EnvelopedData\n"
" cmssign Generate CMS SignedData\n"
" cmsverify Verify CMS SignedData\n"
" sdfutil SDF crypto device utility\n"
" skfutil SKF crypto device utility\n"
" tlcp_client TLCP client\n"
" tlcp_server TLCP server\n"
" tls12_client TLS 1.2 client\n"
" tls12_server TLS 1.2 server\n"
" tls13_client TLS 1.3 client\n"
" tls13_server TLS 1.3 server\n"
" sdfutil SDF crypto device utility\n"
" skfutil SKF crypto device utility\n";
" tls13_server TLS 1.3 server\n";
@@ -154,6 +164,8 @@ 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, "crlparse")) {
return crlparse_main(argc, argv);
} else if (!strcmp(*argv, "reqgen")) {
return reqgen_main(argc, argv);
} else if (!strcmp(*argv, "reqparse")) {
@@ -192,6 +204,16 @@ int main(int argc, char **argv)
return sm9encrypt_main(argc, argv);
} else if (!strcmp(*argv, "sm9decrypt")) {
return sm9decrypt_main(argc, argv);
} else if (!strcmp(*argv, "cmsparse")) {
return cmsparse_main(argc, argv);
} else if (!strcmp(*argv, "cmsencrypt")) {
return cmsencrypt_main(argc, argv);
} else if (!strcmp(*argv, "cmsdecrypt")) {
return cmsdecrypt_main(argc, argv);
} else if (!strcmp(*argv, "cmssign")) {
return cmssign_main(argc, argv);
} else if (!strcmp(*argv, "cmsverify")) {
return cmsverify_main(argc, argv);
} else if (!strcmp(*argv, "tlcp_client")) {
return tlcp_client_main(argc, argv);
} else if (!strcmp(*argv, "tlcp_server")) {

View File

@@ -47,28 +47,23 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/mem.h>
#include <gmssl/rand.h>
#include <gmssl/pkcs8.h>
#include <gmssl/x509.h>
#include <gmssl/x509_req.h>
#include <gmssl/pkcs8.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
#ifndef WIN32
#include <pwd.h>
#include <unistd.h>
#endif
static const char *options =
"[-C str] [-ST str] [-L str] [-O str] [-OU str] -CN str -days num"
" -key file [-pass pass] [-out file]";
int reqgen_main(int argc, char **argv)
{
int ret = -1;
int ret = 1;
char *prog = argv[0];
char *country = NULL;
char *state = NULL;
@@ -76,34 +71,31 @@ int reqgen_main(int argc, char **argv)
char *org = NULL;
char *org_unit = NULL;
char *common_name = NULL;
char *file = NULL;
char *pass = NULL;
int days = 0;
FILE *keyfp = NULL;
FILE *outfp = stdout;
uint8_t req[1024];
size_t reqlen = 0;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
uint8_t name[256];
size_t namelen = 0;
SM2_KEY sm2_key; // 这个应该是从文件中读取的!
if (argc < 2) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
FILE *keyfp = NULL;
FILE *outfp = stdout;
uint8_t req[1024];
size_t reqlen = 0;
SM2_KEY sm2_key;
argc--;
argv++;
while (argc >= 1) {
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
printf("usage: %s %s\n", prog, options);
return 0;
ret = 0;
goto end;
} else if (!strcmp(*argv, "-C")) {
if (--argc < 1) goto bad;
country = *(++argv);
@@ -122,51 +114,62 @@ 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;
file = *(++argv);
if (!(keyfp = fopen(file, "r"))) {
error_print();
return -1;
keyfile = *(++argv);
if (!(keyfp = fopen(keyfile, "r"))) {
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, "-days")) {
if (--argc < 1) goto bad;
days = atoi(*(++argv));
} else if (!strcmp(*argv, "-out")) {
if (--argc < 1) goto bad;
file = *(++argv);
if (!(outfp = fopen(file, "w"))) {
error_print();
return -1;
outfile = *(++argv);
if (!(outfp = fopen(outfile, "w"))) {
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, "usage: %s %s\n", prog, options);
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (!common_name || days <= 0 || !keyfp) {
fprintf(stderr, "%s: missing options\n", prog);
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
if (!common_name) {
fprintf(stderr, "%s: '-CN' option required\n", prog);
goto end;
}
if (!days) {
fprintf(stderr, "%s: '-days' option required\n", prog);
goto end;
}
if (!keyfile) {
fprintf(stderr, "%s: '-key' option required\n", prog);
goto end;
}
if (!pass) {
pass = getpass("Encryption Password : ");
}
if (!pass || strlen(pass) == 0) {
fprintf(stderr, "%s: '-pass' option required\n", prog);
error_print();
return -1;
goto end;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
error_print();
return -1;
fprintf(stderr, "%s: load private key failed\n", prog);
goto end;
}
if (x509_name_set(name, &namelen, sizeof(name),
@@ -177,13 +180,18 @@ bad:
&sm2_key,
NULL, 0,
OID_sm2sign_with_sm3,
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1
|| x509_req_to_pem(req, reqlen, outfp) != 1) {
memset(&sm2_key, 0, sizeof(SM2_KEY));
error_print();
return -1;
&sm2_key, SM2_DEFAULT_ID, strlen(SM2_DEFAULT_ID)) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
memset(&sm2_key, 0, sizeof(SM2_KEY));
return 0;
if (x509_req_to_pem(req, reqlen, outfp) != 1) {
fprintf(stderr, "%s: output CSR failed\n", prog);
goto end;
}
ret = 0;
end:
gmssl_secure_clear(&sm2_key, sizeof(SM2_KEY));
if (keyfp) fclose(keyfp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -47,19 +47,23 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <gmssl/pem.h>
#include <gmssl/x509.h>
#include <gmssl/x509_req.h>
#include <gmssl/error.h>
static const char *options = "[-in file] [-out file]";
int reqparse_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 req[1024];
size_t reqlen;
@@ -68,39 +72,46 @@ int reqparse_main(int argc, char **argv)
while (argc > 0) {
if (!strcmp(*argv, "-help")) {
help:
fprintf(stderr, "usage: %s [-in file]\n", prog);
return -1;
printf("usage: %s %s\n", prog, options);
goto end;
} else if(!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
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, "w"))) {
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 help;
goto end;
bad:
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (infile) {
if (!(infp = fopen(infile, "r"))) {
error_print();
return -1;
}
}
if (x509_req_from_pem(req, &reqlen, sizeof(req), infp) != 1) {
error_print();
return -1;
fprintf(stderr, "%s: read CSR failure\n", prog);
goto end;
}
x509_req_print(stdout, 0, 0, "CertificationRequest", req, reqlen);
x509_req_to_pem(req, reqlen, stdout);
return 0;
bad:
fprintf(stderr, "%s: '%s' option value required\n", prog, *argv);
return -1;
x509_req_print(outfp, 0, 0, "CertificationRequest", req, reqlen);
if (x509_req_to_pem(req, reqlen, outfp) != 1) {
fprintf(stderr, "%s: output CSR failure\n", prog);
goto end;
}
ret = 0;
end:
if (infile && infp) fclose(infp);
if (outfile && outfp) fclose(outfp);
return ret;
}

View File

@@ -47,43 +47,42 @@
*/
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <gmssl/pem.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/pkcs8.h>
#include <gmssl/rand.h>
#include <gmssl/error.h>
static const char *options = "[-in pem] -days num -cacert pem -key pem [-pass str] [-out pem]\n";
static int ext_key_usage_set(int *usages, const char *usage_name)
{
int flag = 0;
if (x509_key_usage_from_name(&flag, usage_name) != 1) {
error_print();
return -1;
}
*usages |= flag;
printf("flag = %08x", flag);
printf("usage = %08x", *usages);
return 1;
}
static const char *usage = "usage: %s [-in file] -days num -cacert file -key file [-pass str] [-out file]\n";
int reqsign_main(int argc, char **argv)
{
int ret = 1;
char *prog = argv[0];
char *file;
char *pass = NULL;
char *infile = NULL;
int days = 0;
char *cacertfile = NULL;
char *keyfile = NULL;
char *pass = NULL;
char *outfile = NULL;
FILE *infp = stdin;
FILE *cacertfp = NULL;
FILE *keyfp = NULL;
FILE *outfp = stdout;
uint8_t req[512];
size_t reqlen;
@@ -91,16 +90,12 @@ int reqsign_main(int argc, char **argv)
size_t subject_len;
SM2_KEY subject_public_key;
FILE *outfp = stdout;
FILE *cacertfp = NULL;
uint8_t cacert[1024];
size_t cacertlen;
const uint8_t *issuer;
size_t issuer_len;
SM2_KEY issuer_public_key;
FILE *keyfp = NULL;
SM2_KEY sm2_key;
uint8_t cert[1024];
@@ -111,107 +106,121 @@ int reqsign_main(int argc, char **argv)
size_t extslen = 0;
int key_usage = 0;
argc--;
argv++;
if (argc < 2) {
fprintf(stderr, usage, prog);
if (argc < 1) {
fprintf(stderr, "usage: %s %s\n", prog, options);
return 1;
}
argc--;
argv++;
while (argc >= 1) {
if (!strcmp(*argv, "-help")) {
help:
printf(usage, prog);
return 0;
printf("usage: %s %s\n", prog, options);
ret = 0;
goto end;
} else if (!strcmp(*argv, "-in")) {
if (--argc < 1) goto bad;
file = *(++argv);
if (!(infp = fopen(file, "r"))) {
error_print();
return -1;
infile = *(++argv);
if (!(infp = fopen(infile, "r"))) {
fprintf(stderr, "%s: open '%s' failure : %s\n", prog, outfile, strerror(errno));
goto end;
}
} 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_usage")) {
if (--argc < 1) goto bad;
if (ext_key_usage_set(&key_usage, *(++argv)) != 1) {
error_print();
return -1;
fprintf(stderr, "%s: set KeyUsage extenstion failure\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-cacert")) {
if (--argc < 1) goto bad;
file = *(++argv);
if (!(cacertfp = fopen(file, "r"))) {
error_print();
return -1;
cacertfile = *(++argv);
if (!(cacertfp = fopen(cacertfile, "r"))) {
fprintf(stderr, "%s: invalid -key_usage value\n", prog);
goto end;
}
} else if (!strcmp(*argv, "-key")) {
if (--argc < 1) goto bad;
file = *(++argv);
if (!(keyfp = fopen(file, "r"))) {
error_print();
return -1;
keyfile = *(++argv);
if (!(keyfp = fopen(keyfile, "r"))) {
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;
file = *(++argv);
if (!(outfp = fopen(file, "w"))) {
error_print();
return -1;
outfile = *(++argv);
if (!(outfp = fopen(outfile, "w"))) {
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:
error_print();
break;
fprintf(stderr, "%s: '%s' option value missing\n", prog, *argv);
goto end;
}
argc--;
argv++;
}
if (days <= 0
|| !infp
|| !cacertfp
|| !keyfp) {
error_print();
return -1;
if (!days) {
fprintf(stderr, "%s: '-days' 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 (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) {
error_print();
return -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
|| x509_cert_get_subject_public_key(cacert, cacertlen, &issuer_public_key) != 1) {
error_print();
return -1;
fprintf(stderr, "%s: parse CA certificate failure\n", prog);
goto end;
}
if (!pass) {
pass = getpass("Password : ");
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1) {
fprintf(stderr, "%s: load private key failure\n", prog);
goto end;
}
if (!pass || strlen(pass) == 0) {
error_print();
return -1;
}
if (sm2_private_key_info_decrypt_from_pem(&sm2_key, pass, keyfp) != 1
|| sm2_public_key_equ(&sm2_key, &issuer_public_key) != 1) {
error_print();
memset(&sm2_key, 0, sizeof(SM2_KEY));
return -1;
if (sm2_public_key_equ(&sm2_key, &issuer_public_key) != 1) {
fprintf(stderr, "%s: private key and CA certificate not match\n", prog);
goto end;
}
rand_bytes(serial, sizeof(serial));
if (rand_bytes(serial, sizeof(serial)) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
time(&not_before);
if (x509_validity_add_days(&not_after, not_before, days) != 1
@@ -228,14 +237,20 @@ bad:
NULL, 0,
NULL, 0,
exts, extslen,
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1
|| x509_cert_to_pem(cert, certlen, outfp) != 1) {
memset(&sm2_key, 0, sizeof(SM2_KEY));
error_print();
return -1;
&sm2_key, SM2_DEFAULT_ID, SM2_DEFAULT_ID_LENGTH) != 1) {
fprintf(stderr, "%s: inner error\n", prog);
goto end;
}
// FIXME: fclose() ....
memset(&sm2_key, 0, sizeof(SM2_KEY));
return 0;
if (x509_cert_to_pem(cert, certlen, outfp) != 1) {
fprintf(stderr, "%s: output certificate failed\n", prog);
goto end;
}
ret = 0;
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;
}

View File

@@ -1,4 +1,4 @@
/*
/*
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -131,7 +131,7 @@ bad:
}
if (sm2_private_key_info_decrypt_from_pem(&key, pass, keyfp) != 1) {
fprintf(stderr, "%s: private key decryption failure", prog);
fprintf(stderr, "%s: private key decryption failure\n", prog);
goto end;
}