mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-28 08:43:38 +08:00
Update Tools
This commit is contained in:
14
demos/certdemo.sh
Executable file
14
demos/certdemo.sh
Executable 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
17
demos/cmsdemo.sh
Executable 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
19
demos/reqdemo.sh
Executable 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
16
demos/sm234demo.sh
Executable 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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
20
src/asn1.c
20
src/asn1.c
@@ -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
259
src/cms.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 =
|
||||
|
||||
147
src/x509_cer.c
147
src/x509_cer.c
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) },
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
#include <gmssl/digest.h>
|
||||
|
||||
const char *digests[] = {
|
||||
"md5",
|
||||
// "md5",
|
||||
"sha1",
|
||||
"sm3",
|
||||
"sha224",
|
||||
|
||||
125
tools/certgen.c
125
tools/certgen.c
@@ -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(¬_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
215
tools/cmsdecrypt.c
Normal 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
270
tools/cmsencrypt.c
Normal 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
126
tools/cmsparse.c
Normal 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
246
tools/cmssign.c
Normal 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
177
tools/cmsverify.c
Normal 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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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")) {
|
||||
|
||||
128
tools/reqgen.c
128
tools/reqgen.c
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
173
tools/reqsign.c
173
tools/reqsign.c
@@ -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(¬_before);
|
||||
|
||||
if (x509_validity_add_days(¬_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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user