diff options
author | Dr. Stephen Henson <steve@openssl.org> | 2008-03-28 19:43:16 +0000 |
---|---|---|
committer | Dr. Stephen Henson <steve@openssl.org> | 2008-03-28 19:43:16 +0000 |
commit | 36309aa2be6c80fcb6500d3c189d1d6bc52e11f3 (patch) | |
tree | e9b4d2c831cb0af64346ceda54a8aac5b467ae58 /crypto/cms | |
parent | eb9d8d8cd4ef3b1b6e1a14954c5b16438c27abf9 (diff) |
Signed receipt generation code.
Diffstat (limited to 'crypto/cms')
-rw-r--r-- | crypto/cms/cms.h | 9 | ||||
-rw-r--r-- | crypto/cms/cms_err.c | 4 | ||||
-rw-r--r-- | crypto/cms/cms_ess.c | 71 | ||||
-rw-r--r-- | crypto/cms/cms_lcl.h | 2 | ||||
-rw-r--r-- | crypto/cms/cms_smime.c | 72 |
5 files changed, 158 insertions, 0 deletions
diff --git a/crypto/cms/cms.h b/crypto/cms/cms.h index 22baa3e837..19fde29e93 100644 --- a/crypto/cms/cms.h +++ b/crypto/cms/cms.h @@ -140,6 +140,11 @@ int CMS_final(CMS_ContentInfo *cms, BIO *data, int flags); CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, BIO *data, unsigned int flags); +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, + unsigned int flags); + int CMS_data(CMS_ContentInfo *cms, BIO *out, unsigned int flags); CMS_ContentInfo *CMS_data_create(BIO *in, unsigned int flags); @@ -342,6 +347,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_DIGESTALGORITHM_INIT_BIO 116 #define CMS_F_CMS_DIGESTEDDATA_DO_FINAL 117 #define CMS_F_CMS_DIGEST_VERIFY 118 +#define CMS_F_CMS_ENCODE_RECEIPT 161 #define CMS_F_CMS_ENCRYPT 119 #define CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO 120 #define CMS_F_CMS_ENCRYPTEDDATA_DECRYPT 121 @@ -357,6 +363,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_GET0_ENVELOPED 131 #define CMS_F_CMS_GET0_REVOCATION_CHOICES 132 #define CMS_F_CMS_GET0_SIGNED 133 +#define CMS_F_CMS_MSGSIGDIGEST_ADD1 162 #define CMS_F_CMS_RECEIPTREQUEST_CREATE0 159 #define CMS_F_CMS_RECEIPT_VERIFY 160 #define CMS_F_CMS_RECIPIENTINFO_DECRYPT 134 @@ -380,6 +387,7 @@ void ERR_load_CMS_strings(void); #define CMS_F_CMS_SIGNERINFO_VERIFY 152 #define CMS_F_CMS_SIGNERINFO_VERIFY_CERT 153 #define CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT 154 +#define CMS_F_CMS_SIGN_RECEIPT 163 #define CMS_F_CMS_STREAM 155 #define CMS_F_CMS_UNCOMPRESS 156 #define CMS_F_CMS_VERIFY 157 @@ -427,6 +435,7 @@ void ERR_load_CMS_strings(void); #define CMS_R_NO_DEFAULT_DIGEST 128 #define CMS_R_NO_DIGEST_SET 129 #define CMS_R_NO_KEY 130 +#define CMS_R_NO_KEY_OR_CERT 174 #define CMS_R_NO_MATCHING_DIGEST 131 #define CMS_R_NO_MATCHING_RECIPIENT 132 #define CMS_R_NO_MATCHING_SIGNATURE 166 diff --git a/crypto/cms/cms_err.c b/crypto/cms/cms_err.c index 420a401770..9c813e5db6 100644 --- a/crypto/cms/cms_err.c +++ b/crypto/cms/cms_err.c @@ -91,6 +91,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_DIGESTALGORITHM_INIT_BIO), "CMS_DIGESTALGORITHM_INIT_BIO"}, {ERR_FUNC(CMS_F_CMS_DIGESTEDDATA_DO_FINAL), "CMS_DIGESTEDDATA_DO_FINAL"}, {ERR_FUNC(CMS_F_CMS_DIGEST_VERIFY), "CMS_digest_verify"}, +{ERR_FUNC(CMS_F_CMS_ENCODE_RECEIPT), "CMS_ENCODE_RECEIPT"}, {ERR_FUNC(CMS_F_CMS_ENCRYPT), "CMS_encrypt"}, {ERR_FUNC(CMS_F_CMS_ENCRYPTEDCONTENT_INIT_BIO), "CMS_ENCRYPTEDCONTENT_INIT_BIO"}, {ERR_FUNC(CMS_F_CMS_ENCRYPTEDDATA_DECRYPT), "CMS_EncryptedData_decrypt"}, @@ -106,6 +107,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_GET0_ENVELOPED), "CMS_GET0_ENVELOPED"}, {ERR_FUNC(CMS_F_CMS_GET0_REVOCATION_CHOICES), "CMS_GET0_REVOCATION_CHOICES"}, {ERR_FUNC(CMS_F_CMS_GET0_SIGNED), "CMS_GET0_SIGNED"}, +{ERR_FUNC(CMS_F_CMS_MSGSIGDIGEST_ADD1), "CMS_MSGSIGDIGEST_ADD1"}, {ERR_FUNC(CMS_F_CMS_RECEIPTREQUEST_CREATE0), "CMS_ReceiptRequest_create0"}, {ERR_FUNC(CMS_F_CMS_RECEIPT_VERIFY), "CMS_RECEIPT_VERIFY"}, {ERR_FUNC(CMS_F_CMS_RECIPIENTINFO_DECRYPT), "CMS_RecipientInfo_decrypt"}, @@ -129,6 +131,7 @@ static ERR_STRING_DATA CMS_str_functs[]= {ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY), "CMS_SignerInfo_verify"}, {ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CERT), "CMS_SIGNERINFO_VERIFY_CERT"}, {ERR_FUNC(CMS_F_CMS_SIGNERINFO_VERIFY_CONTENT), "CMS_SignerInfo_verify_content"}, +{ERR_FUNC(CMS_F_CMS_SIGN_RECEIPT), "CMS_SIGN_RECEIPT"}, {ERR_FUNC(CMS_F_CMS_STREAM), "CMS_stream"}, {ERR_FUNC(CMS_F_CMS_UNCOMPRESS), "CMS_uncompress"}, {ERR_FUNC(CMS_F_CMS_VERIFY), "CMS_verify"}, @@ -179,6 +182,7 @@ static ERR_STRING_DATA CMS_str_reasons[]= {ERR_REASON(CMS_R_NO_DEFAULT_DIGEST) ,"no default digest"}, {ERR_REASON(CMS_R_NO_DIGEST_SET) ,"no digest set"}, {ERR_REASON(CMS_R_NO_KEY) ,"no key"}, +{ERR_REASON(CMS_R_NO_KEY_OR_CERT) ,"no key or cert"}, {ERR_REASON(CMS_R_NO_MATCHING_DIGEST) ,"no matching digest"}, {ERR_REASON(CMS_R_NO_MATCHING_RECIPIENT) ,"no matching recipient"}, {ERR_REASON(CMS_R_NO_MATCHING_SIGNATURE) ,"no matching signature"}, diff --git a/crypto/cms/cms_ess.c b/crypto/cms/cms_ess.c index ff9b2a86f2..b2ff4fc595 100644 --- a/crypto/cms/cms_ess.c +++ b/crypto/cms/cms_ess.c @@ -190,6 +190,8 @@ void CMS_ReceiptRequest_get0_values(CMS_ReceiptRequest *rr, *prto = rr->receiptsTo; } +/* Digest a SignerInfo structure for msgSigDigest attribute processing */ + static int cms_msgSigDigest(CMS_SignerInfo *si, unsigned char *dig, unsigned int *diglen) { @@ -203,6 +205,26 @@ static int cms_msgSigDigest(CMS_SignerInfo *si, return 1; } +/* Add a msgSigDigest attribute to a SignerInfo */ + +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src) + { + unsigned char dig[EVP_MAX_MD_SIZE]; + unsigned int diglen; + if (!cms_msgSigDigest(src, dig, &diglen)) + { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, CMS_R_MSGSIGDIGEST_ERROR); + return 0; + } + if (!CMS_signed_add1_attr_by_NID(dest, NID_id_smime_aa_msgSigDigest, + V_ASN1_OCTET_STRING, dig, diglen)) + { + CMSerr(CMS_F_CMS_MSGSIGDIGEST_ADD1, ERR_R_MALLOC_FAILURE); + return 0; + } + return 1; + } + /* Verify signed receipt after it has already passed normal CMS verify */ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) @@ -348,3 +370,52 @@ int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms) return r; } + +/* Encode a Receipt into an OCTET STRING read for including into content of + * a SignedData ContentInfo. + */ + +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si) + { + CMS_Receipt rct; + CMS_ReceiptRequest *rr = NULL; + ASN1_OBJECT *ctype; + ASN1_OCTET_STRING *os = NULL; + + /* Get original receipt request */ + + /* Get original receipt request details */ + + if (!CMS_get1_ReceiptRequest(si, &rr)) + { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_RECEIPT_REQUEST); + goto err; + } + + /* Get original content type */ + + ctype = CMS_signed_get0_data_by_OBJ(si, + OBJ_nid2obj(NID_pkcs9_contentType), + -3, V_ASN1_OBJECT); + if (!ctype) + { + CMSerr(CMS_F_CMS_ENCODE_RECEIPT, CMS_R_NO_CONTENT_TYPE); + goto err; + } + + rct.version = 1; + rct.contentType = ctype; + rct.signedContentIdentifier = rr->signedContentIdentifier; + rct.originatorSignatureValue = si->signature; + + os = ASN1_item_pack(&rct, ASN1_ITEM_rptr(CMS_Receipt), NULL); + + err: + if (rr) + CMS_ReceiptRequest_free(rr); + + return os; + + } + + diff --git a/crypto/cms/cms_lcl.h b/crypto/cms/cms_lcl.h index ec644c36fb..c8ecfa724a 100644 --- a/crypto/cms/cms_lcl.h +++ b/crypto/cms/cms_lcl.h @@ -450,6 +450,8 @@ int cms_EncryptedContent_init(CMS_EncryptedContentInfo *ec, const unsigned char *key, size_t keylen); int cms_Receipt_verify(CMS_ContentInfo *cms, CMS_ContentInfo *req_cms); +int cms_msgSigDigest_add1(CMS_SignerInfo *dest, CMS_SignerInfo *src); +ASN1_OCTET_STRING *cms_encode_Receipt(CMS_SignerInfo *si); BIO *cms_EnvelopedData_init_bio(CMS_ContentInfo *cms); diff --git a/crypto/cms/cms_smime.c b/crypto/cms/cms_smime.c index b37d17c5af..48885ce675 100644 --- a/crypto/cms/cms_smime.c +++ b/crypto/cms/cms_smime.c @@ -471,6 +471,78 @@ CMS_ContentInfo *CMS_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs, return NULL; } +CMS_ContentInfo *CMS_sign_receipt(CMS_SignerInfo *si, + X509 *signcert, EVP_PKEY *pkey, + STACK_OF(X509) *certs, + unsigned int flags) + { + CMS_SignerInfo *rct_si; + CMS_ContentInfo *cms = NULL; + ASN1_OCTET_STRING **pos, *os; + BIO *rct_cont = NULL; + int r = 0; + + flags &= ~CMS_STREAM; + /* Not really detached but avoids content being allocated */ + flags |= CMS_PARTIAL|CMS_BINARY|CMS_DETACHED; + if (!pkey || !signcert) + { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_NO_KEY_OR_CERT); + return NULL; + } + + /* Initialize signed data */ + + cms = CMS_sign(NULL, NULL, certs, NULL, flags); + if (!cms) + goto err; + + /* Set inner content type to signed receipt */ + if (!CMS_set1_eContentType(cms, OBJ_nid2obj(NID_id_smime_ct_receipt))) + goto err; + + rct_si = CMS_add1_signer(cms, signcert, pkey, NULL, flags); + if (!rct_si) + { + CMSerr(CMS_F_CMS_SIGN_RECEIPT, CMS_R_ADD_SIGNER_ERROR); + goto err; + } + + os = cms_encode_Receipt(si); + + if (!os) + goto err; + + /* Set content to digest */ + rct_cont = BIO_new_mem_buf(os->data, os->length); + if (!rct_cont) + goto err; + + /* Add msgSigDigest attribute */ + + if (!cms_msgSigDigest_add1(rct_si, si)) + goto err; + + /* Finalize structure */ + if (!CMS_final(cms, rct_cont, flags)) + goto err; + + /* Set embedded content */ + pos = CMS_get0_content(cms); + *pos = os; + + r = 1; + + err: + if (rct_cont) + BIO_free(rct_cont); + if (r) + return cms; + CMS_ContentInfo_free(cms); + return NULL; + + } + CMS_ContentInfo *CMS_encrypt(STACK_OF(X509) *certs, BIO *data, const EVP_CIPHER *cipher, unsigned int flags) { |