summaryrefslogtreecommitdiff
path: root/crypto/cms
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2008-03-28 19:43:16 +0000
committerDr. Stephen Henson <steve@openssl.org>2008-03-28 19:43:16 +0000
commit36309aa2be6c80fcb6500d3c189d1d6bc52e11f3 (patch)
treee9b4d2c831cb0af64346ceda54a8aac5b467ae58 /crypto/cms
parenteb9d8d8cd4ef3b1b6e1a14954c5b16438c27abf9 (diff)
downloadopenssl-new-36309aa2be6c80fcb6500d3c189d1d6bc52e11f3.tar.gz
Signed receipt generation code.
Diffstat (limited to 'crypto/cms')
-rw-r--r--crypto/cms/cms.h9
-rw-r--r--crypto/cms/cms_err.c4
-rw-r--r--crypto/cms/cms_ess.c71
-rw-r--r--crypto/cms/cms_lcl.h2
-rw-r--r--crypto/cms/cms_smime.c72
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)
{