diff --git a/include/gmssl/asn1.h b/include/gmssl/asn1.h index bbd62f82..1aa12f3f 100644 --- a/include/gmssl/asn1.h +++ b/include/gmssl/asn1.h @@ -257,6 +257,8 @@ int asn1_generalized_time_from_der_ex(int tag, time_t *tv, const uint8_t **in, s #define asn1_implicit_from_der(i,d,dlen,in,inlen) asn1_type_from_der(ASN1_TAG_EXPLICIT(i),d,dlen,in,inlen) int asn1_header_to_der(int tag, size_t dlen, uint8_t **out, size_t *outlen); +#define asn1_implicit_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) + #define asn1_sequence_header_to_der(dlen,out,outlen) asn1_header_to_der(ASN1_TAG_SEQUENCE,dlen,out,outlen) #define asn1_implicit_sequence_header_to_der(i,dlen,out,outlen) asn1_header_to_der(ASN1_TAG_EXPLICIT(i),dlen,out,outlen) diff --git a/include/gmssl/cms.h b/include/gmssl/cms.h index 686b7686..5a9aa1ae 100644 --- a/include/gmssl/cms.h +++ b/include/gmssl/cms.h @@ -67,6 +67,10 @@ References: extern "C" { #endif +enum { + CMS_version_v1 = 1, +}; + /* ContentType: @@ -87,6 +91,9 @@ ContentInfo ::= SEQUENCE { contentType OBJECT IDENTIFIER, content [0] EXPLICIT ANY OPTIONAL } */ +int cms_content_info_header_to_der( + int content_type, size_t content_len, + uint8_t **out, size_t *outlen); int cms_content_info_to_der( int content_type, const uint8_t *content, size_t content_len, @@ -129,20 +136,19 @@ int cms_enced_content_info_from_der( int cms_enced_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int cms_enced_content_info_encrypt_to_der( - int content_type, - int enc_algor, const uint8_t *iv, size_t ivlen, - const uint8_t *content, size_t content_len, + int enc_algor, + const uint8_t *key, size_t keylen, + const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, - const uint8_t *key, size_t keylen, uint8_t **out, size_t *outlen); int cms_enced_content_info_decrypt_from_der( - int *content_type, - int *enc_algor, const uint8_t **iv, size_t *ivlen, - uint8_t *content, size_t *content_len, + int *enc_algor, + const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t *key, size_t keylen, const uint8_t **in, size_t *inlen); /* @@ -169,22 +175,19 @@ int cms_encrypted_data_from_der( int cms_encrypted_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int cms_encrypted_data_encrypt_to_der( - int version, - int content_type, - int enc_algor, const uint8_t *iv, size_t ivlen, - const uint8_t *content, size_t content_len, + int enc_algor, + const uint8_t *key, size_t keylen, + const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, - const uint8_t *key, size_t keylen, uint8_t **out, size_t *outlen); int cms_encrypted_data_decrypt_from_der( - int *version, - int *content_type, - int *enc_algor, const uint8_t **iv, size_t *ivlen, - uint8_t *content, size_t *content_len, + int *enc_algor, + const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t *key, size_t keylen, const uint8_t **in, size_t *inlen); /* @@ -235,64 +238,35 @@ int cms_signer_info_from_der( int cms_signer_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int cms_signer_info_sign_to_der( - int version, + const SM3_CTX *sm3_ctx, const SM2_KEY *sm2_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, const uint8_t *authed_attrs, size_t authed_attrs_len, const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, uint8_t **out, size_t *outlen); int cms_signer_info_verify_from_der( - int *version, + const SM3_CTX *sm3_ctx, const uint8_t *certs, size_t certslen, + const uint8_t **cert, size_t *certlen, const uint8_t **issuer, size_t *issuer_len, - const uint8_t **serial_number, size_t *serial_number_len, - int *digest_algor, + const uint8_t **serial, size_t *serial_len, const uint8_t **authed_attrs, size_t *authed_attrs_len, - int *signature_algor, - const uint8_t **enced_digest, size_t *enced_digest_len, const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_pub_key, const uint8_t **in, size_t *inlen); - /* SignerInfos ::= SET OF SignerInfo; */ int cms_signer_infos_add_signer_info( uint8_t *d, size_t *dlen, size_t maxlen, - int version, + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, const uint8_t *authed_attrs, size_t authed_attrs_len, - const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key); + const uint8_t *unauthed_attrs, size_t unauthed_attrs_len); #define cms_signer_infos_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) #define cms_signer_infos_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) int cms_signer_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); -/* -CertificateRevocationLists ::= SET OF CertificateRevocationList -*/ -int cms_crls_add_crl(uint8_t *d, size_t *dlen, size_t maxlen, const uint8_t *crl, size_t crllen); -#define cms_crls_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) -#define cms_crls_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) -int cms_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); - -/* -ExtendedCertificateAndCertificate ::= CHOICE { - certificate Certificate, - extendedCertificate [0] IMPLICIT ExtendedCertificate } - -ExtendedCertificatesAndCertificates ::= SET OF - ExtendedCertificateOrCertificate - -ExtendedCertificate is supported in print, not in add/to/from -*/ -int cms_extened_certs_add_cert(uint8_t *d, size_t *dlen, size_t maxlen, const uint8_t *cert, size_t certlen); -#define cms_extened_certs_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) -#define cms_extened_certs_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) -int cms_extended_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); - int cms_digest_algors_to_der(const int *digest_algors, size_t digest_algors_cnt, uint8_t **out, size_t *outlen); int cms_digest_algors_from_der(int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, const uint8_t **in, size_t *inlen); @@ -329,26 +303,21 @@ int cms_signed_data_print(FILE *fp, int fmt, int ind, const char *label, const u typedef struct { uint8_t *certs; size_t certs_len; - SM2_KEY *sm2_key; - char *signer_id; - size_t signer_id_len; -} CMS_CERT_AND_KEY; + SM2_KEY *sign_key; +} CMS_CERTS_AND_KEY; int cms_signed_data_sign_to_der( - int version, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, int content_type, const uint8_t *content, size_t content_len, - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, - const uint8_t *crls, size_t crls_len, + const uint8_t *crls, size_t crls_len, // 可以为空 uint8_t **out, size_t *outlen); int cms_signed_data_verify_from_der( - int *version, - const uint8_t *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, int *content_type, const uint8_t **content, size_t *content_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t *extra_certs, size_t extra_certs_len, - const uint8_t *extra_crls, size_t extra_crls_len, const uint8_t **in, size_t *inlen); /* @@ -370,28 +339,28 @@ int cms_recipient_info_from_der( int *version, const uint8_t **issuer, size_t *issuer_len, const uint8_t **serial_number, size_t *serial_number_len, - int *pke_algor, const uint8_t **params, size_t *paramslen,// SM2加密只使用SM3,没有默认参数,但是ECIES可能有 + int *pke_algor, const uint8_t **params, size_t *params_len,// SM2加密只使用SM3,没有默认参数,但是ECIES可能有 const uint8_t **enced_key, size_t *enced_key_len, const uint8_t **in, size_t *inlen); int cms_recipient_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int cms_recipient_info_encrypt_to_der( - int version, - const uint8_t *issuer, size_t issuer_len, - const uint8_t *serial_number, size_t serial_number_len, - int public_key_enc_algor, - const uint8_t *in, size_t inlen, const SM2_KEY *public_key, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t *in, size_t inlen, uint8_t **out, size_t *outlen); int cms_recipient_info_decrypt_from_der( - int *version, - const uint8_t **issuer, size_t *issuer_len, - const uint8_t **serial_number, size_t *serial_number_len, - int *pke_algor, const uint8_t **params, size_t *paramslen, - const uint8_t **decrypted_key, size_t *decrypted_key_len, const SM2_KEY *sm2_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + uint8_t *out, size_t *outlen, size_t maxlen, const uint8_t **in, size_t *inlen); +#define cms_recipient_infos_to_der(d,dlen,out,outlen) asn1_set_to_der(d,dlen,out,outlen) +#define cms_recipient_infos_from_der(d,dlen,in,inlen) asn1_set_from_der(d,dlen,in,inlen) +int cms_recipient_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + /* EnvelopedData ::= SEQUENCE { version Version, @@ -410,31 +379,25 @@ int cms_enveloped_data_to_der( int cms_enveloped_data_from_der( int *version, const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, const uint8_t **in, size_t *inlen); int cms_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); int cms_enveloped_data_encrypt_to_der( - int version, - const uint8_t *rcpt_certs, size_t rcpt_certs_len, // 当只有一个接收者的时候,这个参数类型非常方便 + const uint8_t *rcpt_certs, size_t rcpt_certs_len, int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, uint8_t **out, size_t *outlen); int cms_enveloped_data_decrypt_from_der( - int *version, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, const SM2_KEY *sm2_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, const uint8_t **in, size_t *inlen); /* @@ -464,48 +427,37 @@ int cms_signed_and_enveloped_data_from_der( int *version, const uint8_t **rcpt_infos, size_t *rcpt_infos_len, int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, const uint8_t **signer_infos, size_t *signer_infos_len, const uint8_t **in, size_t *inlen); int cms_signed_and_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); -int cms_signed_and_enveloped_encipher_to_der( - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, +int cms_signed_and_enveloped_data_encipher_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, - const uint8_t *signer_crls, size_t signer_crls_len, + const uint8_t *signers_crls, size_t signers_crls_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, uint8_t **out, size_t *outlen); - -int cms_deenvelop_and_verify_decipher_from_der( - int *version, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - const uint8_t **digest_algors, size_t *digest_algors_len, - int *enc_algor, uint8_t *key, size_t *keylen, const uint8_t **iv, size_t *ivlen, +int cms_signed_and_enveloped_data_decipher_from_der( + const SM2_KEY *rcpt_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **prcpt_infos, size_t *prcpt_infos_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - - const SM2_KEY *rcpt_key, - const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, - const uint8_t *rcpt_serial_number, size_t rcpt_serial_number_len, - const uint8_t *extra_verify_certs, size_t extra_verify_certs_len, - const uint8_t *extra_verify_crls, size_t extra_verify_crls_len, - + const uint8_t **psigner_infos, size_t *psigner_infos_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, const uint8_t **in, size_t *inlen); - /* KeyAgreementInfo ::= SEQUENCE { version INTEGER (1), @@ -530,83 +482,78 @@ int cms_key_agreement_info_print(FILE *fp, int fmt, int ind, const char *label, // 下面是公开API +// 公开API的设计考虑: +// 1. 不需要调用其他函数 +// 2. 在逻辑上容易理解 +// 3. 将cms,cmslen看做对象 // 生成ContentInfo, type == data -int cms_set_data(uint8_t *cms, size_t *cmslen, size_t maxlen, const uint8_t *d, size_t dlen); +int cms_set_data(uint8_t *cms, size_t *cmslen, + const uint8_t *d, size_t dlen); int cms_encrypt( + uint8_t *cms, size_t *cmslen, // 输出的ContentInfo (type encryptedData) int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法、密钥和IV int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 const uint8_t *shared_info1, size_t shared_info1_len, // 附加信息 - const uint8_t *shared_info2, size_t shared_info2_len, // 附加信息 - uint8_t *cms, size_t *cmslen, size_t maxlen); // 输出的ContentInfo (type encryptedData) + const uint8_t *shared_info2, size_t shared_info2_len); int cms_decrypt( - const uint8_t *key, size_t keylen, // 解密密钥(我们不知道解密算法) - const uint8_t *cms, size_t cms_len, // 输入的ContentInfo (type encryptedData) - const uint8_t *extra_enced_content, size_t extra_enced_content_len, // EncryptedContentInfo的密文数据为空时显示提供输入密文 + const uint8_t *cms, size_t cmslen, // 输入的ContentInfo (type encryptedData) + int *enc_algor, const uint8_t *key, size_t keylen, // 解密密钥(我们不知道解密算法) int *content_type, uint8_t *content, size_t *content_len, // 输出的解密数据类型及数据 - int *enc_algor, const uint8_t **iv, size_t *ivlen, // 解析EncryptedContentInfo得到的对称加密算法及参数 const uint8_t **shared_info1, size_t *shared_info1_len, // 附加信息 const uint8_t **shared_info2, size_t *shared_info2_len); int cms_sign( - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, // 签名者的签名私钥和证书 + uint8_t *cms, size_t *cms_len, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, // 签名者的签名私钥和证书 int content_type, const uint8_t *content, size_t content_len, // 待签名的输入数据 - const uint8_t *crls, size_t crls_len, // 签名者证书的CRL - uint8_t *cms, size_t *cms_len); // 输出的ContentInfo (type signedData) + const uint8_t *crls, size_t crls_len); int cms_verify( - const uint8_t *cms, size_t cms_len, // 输入的ContentInfo (type signedData) - const uint8_t *extra_content, size_t extra_content_len, // ContentInfo的数据为空时显示提供输入 - const uint8_t *extra_certs, size_t extra_certs_len, // 当SignedData中未提供证书时显示输入 - const uint8_t *extra_crls, size_t extra_crls_len, // 当SignedData中未提供CRL时显示输入 - int *content_type, const uint8_t **content, size_t *content_len, // 从SignedData解析得到的被签名数据 - const uint8_t **certs, size_t *certs_len, // 从SignedData解析得到的签名证书 - const uint8_t **crls, size_t *crls_len, // 从SignedData解析得到的CRL - const uint8_t **signer_infos, size_t *signer_infos_len); // 从SignedData解析得到的SignerInfos,可用于显示验证结果 + const uint8_t *cms, size_t cms_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + int *content_type, const uint8_t **content, size_t *content_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **signer_infos, size_t *signer_infos_len); int cms_envelop( + uint8_t *cms, size_t *cms_len, const uint8_t *rcpt_certs, size_t rcpt_certs_len, // 接收方证书,注意这个参数的类型可以容纳多个证书,但是只有在一个接受者时对调用方最方便 int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法及参数 int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 const uint8_t *shared_info1, size_t shared_info1_len, // 附加输入信息 - const uint8_t *shared_info2, size_t shared_info2_len, // 附加输入信息 - uint8_t *cms, size_t *cms_len); // 输出ContentInfo + const uint8_t *shared_info2, size_t shared_info2_len); int cms_deenvelop( - const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, // 接收方的解密私钥和对应的证书,注意只需要一个解密方 const uint8_t *cms, size_t cms_len, - const uint8_t *extra_enced_content, size_t extra_enced_content_len, // 显式输入的密文 + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, // 接收方的解密私钥和对应的证书,注意只需要一个解密方 int *content_type, uint8_t *content, size_t *content_len, - int *enc_algor, const uint8_t **iv, size_t *ivlen, // 注意,对称加密的密钥就不输出了 const uint8_t **rcpt_infos, size_t *rcpt_infos_len, // 解析得到,用于显示 const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len); -int cms_sign_and_envelop( // 参考cms_sign, cms_envelop - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, +int cms_sign_and_envelop( + uint8_t *cms, size_t *cms_len, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, const uint8_t *rcpt_certs, size_t rcpt_certs_len, int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, - const uint8_t *signer_crls, size_t signer_crls_len, + const uint8_t *signers_crls, size_t signers_crls_len, const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t *cms, size_t *cms_len); + const uint8_t *shared_info2, size_t shared_info2_len); -int cms_deenvelop_and_verify( // 参考cms_deenvelop, cms_verify - const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, - // 输入 +int cms_deenvelop_and_verify( const uint8_t *cms, size_t cms_len, - const uint8_t *extra_enced_content, size_t extra_enced_content_len, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, const uint8_t *extra_signer_certs, size_t extra_signer_certs_len, const uint8_t *extra_signer_crls, size_t extra_signer_crls_len, - // 输出 int *content_type, uint8_t *content, size_t *content_len, - // 格外的解析内容输出,均为可选 - int *enc_algor, const uint8_t **iv, size_t *ivlen, - const uint8_t **rcpt_infos, size_t rcpt_infos_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, const uint8_t **signer_infos, size_t *signer_infos_len, const uint8_t **signer_certs, size_t *signer_certs_len, const uint8_t **signer_crls, size_t *signer_crls_len, @@ -620,7 +567,7 @@ 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); -int cms_print(FILE *fp, int fmt, int ind, const uint8_t *a, size_t alen); +int cms_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *a, size_t alen); #ifdef __cplusplus diff --git a/include/gmssl/sm2.h b/include/gmssl/sm2.h index f5547b80..cd14c192 100644 --- a/include/gmssl/sm2.h +++ b/include/gmssl/sm2.h @@ -91,6 +91,7 @@ int sm2_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY * int sm2_public_key_copy(SM2_KEY *sm2_key, const SM2_KEY *pub_key); int sm2_public_key_digest(const SM2_KEY *key, uint8_t dgst[32]); +int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key); /* from RFC 5915 diff --git a/include/gmssl/x509.h b/include/gmssl/x509.h index 71e0b837..3215b9b2 100644 --- a/include/gmssl/x509.h +++ b/include/gmssl/x509.h @@ -312,6 +312,15 @@ 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); +int x509_certs_get_cert_by_issuer_and_serial_number( + const uint8_t *certs, size_t certs_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t **cert, size_t *cert_len); + +int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + + #ifdef __cplusplus } #endif diff --git a/include/gmssl/x509_crl.h b/include/gmssl/x509_crl.h index 496986ea..d6bd6beb 100644 --- a/include/gmssl/x509_crl.h +++ b/include/gmssl/x509_crl.h @@ -258,6 +258,8 @@ int x509_crl_get_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, const uint8_t *serial, size_t serial_len, time_t *revoke_date, const uint8_t **entry_exts, size_t *entry_exts_len); +int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen); + #ifdef __cplusplus } #endif diff --git a/src/cms.c b/src/cms.c index be97d1f5..afc1474a 100644 --- a/src/cms.c +++ b/src/cms.c @@ -53,6 +53,7 @@ #include #include #include +#include #include #include #include @@ -72,14 +73,15 @@ static uint32_t oid_cms_enveloped_data[] = { oid_sm2_cms,3 }; static uint32_t oid_cms_signed_and_enveloped_data[] = { oid_sm2_cms,4 }; static uint32_t oid_cms_encrypted_data[] = { oid_sm2_cms,5 }; static uint32_t oid_cms_key_agreement_info[] = { oid_sm2_cms,6 }; +#define OID_CMS_CONUNT (sizeof(oid_cms_data)/sizeof(int)) static const ASN1_OID_INFO cms_content_types[] = { - { OID_cms_data, "data", oid_cms_data, sizeof(oid_cms_data)/sizeof(int) }, - { OID_cms_signed_data, "signedData", oid_cms_signed_data, sizeof(oid_cms_signed_data)/sizeof(int) }, - { OID_cms_enveloped_data, "envelopedData", oid_cms_signed_data, sizeof(oid_cms_signed_data)/sizeof(int) }, - { OID_cms_signed_and_enveloped_data, "signedAndEnvelopedData", oid_cms_signed_and_enveloped_data, sizeof(oid_cms_signed_and_enveloped_data)/sizeof(int) }, - { OID_cms_encrypted_data, "encryptedData", oid_cms_encrypted_data, sizeof(oid_cms_encrypted_data)/sizeof(int) }, - { OID_cms_key_agreement_info, "keyAgreementInfo", oid_cms_key_agreement_info, sizeof(oid_cms_key_agreement_info)/sizeof(int) } + { OID_cms_data, "data", oid_cms_data, OID_CMS_CONUNT }, + { OID_cms_signed_data, "signedData", oid_cms_signed_data, OID_CMS_CONUNT }, + { OID_cms_enveloped_data, "envelopedData", oid_cms_signed_data, OID_CMS_CONUNT }, + { OID_cms_signed_and_enveloped_data, "signedAndEnvelopedData", oid_cms_signed_and_enveloped_data, OID_CMS_CONUNT }, + { OID_cms_encrypted_data, "encryptedData", oid_cms_encrypted_data, OID_CMS_CONUNT }, + { OID_cms_key_agreement_info, "keyAgreementInfo", oid_cms_key_agreement_info, OID_CMS_CONUNT } }; static const size_t cms_content_types_count = @@ -143,24 +145,136 @@ int cms_content_type_from_der(int *oid, const uint8_t **in, size_t *inlen) return 1; } +/* +static int cms_content_info_data_header_to_der(size_t dlen, uint8_t **out, size_t *outlen) +{ + uint8_t d[1]; + size_t len = 0; + size_t content_len = 0; + if (asn1_octet_string_to_der(p, dlen, NULL, &content_len) != 1 + || cms_content_type_to_der(OID_cms_data, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) < 0 + || asn1_octet_string_to_der(dlen, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} +*/ + +int cms_content_info_header_to_der(int content_type, size_t content_len, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + /* + 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 + || cms_content_type_to_der(content_type, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; +} + +static int cms_content_info_data_to_der(const uint8_t *d, size_t dlen, uint8_t **out, size_t *outlen) +{ + size_t len = 0; + size_t content_len = 0; + if (asn1_octet_string_to_der(d, dlen, NULL, &content_len) != 1 + || cms_content_type_to_der(OID_cms_data, NULL, &len) != 1 + || asn1_explicit_to_der(0, d, content_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(OID_cms_data, out, outlen) != 1 + || asn1_explicit_header_to_der(0, content_len, out, outlen) != 1 + || asn1_octet_string_to_der(d, dlen, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + int cms_content_info_to_der( - int content_type, - const uint8_t *content, size_t content_len, + int content_type, const uint8_t *content, size_t content_len, uint8_t **out, size_t *outlen) { - return -1; + size_t len = 0; + if (content_type == OID_cms_data) { + return cms_content_info_data_to_der(content, content_len, out, outlen); + } + if (cms_content_type_to_der(content_type, NULL, &len) != 1 + || asn1_explicit_to_der(0, content, content_len, NULL, &len) < 0 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || cms_content_type_to_der(content_type, out, outlen) != 1 + || asn1_explicit_to_der(0, content, content_len, out, outlen) < 0) { + error_print(); + return -1; + } + return 1; } int cms_content_info_from_der( int *content_type, - const uint8_t **content, size_t *content_len, // 这里获得的是完整的TLV + const uint8_t **content, size_t *content_len, const uint8_t **in, size_t *inlen) { - return -1; + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (cms_content_type_from_der(content_type, &d, &dlen) != 1 + || asn1_explicit_from_der(0, content, content_len, &d, &dlen) < 0 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; } int cms_content_info_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { + int ret; + int content_type; + const uint8_t *content; + size_t content_len; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + 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; + } + if (asn1_length_is_zero(content_len) != 1) goto err; + } + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); return -1; } @@ -245,12 +359,10 @@ err: } int cms_enced_content_info_encrypt_to_der( - int content_type, - int enc_algor, const uint8_t *iv, size_t ivlen, - const uint8_t *content, size_t content_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, - const uint8_t *key, size_t keylen, uint8_t **out, size_t *outlen) { int ret; @@ -284,43 +396,33 @@ int cms_enced_content_info_encrypt_to_der( } int cms_enced_content_info_decrypt_from_der( - int *content_type, - int *enc_algor, const uint8_t **iv, size_t *ivlen, - uint8_t *content, size_t *content_len, + int *enc_algor, const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t *key, size_t keylen, const uint8_t **in, size_t *inlen) { int ret; SM4_KEY sm4_key; + const uint8_t *iv; + size_t ivlen; const uint8_t *enced_content; size_t enced_content_len; - if ((ret = cms_enced_content_info_from_der(content_type, - enc_algor, iv, ivlen, &enced_content, &enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; - } - - if (*enc_algor != OID_sm4_cbc) { - error_print(); - return -1; - } - if (*ivlen != SM4_BLOCK_SIZE) { - error_print(); - return -1; - } - if (keylen != SM4_KEY_SIZE) { + if (cms_enced_content_info_from_der(content_type, + enc_algor, &iv, &ivlen, &enced_content, &enced_content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + in, inlen) != 1 + || asn1_check(*enc_algor == OID_sm4_cbc) != 1 + || asn1_check(ivlen == SM4_BLOCK_SIZE) != 1 + || asn1_check(keylen == SM4_KEY_SIZE) != 1) { error_print(); return -1; } sm4_set_decrypt_key(&sm4_key, key); - if (sm4_cbc_padding_decrypt(&sm4_key, *iv, enced_content, enced_content_len, + if (sm4_cbc_padding_decrypt(&sm4_key, iv, enced_content, enced_content_len, content, content_len) != 1) { memset(&sm4_key, 0, sizeof(SM4_KEY)); return -1; @@ -424,34 +526,27 @@ err: } int cms_encrypted_data_encrypt_to_der( - int version, - int content_type, - int enc_algor, const uint8_t *iv, size_t ivlen, - const uint8_t *content, size_t content_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, - const uint8_t *key, size_t keylen, uint8_t **out, size_t *outlen) { size_t len = 0; - if (asn1_int_to_der(version, NULL, &len) != 1 + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 || cms_enced_content_info_encrypt_to_der( - content_type, - enc_algor, iv, ivlen, - content, content_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, - key, keylen, NULL, &len) != 1 || asn1_sequence_header_to_der(len, out, outlen) != 1 - || asn1_int_to_der(version, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 || cms_enced_content_info_encrypt_to_der( - content_type, - enc_algor, iv, ivlen, - content, content_len, + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, - key, keylen, out, outlen) != 1) { error_print(); return -1; @@ -460,16 +555,13 @@ int cms_encrypted_data_encrypt_to_der( } int cms_encrypted_data_decrypt_from_der( - int *version, - int *content_type, - int *enc_algor, const uint8_t **iv, size_t *ivlen, - uint8_t *content, size_t *content_len, + int *enc_algor, const uint8_t *key, size_t keylen, + int *content_type, uint8_t *content, size_t *content_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, - const uint8_t *key, size_t keylen, const uint8_t **in, size_t *inlen) { - int ret; + int ret, version; const uint8_t *d; size_t dlen; @@ -477,23 +569,18 @@ int cms_encrypted_data_decrypt_from_der( if (ret < 0) error_print(); return ret; } - if (asn1_int_from_der(version, &d, &dlen) != 1 + if (asn1_int_from_der(&version, &d, &dlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 || cms_enced_content_info_decrypt_from_der( - content_type, - enc_algor, iv, ivlen, - content, content_len, + enc_algor, key, keylen, + content_type, content, content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, - key, keylen, &d, &dlen) != 1 || asn1_length_is_zero(dlen) != 1) { error_print(); return -1; } - if (*version != 1) { - error_print(); - return -1; - } return 1; } @@ -661,12 +748,11 @@ err: } int cms_signer_info_sign_to_der( - int version, + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, const uint8_t *authed_attrs, size_t authed_attrs_len, const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, uint8_t **out, size_t *outlen) { SM3_CTX ctx = *sm3_ctx; @@ -681,7 +767,7 @@ int cms_signer_info_sign_to_der( return -1; } - if (cms_signer_info_to_der(version, + if (cms_signer_info_to_der(CMS_version_v1, issuer, issuer_len, serial_number, serial_number_len, OID_sm3, authed_attrs, authed_attrs_len, OID_sm2sign_with_sm3, sig, siglen, @@ -693,56 +779,76 @@ int cms_signer_info_sign_to_der( } int cms_signer_info_verify_from_der( - int *version, + const SM3_CTX *ctx, const uint8_t *certs, size_t certslen, + const uint8_t **cert, size_t *certlen, const uint8_t **issuer, size_t *issuer_len, - const uint8_t **serial_number, size_t *serial_number_len, - int *digest_algor, + const uint8_t **serial, size_t *serial_len, const uint8_t **authed_attrs, size_t *authed_attrs_len, - int *signature_algor, - const uint8_t **enced_digest, size_t *enced_digest_len, const uint8_t **unauthed_attrs, size_t *unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_pub_key, const uint8_t **in, size_t *inlen) { - int ret; - SM3_CTX ctx = *sm3_ctx; - uint8_t dgst[SM3_DIGEST_SIZE]; + int version; + int digest_algor; + int signature_algor; + const uint8_t *sig; + size_t siglen; + SM2_KEY public_key; + SM3_CTX sm3_ctx = *ctx; + uint8_t dgst[32]; - if ((ret = cms_signer_info_from_der(version, - issuer, issuer_len, serial_number, serial_number_len, - digest_algor, authed_attrs, authed_attrs_len, - signature_algor, enced_digest, enced_digest_len, - unauthed_attrs, unauthed_attrs_len, in, inlen)) != 1) { - if (ret < 0) error_print(); - return ret; + if (cms_signer_info_from_der(&version, + issuer, issuer_len, + serial, serial_len, + &digest_algor, authed_attrs, authed_attrs_len, + &signature_algor, &sig, &siglen, + unauthed_attrs, unauthed_attrs_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algor == OID_sm3) != 1 + || asn1_check(signature_algor == OID_sm2sign_with_sm3) != 1) { + error_print(); + return -1; } - if (*digest_algor != OID_sm3 - || *signature_algor != OID_sm2sign_with_sm3) { + if (x509_certs_get_cert_by_issuer_and_serial_number(certs, certslen, + *issuer, *issuer_len, *serial, *serial_len, cert, certlen) != 1 + || x509_cert_get_subject_public_key(*cert, *certlen, &public_key) != 1) { error_print(); return -1; } - sm3_update(&ctx, *authed_attrs, *authed_attrs_len); - sm3_finish(&ctx, dgst); - - if ((ret = sm2_verify(sign_pub_key, dgst, *enced_digest, *enced_digest_len)) != 1) { - if (ret < 0) error_print(); - else error_print(); - return ret; + sm3_update(&sm3_ctx, *authed_attrs, *authed_attrs_len); + sm3_finish(&sm3_ctx, dgst); + if (sm2_verify(&public_key, dgst, sig, siglen) != 1) { + error_print(); + return -1; } - return ret; + return 1; } int cms_signer_infos_add_signer_info( uint8_t *d, size_t *dlen, size_t maxlen, - int version, + const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, const uint8_t *authed_attrs, size_t authed_attrs_len, - const uint8_t *unauthed_attrs, size_t unauthed_attrs_len, - const SM3_CTX *sm3_ctx, const SM2_KEY *sign_key) + const uint8_t *unauthed_attrs, size_t unauthed_attrs_len) { - return -1; + size_t len = *dlen; + if (cms_signer_info_sign_to_der(sm3_ctx, sign_key, + issuer, issuer_len, serial_number, serial_number_len, + authed_attrs, authed_attrs_len, + unauthed_attrs, unauthed_attrs_len, + NULL, &len) != 1 + || asn1_length_le(len, maxlen) != 1 + || cms_signer_info_sign_to_der(sm3_ctx, sign_key, + issuer, issuer_len, serial_number, serial_number_len, + authed_attrs, authed_attrs_len, + unauthed_attrs, unauthed_attrs_len, + &d, dlen) != 1) { + error_print(); + return -1; + } + return 1; } int cms_signer_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) @@ -763,40 +869,6 @@ int cms_signer_infos_print(FILE *fp, int fmt, int ind, const char *label, const return 1; } -int cms_crls_add_crl(uint8_t *d, size_t *dlen, size_t maxlen, const uint8_t *crl, size_t crllen) -{ - return -1; -} - -int cms_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) -{ - const uint8_t *p; - size_t len; - - format_print(fp, fmt, ind, "%s\n", label); - ind += 4; - - while (dlen) { - if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { - error_print(); - return -1; - } - x509_cert_list_print(fp, fmt, ind, "CertificateRevocationList", p, len); - } - return 1; -} - -int cms_extened_certs_add_cert(uint8_t *d, size_t *dlen, size_t maxlen, const uint8_t *cert, size_t certlen) -{ - return -1; -} - -int cms_extended_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) -{ - // 注意:这里可能需要解析ExtendedCertificateAndCertificate - return -1; -} - int cms_digest_algors_to_der(const int *digest_algors, size_t digest_algors_cnt, uint8_t **out, size_t *outlen) { @@ -823,12 +895,46 @@ int cms_digest_algors_to_der(const int *digest_algors, size_t digest_algors_cnt, int cms_digest_algors_from_der(int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, const uint8_t **in, size_t *inlen) { - return -1; + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_set_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + + *digest_algors_cnt = 0; + while (dlen) { + if (*digest_algors_cnt > max_digest_algors) { + error_print(); + return -1; + } + if (x509_digest_algor_from_der(digest_algors, &d, &dlen) != 1) { + error_print(); + return -1; + } + digest_algors++; + (*digest_algors_cnt)++; + } + return 1; } int cms_digest_algors_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { - return -1; + int oid; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (x509_digest_algor_from_der(&oid, &d, &dlen) != 1) { + error_print(); + return -1; + } + format_print(fp, fmt, ind, "%s\n", x509_digest_algor_name(oid)); + } + return 1; } int cms_signed_data_to_der( @@ -841,10 +947,6 @@ int cms_signed_data_to_der( uint8_t **out, size_t *outlen) { size_t len = 0; - if (version != 1) { - error_print(); - return -1; - } if (asn1_int_to_der(version, NULL, &len) != 1 || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 || cms_content_info_to_der(content_type, content, content_len, NULL, &len) != 1 @@ -891,7 +993,7 @@ int cms_signed_data_from_der( error_print(); return -1; } - if (*version != 1) { + if (*version != CMS_version_v1) { error_print(); return -1; } @@ -914,7 +1016,7 @@ int cms_signed_data_print(FILE *fp, int fmt, int ind, const char *label, const u if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; cms_content_info_print(fp, fmt, ind, "contentInfo", p, len); if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; - if (ret) cms_extended_certs_print(fp, fmt, ind, "certificates", p, len); + if (ret) x509_certs_print(fp, fmt, ind, "certificates", p, len); if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; cms_signer_infos_print(fp, fmt, ind, "signerInfos", p, len); @@ -925,28 +1027,165 @@ err: return -1; } +static int cms_implicit_signers_certs_to_der(int index, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + uint8_t **out, size_t *outlen) +{ + size_t i; + size_t len = 0; + for (i = 0; i < signers_cnt; i++) { + if (asn1_data_to_der(signers[i].certs, signers[i].certs_len, NULL, &len) != 1) { + error_print(); + return -1; + } + } + if (asn1_implicit_header_to_der(index, len, out, outlen) != 1) { + error_print(); + return -1; + } + for (i = 0; i < signers_cnt; i++) { + if (asn1_data_to_der(signers[i].certs, signers[i].certs_len, out, outlen) != 1) { + error_print(); + return -1; + } + } + return 1; +} + int cms_signed_data_sign_to_der( - int version, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, int content_type, const uint8_t *content, size_t content_len, - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, const uint8_t *crls, size_t crls_len, uint8_t **out, size_t *outlen) { - return -1; + int digest_algors[] = { OID_sm3 }; + size_t digest_algors_cnt = sizeof(digest_algors)/sizeof(int); + uint8_t content_header[256]; + size_t content_header_len = 0; + const uint8_t *certs; + size_t certs_len = 0; + uint8_t signer_infos[512]; + size_t signer_infos_len = 0; + SM3_CTX sm3_ctx; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + uint8_t *p; + size_t len = 0; + size_t i; + + p = content_header; + if (cms_content_info_header_to_der(content_type, content_len, &p, &content_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_header, content_header_len); + sm3_update(&sm3_ctx, content, content_len); + + for (i = 0; i < signers_cnt; i++) { + if (x509_cert_get_issuer_and_serial_number( + signers[i].certs, signers[i].certs_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, signers->sign_key, + issuer, issuer_len, serial, serial_len, + NULL, 0, NULL, 0) != 1) { + error_print(); + return -1; + } + } + + if (asn1_int_to_der(CMS_version_v1, NULL, &len) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_content_info_to_der(content_type, content, content_len, NULL, &len) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, NULL, &len) != 1 + || asn1_implicit_set_to_der(1, crls, crls_len, NULL, &len) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_content_info_to_der(content_type, content, content_len, out, outlen) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, out, outlen) != 1 + || asn1_implicit_set_to_der(1, crls, crls_len, out, outlen) != 1 + || asn1_set_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; } int cms_signed_data_verify_from_der( - int *version, - const uint8_t *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, int *content_type, const uint8_t **content, size_t *content_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t *extra_certs, size_t extra_certs_len, - const uint8_t *extra_crls, size_t extra_crls_len, + const uint8_t **psigner_infos, size_t *psigner_infos_len, const uint8_t **in, size_t *inlen) { - return -1; + int version; + int digest_algors[4]; + size_t digest_algors_cnt; + SM3_CTX sm3_ctx; + uint8_t content_info_header[128]; + size_t content_info_header_len; + uint8_t *p = content_info_header; + const uint8_t *signer_infos; + size_t signer_infos_len; + + if (cms_signed_data_from_der( + &version, + digest_algors, &digest_algors_cnt, sizeof(digest_algors)/sizeof(int), + content_type, content, content_len, + certs, certs_len, + crls, crls_len, + &signer_infos, &signer_infos_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algors[0] == OID_sm3) != 1 + || asn1_check(digest_algors_cnt == 1) != 1) { + error_print(); + return -1; + } + *psigner_infos = signer_infos; + *psigner_infos_len = signer_infos_len; + + if (cms_content_info_header_to_der(*content_type, *content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, *content, *content_len); + + while (signer_infos_len) { + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + const uint8_t *authed_attrs; + size_t authed_attrs_len; + const uint8_t *unauthed_attrs; + size_t unauthed_attrs_len; + + if (cms_signer_info_verify_from_der( + &sm3_ctx, *certs, *certs_len, + &cert, &certlen, + &issuer, &issuer_len, + &serial, &serial_len, + &authed_attrs, &authed_attrs_len, + &unauthed_attrs, &unauthed_attrs_len, + &signer_infos, &signer_infos_len) != 1) { + error_print(); + return -1; + } + } + return 1; } int cms_recipient_info_to_der( @@ -1044,26 +1283,96 @@ err: } int cms_recipient_info_encrypt_to_der( - int version, + const SM2_KEY *public_key, const uint8_t *issuer, size_t issuer_len, const uint8_t *serial_number, size_t serial_number_len, - int public_key_enc_algor, const uint8_t *in, size_t inlen, - const SM2_KEY *public_key, uint8_t **out, size_t *outlen) { + int pke_algor = OID_sm2encrypt; + uint8_t enced_key[SM2_CIPHERTEXT_SIZE(inlen)]; + size_t enced_key_len; + + if (pke_algor != OID_sm2encrypt) { + error_print(); + return -1; + } + if (sm2_encrypt(public_key, in, inlen, enced_key, &enced_key_len) != 1) { + error_print(); + return -1; + } + if (cms_recipient_info_to_der(CMS_version_v1, + issuer, issuer_len, serial_number, serial_number_len, + pke_algor, enced_key, enced_key_len, + out, outlen) != 1) { + error_print(); + return -1; + } return 1; } int cms_recipient_info_decrypt_from_der( - int *version, - const uint8_t **issuer, size_t *issuer_len, - const uint8_t **serial_number, size_t *serial_number_len, - int *pke_algor, const uint8_t **params, size_t *paramslen, - const uint8_t **decrypted_key, size_t *decrypted_key_len, const SM2_KEY *sm2_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, + uint8_t *out, size_t *outlen, size_t maxlen, const uint8_t **in, size_t *inlen) { + int ret; + int version; + int pke_algor; + const uint8_t *params; + size_t params_len; + const uint8_t *enced_key; + size_t enced_key_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + + if (cms_recipient_info_from_der(&version, + &issuer, &issuer_len, &serial, &serial_len, + &pke_algor, ¶ms, ¶ms_len, + &enced_key, &enced_key_len, + in, inlen) != 1) { + error_print(); + return -1; + } + if (issuer_len != rcpt_issuer_len + || memcmp(issuer, rcpt_issuer, rcpt_issuer_len) != 0 + || serial_len != rcpt_serial_len + || memcmp(serial, rcpt_serial, serial_len) != 0) { + return 0; + } + if (pke_algor != OID_sm2encrypt || params || params_len) { + error_print(); + return -1; + } + + if (sm2_decrypt(sm2_key, enced_key, enced_key_len, NULL, outlen) != 1 + || asn1_length_le(*outlen, maxlen) != 1 + || sm2_decrypt(sm2_key, enced_key, enced_key_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_recipient_infos_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + cms_recipient_info_print(fp, fmt, ind, "RecipientInfo", p, len); + } return 1; } @@ -1071,7 +1380,7 @@ int cms_enveloped_data_to_der( int version, const uint8_t *rcpt_infos, size_t rcpt_infos_len, int content_type, - int enc_algor, const uint8_t *enc_iv, size_t enc_iv_len, + int enc_algor, const uint8_t *iv, size_t ivlen, const uint8_t *enced_content, size_t enced_content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, @@ -1081,7 +1390,7 @@ int cms_enveloped_data_to_der( if (asn1_int_to_der(version, NULL, &len) != 1 || asn1_set_to_der(rcpt_infos, rcpt_infos_len, NULL, &len) != 1 || cms_enced_content_info_to_der(content_type, - enc_algor, enc_iv, enc_iv_len, + enc_algor, iv, ivlen, enced_content, enced_content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, @@ -1090,7 +1399,7 @@ int cms_enveloped_data_to_der( || asn1_int_to_der(version, out, outlen) != 1 || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 || cms_enced_content_info_to_der(content_type, - enc_algor, enc_iv, enc_iv_len, + enc_algor, iv, ivlen, enced_content, enced_content_len, shared_info1, shared_info1_len, shared_info2, shared_info2_len, @@ -1104,45 +1413,172 @@ int cms_enveloped_data_to_der( int cms_enveloped_data_from_der( int *version, const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, const uint8_t **in, size_t *inlen) { - return -1; + int ret; + const uint8_t *d; + size_t dlen; + + if ((ret = asn1_sequence_from_der(&d, &dlen, in, inlen)) != 1) { + if (ret < 0) error_print(); + return ret; + } + if (asn1_int_from_der(version, &d, &dlen) != 1 + || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &d, &dlen) != 1 + || asn1_any_from_der(enced_content_info, enced_content_info_len, &d, &dlen) != 1 + || asn1_length_is_zero(dlen) != 1) { + error_print(); + return -1; + } + return 1; } int cms_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_recipient_infos_print(fp, fmt, ind, "recipientInfos", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_enced_content_info_print(fp, fmt, ind, "encryptedContentInfo", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); return -1; } int cms_enveloped_data_encrypt_to_der( - int version, - const uint8_t *rcpt_certs, size_t rcpt_certs_len, // 当只有一个接收者的时候,这个参数类型非常方便 + const uint8_t *rcpt_certs, size_t rcpt_certs_len, int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, uint8_t **out, size_t *outlen) { - return -1; + uint8_t rcpt_infos[512]; + size_t rcpt_infos_len = 0; + uint8_t *p = rcpt_infos; + size_t len = 0; + + while (rcpt_certs_len) { + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + + if (asn1_any_from_der(&cert, &certlen, &rcpt_certs, &rcpt_certs_len) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1) { + error_print(); + return -1; + } + if (cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, NULL, &len) != 1 + || asn1_length_le(len, sizeof(rcpt_infos)) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, &p, &rcpt_infos_len) != 1) { + error_print(); + 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 + || cms_enced_content_info_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 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1) { + error_print(); + return -1; + } + return 1; } int cms_enveloped_data_decrypt_from_der( - int *version, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, const SM2_KEY *sm2_key, const uint8_t *issuer, size_t issuer_len, - const uint8_t *serial_number, size_t serial_number_len, + const uint8_t *serial, size_t serial_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **recipient_infos, size_t *recipient_infos_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len, const uint8_t **in, size_t *inlen) { - return -1; + int ret; + int version; + const uint8_t *rcpt_infos; + size_t rcpt_infos_len; + const uint8_t *enced_content_info; + size_t enced_content_info_len; + int enc_algor; + uint8_t key[32]; + size_t keylen; + + if (cms_enveloped_data_from_der( + &version, &rcpt_infos, &rcpt_infos_len, + &enced_content_info, &enced_content_info_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1) { + return ret; + } + *recipient_infos = rcpt_infos; + *recipient_infos_len = rcpt_infos_len; + + while (rcpt_infos_len) { + if ((ret = cms_recipient_info_decrypt_from_der( + sm2_key, + issuer, issuer_len, + serial, serial_len, + key, &keylen, sizeof(key), + &rcpt_infos, &rcpt_infos_len)) < 0) { + error_print(); + return -1; + } else if (ret) { + break; + } + } + if (!ret) { + error_print(); + return -1; + } + + if (cms_enced_content_info_decrypt_from_der( + &enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &enced_content_info, &enced_content_info_len) != 1) { + error_print(); + return -1; + } + return 1; } int cms_signed_and_enveloped_data_to_der( @@ -1195,11 +1631,7 @@ int cms_signed_and_enveloped_data_from_der( int *version, const uint8_t **rcpt_infos, size_t *rcpt_infos_len, int *digest_algors, size_t *digest_algors_cnt, size_t max_digest_algors, - int *content_type, - int *enc_algor, const uint8_t **enc_iv, size_t *enc_iv_len, - const uint8_t **enced_content, size_t *enced_content_len, - const uint8_t **shared_info1, size_t *shared_info1_len, - const uint8_t **shared_info2, size_t *shared_info2_len, + const uint8_t **enced_content_info, size_t *enced_content_info_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, const uint8_t **signer_infos, size_t *signer_infos_len, @@ -1216,12 +1648,7 @@ int cms_signed_and_enveloped_data_from_der( if (asn1_int_from_der(version, &d, &dlen) != 1 || asn1_set_from_der(rcpt_infos, rcpt_infos_len, &d, &dlen) != 1 || cms_digest_algors_from_der(digest_algors, digest_algors_cnt, max_digest_algors, &d, &dlen) != 1 - || cms_enced_content_info_from_der(content_type, - enc_algor, enc_iv, enc_iv_len, - enced_content, enced_content_len, - shared_info1, shared_info1_len, - shared_info2, shared_info2_len, - &d, &dlen) != 1 + || asn1_any_from_der(enced_content_info, enced_content_info_len, &d, &dlen) != 1 || asn1_implicit_set_from_der(0, certs, certs_len, &d, &dlen) < 0 || asn1_implicit_set_from_der(1, crls, crls_len, &d, &dlen) < 0 || asn1_set_from_der(signer_infos, signer_infos_len, &d, &dlen) != 1 @@ -1234,43 +1661,254 @@ int cms_signed_and_enveloped_data_from_der( int cms_signed_and_enveloped_data_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) { + int ret, val; + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; + format_print(fp, fmt, ind, "version: %d\n", val); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_recipient_infos_print(fp, fmt, ind, "recipientInfos", p, len); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_digest_algors_print(fp, fmt, ind, "digestAlgorithms", p, len); + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_enced_content_info_print(fp, fmt, ind, "encryptedContentInfo", p, len); + if ((ret = asn1_implicit_set_from_der(0, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_certs_print(fp, fmt, ind, "certificates", p, len); + if ((ret = asn1_implicit_set_from_der(1, &p, &len, &d, &dlen)) < 0) goto err; + if (ret) x509_crls_print(fp, fmt, ind, "crls", p, len); + if (asn1_set_from_der(&p, &len, &d, &dlen) != 1) goto err; + cms_signer_infos_print(fp, fmt, ind, "signerInfos", p, len); + if (asn1_length_is_zero(dlen) != 1) goto err; + return 1; +err: + error_print(); return -1; } -int cms_signed_and_enveloped_encipher_to_der( - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, +int cms_signed_and_enveloped_data_encipher_to_der( + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, - const uint8_t *signer_crls, size_t signer_crls_len, + const uint8_t *signers_crls, size_t signers_crls_len, const uint8_t *shared_info1, size_t shared_info1_len, const uint8_t *shared_info2, size_t shared_info2_len, uint8_t **out, size_t *outlen) { - return 0; + uint8_t rcpt_infos[512]; + size_t rcpt_infos_len = 0; + int digest_algors[] = { OID_sm3 }; + size_t digest_algors_cnt = sizeof(digest_algors)/sizeof(int); + uint8_t content_info_header[256]; + size_t content_info_header_len = 0; + uint8_t signer_infos[512]; + size_t signer_infos_len = 0; + SM3_CTX sm3_ctx; + const uint8_t *issuer; + const uint8_t *serial; + size_t issuer_len; + size_t serial_len; + uint8_t *p; + size_t len = 0; + size_t i; + + p = rcpt_infos; + while (rcpt_certs_len) { + const uint8_t *cert; + size_t certlen; + SM2_KEY public_key; + + if (asn1_any_from_der(&cert, &certlen, &rcpt_certs, &rcpt_certs_len) != 1 + || x509_cert_get_issuer_and_serial_number(cert, certlen, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(cert, certlen, &public_key) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, NULL, &len) != 1 + || asn1_length_le(len, sizeof(rcpt_infos)) != 1 + || cms_recipient_info_encrypt_to_der(&public_key, + issuer, issuer_len, serial, serial_len, + key, keylen, &p, &rcpt_infos_len) != 1) { + error_print(); + return -1; + } + } + + p = content_info_header; + if (cms_content_info_header_to_der(content_type, content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, content, content_len); + + for (i = 0; i < signers_cnt; i++) { + if (x509_cert_get_issuer_and_serial_number( + signers[i].certs, signers[i].certs_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || cms_signer_infos_add_signer_info( + signer_infos, &signer_infos_len, sizeof(signer_infos), + &sm3_ctx, signers->sign_key, + issuer, issuer_len, serial, serial_len, + NULL, 0, NULL, 0) != 1) { + error_print(); + 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 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, NULL, &len) != 1 + || cms_enced_content_info_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_implicit_signers_certs_to_der(0, signers, signers_cnt, NULL, &len) != 1 + || asn1_implicit_set_to_der(1, signers_crls, signers_crls_len, NULL, &len) < 0 + || asn1_set_to_der(signer_infos, signer_infos_len, NULL, &len) != 1 + || asn1_sequence_header_to_der(len, out, outlen) != 1 + || asn1_int_to_der(CMS_version_v1, out, outlen) != 1 + || asn1_set_to_der(rcpt_infos, rcpt_infos_len, out, outlen) != 1 + || cms_digest_algors_to_der(digest_algors, digest_algors_cnt, out, outlen) != 1 + || cms_enced_content_info_encrypt_to_der( + enc_algor, key, keylen, iv, ivlen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + out, outlen) != 1 + || cms_implicit_signers_certs_to_der(0, signers, signers_cnt, out, outlen) != 1 + || asn1_implicit_set_to_der(1, signers_crls, signers_crls_len, out, outlen) != 1 + || asn1_set_to_der(signer_infos, signer_infos_len, out, outlen) != 1) { + error_print(); + return -1; + } + return 1; } -int cms_deenvelop_and_verify_decipher_from_der( - int *version, - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, - const uint8_t **digest_algors, size_t *digest_algors_len, - int *enc_algor, uint8_t *key, size_t *keylen, const uint8_t **iv, size_t *ivlen, +int cms_signed_and_enveloped_data_decipher_from_der( + const SM2_KEY *rcpt_key, + const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, + const uint8_t *rcpt_serial, size_t rcpt_serial_len, int *content_type, uint8_t *content, size_t *content_len, - const uint8_t **enced_content, size_t *enced_content_len, + const uint8_t **prcpt_infos, size_t *prcpt_infos_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len, const uint8_t **certs, size_t *certs_len, const uint8_t **crls, size_t *crls_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - - const SM2_KEY *rcpt_key, - const uint8_t *rcpt_issuer, size_t rcpt_issuer_len, - const uint8_t *rcpt_serial_number, size_t rcpt_serial_number_len, - const uint8_t *extra_verify_certs, size_t extra_verify_certs_len, - const uint8_t *extra_verify_crls, size_t extra_verify_crls_len, - + const uint8_t **psigner_infos, size_t *psigner_infos_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, const uint8_t **in, size_t *inlen) { - return 0; + int ret; + int version; + const uint8_t *rcpt_infos; + size_t rcpt_infos_len; + int digest_algors[4]; + size_t digest_algors_cnt; + const uint8_t *enced_content_info; + size_t enced_content_info_len; + const uint8_t *signer_infos; + size_t signer_infos_len; + int enc_algor; + uint8_t key[32]; + size_t keylen; + SM3_CTX sm3_ctx; + uint8_t content_info_header[128]; + size_t content_info_header_len = 0; + uint8_t *p = content_info_header; + + if (cms_signed_and_enveloped_data_from_der( + &version, + &rcpt_infos, &rcpt_infos_len, + digest_algors, &digest_algors_cnt, sizeof(digest_algors)/sizeof(int), + &enced_content_info, &enced_content_info_len, + certs, certs_len, + crls, crls_len, + &signer_infos, &signer_infos_len, + in, inlen) != 1 + || asn1_check(version == CMS_version_v1) != 1 + || asn1_check(digest_algors[0] == OID_sm3) != 1) { + error_print(); + return -1; + } + *prcpt_infos = rcpt_infos; + *prcpt_infos_len = rcpt_infos_len; + *psigner_infos = signer_infos; + *psigner_infos_len = signer_infos_len; + + while (rcpt_infos_len) { + if ((ret = cms_recipient_info_decrypt_from_der( + rcpt_key, + rcpt_issuer, rcpt_issuer_len, + rcpt_serial, rcpt_serial_len, + key, &keylen, sizeof(key), + &rcpt_infos, &rcpt_infos_len)) < 0) { + error_print(); + return -1; + } else if (ret) { + break; + } + } + if (!ret) { + error_print(); + return -1; + } + + if (cms_enced_content_info_decrypt_from_der( + &enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &enced_content_info, &enced_content_info_len) != 1) { + error_print(); + return -1; + } + + if (cms_content_info_header_to_der(*content_type, *content_len, + &p, &content_info_header_len) != 1) { + error_print(); + return -1; + } + sm3_init(&sm3_ctx); + sm3_update(&sm3_ctx, content_info_header, content_info_header_len); + sm3_update(&sm3_ctx, content, *content_len); + + while (signer_infos_len) { + const uint8_t *cert; + size_t certlen; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + const uint8_t *authed_attrs; + size_t authed_attrs_len; + const uint8_t *unauthed_attrs; + size_t unauthed_attrs_len; + + if (cms_signer_info_verify_from_der( + &sm3_ctx, *certs, *certs_len, + &cert, &certlen, + &issuer, &issuer_len, + &serial, &serial_len, + &authed_attrs, &authed_attrs_len, + &unauthed_attrs, &unauthed_attrs_len, + &signer_infos, &signer_infos_len) != 1) { + error_print(); + return -1; + } + } + + return 1; } int cms_key_agreement_info_to_der( @@ -1335,7 +1973,7 @@ int cms_key_agreement_info_print(FILE *fp, int fmt, int ind, const char *label, if (asn1_int_from_der(&val, &d, &dlen) != 1) goto err; format_print(fp, fmt, ind, "version: %d\n", val); if (sm2_public_key_info_from_der(&pub_key, &d, &dlen) != 1) goto err; - //sm2_public_key_info_print(fp, fmt, ind, "tempPublicKeyR", &pub_key); + sm2_public_key_print(fp, fmt, ind, "tempPublicKeyR", &pub_key); if (x509_cert_from_der(&p, &len, &d, &dlen) != 1) goto err; x509_cert_print(fp, fmt, ind, p, len); if (asn1_octet_string_from_der(&p, &len, &d, &dlen) != 1) goto err; @@ -1347,134 +1985,357 @@ err: return -1; } -// 是否要提供一个返回长度的功能?此时不返回错误? -int cms_set_data(uint8_t *cms, size_t *cmslen, size_t maxlen, const uint8_t *d, size_t dlen) +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; + *cmslen = 0; - if (cms_content_info_to_der(OID_cms_data, d, dlen, NULL, &len) != 1 - || asn1_length_le(len, maxlen) != 1 - || cms_content_info_to_der(OID_cms_data, d, dlen, &cms, cmslen) != 1) { + if (asn1_octet_string_to_der(d, dlen, NULL, &len) < 0 + || 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; } return 1; } -int cms_encrypt( - int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法、密钥和IV - int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 - const uint8_t *shared_info1, size_t shared_info1_len, // 附加信息 - const uint8_t *shared_info2, size_t shared_info2_len, // 附加信息 - uint8_t *cms, size_t *cmslen, size_t maxlen) +int cms_encrypt(uint8_t *cms, size_t *cmslen, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len) { - return -1; + 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 + || 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, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; } -int cms_decrypt( - const uint8_t *key, size_t keylen, // 解密密钥(我们不知道解密算法) - const uint8_t *cms, size_t cms_len, // 输入的ContentInfo (type encryptedData) - const uint8_t *extra_enced_content, size_t extra_enced_content_len, // EncryptedContentInfo的密文数据为空时显示提供输入密文 - int *content_type, uint8_t *content, size_t *content_len, // 输出的解密数据类型及数据 - int *enc_algor, const uint8_t **iv, size_t *ivlen, // 解析EncryptedContentInfo得到的对称加密算法及参数 - const uint8_t **shared_info1, size_t *shared_info1_len, // 附加信息 - const uint8_t **shared_info2, size_t *shared_info2_len) -{ - return -1; -} - -int cms_sign( - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, // 签名者的签名私钥和证书 - int content_type, const uint8_t *content, size_t content_len, // 待签名的输入数据 - const uint8_t *crls, size_t crls_len, // 签名者证书的CRL - uint8_t *cms, size_t *cms_len) // 输出的ContentInfo (type signedData -{ - return -1; -} - -int cms_verify( - const uint8_t *cms, size_t cms_len, // 输入的ContentInfo (type signedData) - const uint8_t *extra_content, size_t extra_content_len, // ContentInfo的数据为空时显示提供输入 - const uint8_t *extra_certs, size_t extra_certs_len, // 当SignedData中未提供证书时显示输入 - const uint8_t *extra_crls, size_t extra_crls_len, // 当SignedData中未提供CRL时显示输入 - int *content_type, const uint8_t **content, size_t *content_len, // 从SignedData解析得到的被签名数据 - const uint8_t **certs, size_t *certs_len, // 从SignedData解析得到的签名证书 - const uint8_t **crls, size_t *crls_len, // 从SignedData解析得到的CRL - const uint8_t **signer_infos, size_t *signer_infos_len) // 从SignedData解析得到的SignerInfos,可用于显示验证结果 -{ - return -1; -} - - -int cms_envelop( - const uint8_t *rcpt_certs, size_t rcpt_certs_len, // 接收方证书,注意这个参数的类型可以容纳多个证书,但是只有在一个接受者时对调用方最方便 - int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, // 对称加密算法及参数 - int content_type, const uint8_t *content, size_t content_len, // 待加密的输入数据 - const uint8_t *shared_info1, size_t shared_info1_len, // 附加输入信息 - const uint8_t *shared_info2, size_t shared_info2_len, // 附加输入信息 - uint8_t *cms, size_t *cms_len) // 输出ContentInfo -{ - return -1; -} - -int cms_deenvelop( - const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, // 接收方的解密私钥和对应的证书,注意只需要一个解密方 - const uint8_t *cms, size_t cms_len, - const uint8_t *extra_enced_content, size_t extra_enced_content_len, // 显式输入的密文 +int cms_decrypt(const uint8_t *cms, size_t cmslen, + int *enc_algor, const uint8_t *key, size_t keylen, int *content_type, uint8_t *content, size_t *content_len, - int *enc_algor, const uint8_t **iv, size_t *ivlen, // 注意,对称加密的密钥就不输出了 - const uint8_t **rcpt_infos, size_t *rcpt_infos_len, // 解析得到,用于显示 const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len) { - return -1; + int cms_type; + const uint8_t *cms_content; + 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_encrypted_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + if (cms_encrypted_data_decrypt_from_der( + enc_algor, key, keylen, + content_type, content, content_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; } -int cms_sign_and_envelop( // 参考cms_sign, cms_envelop - const CMS_CERT_AND_KEY *signers, size_t signers_cnt, +int cms_sign(uint8_t *cms, size_t *cmslen, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *crls, size_t crls_len) +{ + 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 + || cms_signed_data_sign_to_der( + signers, signers_cnt, + content_type, content, content_len, + crls, crls_len, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_verify(const uint8_t *cms, size_t cmslen, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + int *content_type, const uint8_t **content, size_t *content_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **signer_infos, size_t *signer_infos_len) +{ + int cms_type; + const uint8_t *cms_content; + 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_signed_data_verify_from_der( + extra_certs, extra_certs_len, + extra_crls, extra_crls_len, + content_type, content, content_len, + certs, certs_len, + crls, crls_len, + signer_infos, signer_infos_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_envelop( + uint8_t *cms, size_t *cmslen, const uint8_t *rcpt_certs, size_t rcpt_certs_len, int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, int content_type, const uint8_t *content, size_t content_len, - const uint8_t *signer_crls, size_t signer_crls_len, const uint8_t *shared_info1, size_t shared_info1_len, - const uint8_t *shared_info2, size_t shared_info2_len, - uint8_t *cms, size_t *cms_len) + const uint8_t *shared_info2, size_t shared_info2_len) { - return -1; + 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 + || 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, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; } -int cms_deenvelop_and_verify( // 参考cms_deenvelop, cms_verify +int cms_deenvelop(const uint8_t *cms, size_t cmslen, const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, - // 输入 - const uint8_t *cms, size_t cms_len, - const uint8_t *extra_enced_content, size_t extra_enced_content_len, - const uint8_t *extra_signer_certs, size_t extra_signer_certs_len, - const uint8_t *extra_signer_crls, size_t extra_signer_crls_len, - // 输出 int *content_type, uint8_t *content, size_t *content_len, - // 格外的解析内容输出,均为可选 - int *enc_algor, const uint8_t **iv, size_t *ivlen, - const uint8_t **rcpt_infos, size_t rcpt_infos_len, - const uint8_t **signer_infos, size_t *signer_infos_len, - const uint8_t **signer_certs, size_t *signer_certs_len, - const uint8_t **signer_crls, size_t *signer_crls_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, const uint8_t **shared_info1, size_t *shared_info1_len, const uint8_t **shared_info2, size_t *shared_info2_len) { - return -1; + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + const uint8_t *issuer; + size_t issuer_len; + const uint8_t *serial; + size_t serial_len; + SM2_KEY public_key; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_check(cms_type == OID_cms_enveloped_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + + if (x509_cert_get_issuer_and_serial_number(rcpt_cert, rcpt_cert_len, + &issuer, &issuer_len, &serial, &serial_len) != 1 + || x509_cert_get_subject_public_key(rcpt_cert, rcpt_cert_len, + &public_key) != 1) { + error_print(); + return -1; + } + if (memcmp(&public_key, rcpt_key, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + + if (cms_enveloped_data_decrypt_from_der( + rcpt_key, issuer, issuer_len, serial, serial_len, + content_type, content, content_len, + rcpt_infos, rcpt_infos_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_sign_and_envelop(uint8_t *cms, size_t *cmslen, + const CMS_CERTS_AND_KEY *signers, size_t signers_cnt, + const uint8_t *rcpt_certs, size_t rcpt_certs_len, + int enc_algor, const uint8_t *key, size_t keylen, const uint8_t *iv, size_t ivlen, + int content_type, const uint8_t *content, size_t content_len, + const uint8_t *crls, size_t crls_len, + const uint8_t *shared_info1, size_t shared_info1_len, + const uint8_t *shared_info2, size_t shared_info2_len) +{ + 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 + || 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, + &cms, cmslen) != 1) { + error_print(); + return -1; + } + return 1; +} + +int cms_deenvelop_and_verify(const uint8_t *cms, size_t cmslen, + const SM2_KEY *rcpt_key, const uint8_t *rcpt_cert, size_t rcpt_cert_len, + const uint8_t *extra_certs, size_t extra_certs_len, + const uint8_t *extra_crls, size_t extra_crls_len, + int *content_type, uint8_t *content, size_t *content_len, + const uint8_t **rcpt_infos, size_t *rcpt_infos_len, + const uint8_t **signer_infos, size_t *signer_infos_len, + const uint8_t **certs, size_t *certs_len, + const uint8_t **crls, size_t *crls_len, + const uint8_t **shared_info1, size_t *shared_info1_len, + const uint8_t **shared_info2, size_t *shared_info2_len) +{ + const uint8_t *rcpt_issuer; + size_t rcpt_issuer_len; + const uint8_t *rcpt_serial; + size_t rcpt_serial_len; + SM2_KEY public_key; + int cms_type; + const uint8_t *cms_content; + size_t cms_content_len; + int digest_algors[4]; + size_t digest_algors_cnt; + + if (cms_content_info_from_der(&cms_type, &cms_content, &cms_content_len, &cms, &cmslen) != 1 + || asn1_check(cms_type == OID_cms_signed_and_enveloped_data) != 1 + || asn1_check(cms_content && cms_content_len) != 1 + || asn1_length_is_zero(cmslen) != 1) { + error_print(); + return -1; + } + + if (x509_cert_get_issuer_and_serial_number(rcpt_cert, rcpt_cert_len, + &rcpt_issuer, &rcpt_issuer_len, + &rcpt_serial, &rcpt_serial_len) != 1 + || x509_cert_get_subject_public_key(rcpt_cert, rcpt_cert_len, + &public_key) != 1) { + error_print(); + return -1; + } + if (memcmp(&public_key, rcpt_key, sizeof(SM2_POINT)) != 0) { + error_print(); + return -1; + } + + if (cms_signed_and_enveloped_data_decipher_from_der( + rcpt_key, + rcpt_issuer, rcpt_issuer_len, + rcpt_serial, rcpt_serial_len, + content_type, content, content_len, + rcpt_infos, rcpt_infos_len, + shared_info1, shared_info1_len, + shared_info2, shared_info2_len, + certs, certs_len, + crls, crls_len, + signer_infos, signer_infos_len, + extra_certs, extra_certs_len, + extra_crls, extra_crls_len, + &cms_content, &cms_content_len) != 1 + || asn1_length_is_zero(cms_content_len) != 1) { + error_print(); + return -1; + } + return 1; } -// 生成ContentInfo, type == keyAgreementInfo int cms_set_key_agreement_info( - uint8_t *cms, size_t *cms_len, + uint8_t *cms, size_t *cmslen, const SM2_KEY *temp_public_key_r, const uint8_t *user_cert, size_t user_cert_len, const uint8_t *user_id, size_t user_id_len) { - return -1; + 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 + || 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(); + return -1; + } + return 1; } -int cms_print(FILE *fp, int fmt, int ind, const uint8_t *a, size_t alen) +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; + return 1; +err: + error_print(); return -1; } diff --git a/src/sm2_prn.c b/src/sm2_prn.c index 66a5d1b6..c1ec6fcb 100644 --- a/src/sm2_prn.c +++ b/src/sm2_prn.c @@ -64,6 +64,12 @@ int sm2_key_print(FILE *fp, int format, int indent, const char *label, const SM2 return 1; } +int sm2_public_key_print(FILE *fp, int fmt, int ind, const char *label, const SM2_KEY *pub_key) +{ + sm2_point_print(fp, fmt, ind + 4, "public_key", &pub_key->public_key); + return 1; +} + int sm2_point_print(FILE *fp, int format, int indent, const char *label, const SM2_POINT *P) { format_bytes(fp, format, indent, "x : ", P->x, 32); diff --git a/src/x509_cer.c b/src/x509_cer.c index 9fd0aa52..29fc6636 100644 --- a/src/x509_cer.c +++ b/src/x509_cer.c @@ -1237,3 +1237,49 @@ int x509_certs_get_cert_by_subject(const uint8_t *d, size_t dlen, error_print(); return -1; } + +int x509_certs_get_cert_by_issuer_and_serial_number( + const uint8_t *certs, size_t certs_len, + const uint8_t *issuer, size_t issuer_len, + const uint8_t *serial, size_t serial_len, + const uint8_t **cert, size_t *cert_len) +{ + const uint8_t *cur_issuer; + size_t cur_issuer_len; + const uint8_t *cur_serial; + size_t cur_serial_len; + + while (certs_len) { + if (asn1_any_from_der(cert, cert_len, &certs, &certs_len) != 1 + || x509_cert_get_issuer_and_serial_number(*cert, *cert_len, + &cur_issuer, &cur_issuer_len, + &cur_serial, &cur_serial_len) != 1) { + error_print(); + return -1; + } + if (cur_issuer_len == issuer_len + && memcmp(cur_issuer, issuer, issuer_len) == 0 + && cur_serial_len == serial_len + && memcmp(cur_serial, serial, serial_len) == 0) { + return 1; + } + } + return 0; +} +int x509_certs_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_certificate_print(fp, fmt, ind, "Certficate", p, len); + } + return 1; +} diff --git a/src/x509_crl.c b/src/x509_crl.c index 6bb2b679..612464bb 100644 --- a/src/x509_crl.c +++ b/src/x509_crl.c @@ -581,3 +581,21 @@ int x509_crl_get_revoked_cert_by_serial_number(const uint8_t *a, size_t alen, { return 1; } + +int x509_crls_print(FILE *fp, int fmt, int ind, const char *label, const uint8_t *d, size_t dlen) +{ + const uint8_t *p; + size_t len; + + format_print(fp, fmt, ind, "%s\n", label); + ind += 4; + + while (dlen) { + if (asn1_sequence_from_der(&p, &len, &d, &dlen) != 1) { + error_print(); + return -1; + } + x509_cert_list_print(fp, fmt, ind, "CertificateRevocationList", p, len); + } + return 1; +}