summaryrefslogtreecommitdiff
path: root/security/nss
diff options
context:
space:
mode:
authorrrelyea%redhat.com <devnull@localhost>2011-01-28 23:08:27 +0000
committerrrelyea%redhat.com <devnull@localhost>2011-01-28 23:08:27 +0000
commitee7a00d669c3d01a5c4ab2f74c3b74f42142d289 (patch)
treeccea67d6192c53d5c7601e3e6590b8f119a4cc13 /security/nss
parent7e8bc4b5ed3d4c311681fd2d839c63578463123a (diff)
downloadnss-hg-ee7a00d669c3d01a5c4ab2f74c3b74f42142d289.tar.gz
Bug 584224 - CMS does not allow content types other than S/MIME
Part 1 Patch by rrelyea r=emaldona
Diffstat (limited to 'security/nss')
-rw-r--r--security/nss/lib/smime/cms.h53
-rw-r--r--security/nss/lib/smime/cmsasn1.c14
-rw-r--r--security/nss/lib/smime/cmscinfo.c113
-rw-r--r--security/nss/lib/smime/cmsdecode.c136
-rw-r--r--security/nss/lib/smime/cmsdigdata.c35
-rw-r--r--security/nss/lib/smime/cmsencdata.c31
-rw-r--r--security/nss/lib/smime/cmsencode.c105
-rw-r--r--security/nss/lib/smime/cmsenvdata.c30
-rw-r--r--security/nss/lib/smime/cmslocal.h43
-rw-r--r--security/nss/lib/smime/cmsmessage.c6
-rw-r--r--security/nss/lib/smime/cmssigdata.c32
-rw-r--r--security/nss/lib/smime/cmst.h26
-rw-r--r--security/nss/lib/smime/cmsutil.c9
-rw-r--r--security/nss/lib/smime/manifest.mn1
-rw-r--r--security/nss/lib/smime/smime.def8
15 files changed, 412 insertions, 230 deletions
diff --git a/security/nss/lib/smime/cms.h b/security/nss/lib/smime/cms.h
index b7f60fb58..d71d0bcb0 100644
--- a/security/nss/lib/smime/cms.h
+++ b/security/nss/lib/smime/cms.h
@@ -303,6 +303,14 @@ extern SECStatus
NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, NSSCMSEncryptedData *encd);
/*
+ * turn off streaming for this content type.
+ * This could fail with SEC_ERROR_NO_MEMORY in memory constrained conditions.
+ */
+extern SECStatus
+NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream);
+
+
+/*
* NSS_CMSContentInfo_GetContent - get pointer to inner content
*
* needs to be casted...
@@ -1128,6 +1136,51 @@ NSS_CMSDEREncode(NSSCMSMessage *cmsg, SECItem *input, SECItem *derOut,
PLArenaPool *arena);
+/************************************************************************
+ *
+ ************************************************************************/
+
+/*
+ * define new S/MIME content type entries
+ *
+ * S/MIME uses the builtin PKCS7 oid types for encoding and decoding the
+ * various S/MIME content. Some applications have their own content type
+ * which is different from the standard content type defined by S/MIME.
+ *
+ * This function allows you to register new content types. There are basically
+ * Two different types of content, Wrappping content, and Data.
+ *
+ * For data types, All the functions below can be zero or NULL excext
+ * type and is isData, which should be your oid tag and PR_FALSE respectively
+ *
+ * For wrapping types, everything must be provided, or you will get encoder
+ * failures.
+ *
+ * If NSS doesn't already define the OID that you need, you can register
+ * your own with SECOID_AddEntry.
+ *
+ * Once you have defined your new content type, you can pass your new content
+ * type to NSS_CMSContentInfo_SetContent().
+ *
+ * If you are using a wrapping type you can pass your own data structure in
+ * the ptr field, but it must contain and embedded NSSCMSGenericWrappingData
+ * structure as the first element. The size you pass to
+ * NSS_CMSType_RegisterContentType is the total size of your self defined
+ * data structure. NSS_CMSContentInfo_GetContent will return that data
+ * structure from the content info. Your ASN1Template will be evaluated
+ * against that data structure.
+ */
+SECStatus NSS_CMSType_RegisterContentType(SECOidTag type,
+ SEC_ASN1Template *template, size_t size,
+ NSSCMSGenericWrapperDataDestroy *destroy,
+ NSSCMSGenericWrapperDataCallback * decode_before,
+ NSSCMSGenericWrapperDataCallback * decode_after,
+ NSSCMSGenericWrapperDataCallback * decode_end,
+ NSSCMSGenericWrapperDataCallback * encode_start,
+ NSSCMSGenericWrapperDataCallback * encode_before,
+ NSSCMSGenericWrapperDataCallback * encode_after,
+ PRBool isData);
+
/************************************************************************/
SEC_END_PROTOS
diff --git a/security/nss/lib/smime/cmsasn1.c b/security/nss/lib/smime/cmsasn1.c
index 31f9be4d7..b1c1577f8 100644
--- a/security/nss/lib/smime/cmsasn1.c
+++ b/security/nss/lib/smime/cmsasn1.c
@@ -547,18 +547,22 @@ nss_cms_choose_content_template(void *src_or_dest, PRBool encoding)
{
const SEC_ASN1Template *theTemplate;
NSSCMSContentInfo *cinfo;
+ SECOidTag type;
PORT_Assert (src_or_dest != NULL);
if (src_or_dest == NULL)
return NULL;
cinfo = (NSSCMSContentInfo *)src_or_dest;
- switch (NSS_CMSContentInfo_GetContentTypeTag(cinfo)) {
- default:
- theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
- break;
- case SEC_OID_PKCS7_DATA:
+ type = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+ if (NSS_CMSType_IsData(type)) {
theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate);
+ } else switch (type) {
+ default:
+ theTemplate = NSS_CMSType_GetTemplate(type);
+ if (theTemplate == NULL) {
+ theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate);
+ }
break;
case SEC_OID_PKCS7_SIGNED_DATA:
theTemplate = NSS_PointerToCMSSignedDataTemplate;
diff --git a/security/nss/lib/smime/cmscinfo.c b/security/nss/lib/smime/cmscinfo.c
index 1129ea33e..73e4eda87 100644
--- a/security/nss/lib/smime/cmscinfo.c
+++ b/security/nss/lib/smime/cmscinfo.c
@@ -47,11 +47,37 @@
#include "secoid.h"
#include "secerr.h"
+
/*
* NSS_CMSContentInfo_Create - create a content info
*
* version is set in the _Finalize procedures for each content type
*/
+SECStatus
+NSS_CMSContentInfo_Private_Init(NSSCMSContentInfo *cinfo)
+{
+ if (cinfo->private) {
+ return SECSuccess;
+ }
+ cinfo->private = PORT_ZNew(NSSCMSContentInfoPrivate);
+ return (cinfo->private) ? SECSuccess: SECFailure;
+}
+
+
+static void
+nss_cmsContentInfo_private_destroy(NSSCMSContentInfoPrivate *private)
+{
+ if (private->digcx) {
+ /* must destroy digest objects */
+ NSS_CMSDigestContext_Cancel(private->digcx);
+ private->digcx = NULL;
+ }
+ if (private->ciphcx) {
+ NSS_CMSCipherContext_Destroy(private->ciphcx);
+ private->ciphcx = NULL;
+ }
+ PORT_Free(private);
+}
/*
* NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces.
@@ -76,23 +102,17 @@ NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo)
NSS_CMSDigestedData_Destroy(cinfo->content.digestedData);
break;
default:
+ NSS_CMSGenericWrapperData_Destroy(kind, cinfo->content.genericData);
/* XXX Anything else that needs to be "manually" freed/destroyed? */
break;
}
- if (cinfo->digcx) {
- /* must destroy digest objects */
- NSS_CMSDigestContext_Cancel(cinfo->digcx);
- cinfo->digcx = NULL;
+ if (cinfo->private) {
+ nss_cmsContentInfo_private_destroy(cinfo->private);
+ cinfo->private = NULL;
}
- if (cinfo->bulkkey)
+ if (cinfo->bulkkey) {
PK11_FreeSymKey(cinfo->bulkkey);
-
- if (cinfo->ciphcx) {
- NSS_CMSCipherContext_Destroy(cinfo->ciphcx);
- cinfo->ciphcx = NULL;
}
-
- /* we live in a pool, so no need to worry about storage */
}
/*
@@ -101,31 +121,46 @@ NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo)
NSSCMSContentInfo *
NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo)
{
- void * ptr = NULL;
NSSCMSContentInfo * ccinfo = NULL;
SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
switch (tag) {
case SEC_OID_PKCS7_SIGNED_DATA:
- ptr = (void *)cinfo->content.signedData;
ccinfo = &(cinfo->content.signedData->contentInfo);
break;
case SEC_OID_PKCS7_ENVELOPED_DATA:
- ptr = (void *)cinfo->content.envelopedData;
ccinfo = &(cinfo->content.envelopedData->contentInfo);
break;
case SEC_OID_PKCS7_DIGESTED_DATA:
- ptr = (void *)cinfo->content.digestedData;
ccinfo = &(cinfo->content.digestedData->contentInfo);
break;
case SEC_OID_PKCS7_ENCRYPTED_DATA:
- ptr = (void *)cinfo->content.encryptedData;
ccinfo = &(cinfo->content.encryptedData->contentInfo);
break;
case SEC_OID_PKCS7_DATA:
default:
+ if (NSS_CMSType_IsWrapper(tag)) {
+ ccinfo = &(cinfo->content.genericData->contentInfo);
+ }
break;
}
- return (ptr ? ccinfo : NULL);
+ if (ccinfo && !ccinfo->private) {
+ NSS_CMSContentInfo_Private_Init(ccinfo);
+ }
+ return ccinfo;
+}
+
+SECStatus
+NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream)
+{
+ SECStatus rv;
+
+ rv = NSS_CMSContentInfo_Private_Init(cinfo);
+ if (rv != SECSuccess) {
+ /* default is streaming, failure to get ccinfo will not effect this */
+ return dontStream ? SECFailure : SECSuccess ;
+ }
+ cinfo->private->dontStream = dontStream;
+ return SECSuccess;
}
/*
@@ -147,7 +182,9 @@ NSS_CMSContentInfo_SetContent(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo, SEC
cinfo->content.pointer = ptr;
- if (type != SEC_OID_PKCS7_DATA) {
+ if (NSS_CMSType_IsData(type) && ptr) {
+ cinfo->rawContent = ptr;
+ } else {
/* as we always have some inner data,
* we need to set it to something, just to fool the encoder enough to work on it
* and get us into nss_cms_encoder_notify at that point */
@@ -174,9 +211,10 @@ NSS_CMSContentInfo_SetContent_Data(NSSCMSMessage *cmsg, NSSCMSContentInfo *cinfo
{
if (NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_DATA, (void *)data) != SECSuccess)
return SECFailure;
- cinfo->rawContent = (detached) ?
- NULL : (data) ?
- data : SECITEM_AllocItem(cmsg->poolp, NULL, 1);
+ if (detached) {
+ cinfo->rawContent = NULL;
+ }
+
return SECSuccess;
}
@@ -204,6 +242,7 @@ NSS_CMSContentInfo_SetContent_EncryptedData(NSSCMSMessage *cmsg, NSSCMSContentIn
return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd);
}
+
/*
* NSS_CMSContentInfo_GetContent - get pointer to inner content
*
@@ -215,16 +254,8 @@ NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo)
SECOidTag tag = (cinfo && cinfo->contentTypeTag)
? cinfo->contentTypeTag->offset
: SEC_OID_UNKNOWN;
- switch (tag) {
- case SEC_OID_PKCS7_DATA:
- case SEC_OID_PKCS7_SIGNED_DATA:
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- case SEC_OID_PKCS7_DIGESTED_DATA:
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
- return cinfo->content.pointer;
- default:
- return NULL;
- }
+ return NSS_CMSType_IsWrapper(tag)||NSS_CMSType_IsData(tag) ?
+ cinfo->content.pointer : NULL;
}
/*
@@ -232,6 +263,7 @@ NSS_CMSContentInfo_GetContent(NSSCMSContentInfo *cinfo)
*
* this is typically only called by NSS_CMSMessage_GetContent()
*/
+
SECItem *
NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo)
{
@@ -240,26 +272,21 @@ NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo)
SECItem *pItem = NULL;
tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
- switch (tag) {
- case SEC_OID_PKCS7_DATA:
- /* end of recursion - every message has to have a data cinfo */
+ if (NSS_CMSType_IsData(tag)) {
pItem = cinfo->content.data;
- break;
- case SEC_OID_PKCS7_DIGESTED_DATA:
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- case SEC_OID_PKCS7_SIGNED_DATA:
+ } else if (NSS_CMSType_IsWrapper(tag)) {
ccinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo);
- if (ccinfo != NULL)
+ if (ccinfo != NULL) {
pItem = NSS_CMSContentInfo_GetContent(ccinfo);
- break;
- default:
+ }
+ } else {
PORT_Assert(0);
- break;
}
+
return pItem;
}
+
/*
* NSS_CMSContentInfo_GetContentType{Tag,OID} - find out (saving pointer to lookup result
* for future reference) and return the inner content type.
diff --git a/security/nss/lib/smime/cmsdecode.c b/security/nss/lib/smime/cmsdecode.c
index b050b9dc7..e75281d48 100644
--- a/security/nss/lib/smime/cmsdecode.c
+++ b/security/nss/lib/smime/cmsdecode.c
@@ -120,8 +120,7 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth)
#endif
/* so what are we working on right now? */
- switch (p7dcx->type) {
- case SEC_OID_UNKNOWN:
+ if (p7dcx->type == SEC_OID_UNKNOWN) {
/*
* right now, we are still decoding the OUTER (root) cinfo
* As soon as we know the inner content type, set up the info,
@@ -136,8 +135,7 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth)
/* is this ready already ? need to alloc? */
/* XXX yes we need to alloc -- continue here */
}
- break;
- case SEC_OID_PKCS7_DATA:
+ } else if (NSS_CMSType_IsData(p7dcx->type)) {
/* this can only happen if the outermost cinfo has DATA in it */
/* otherwise, we handle this type implicitely in the inner decoders */
@@ -150,86 +148,71 @@ nss_cms_decoder_notify(void *arg, PRBool before, void *dest, int depth)
nss_cms_decoder_update_filter,
p7dcx,
(PRBool)(p7dcx->cb != NULL));
- break;
- }
-
- if (after && dest == &(rootcinfo->content.data)) {
+ } else if (after && dest == &(rootcinfo->content.data)) {
/* remove the filter */
SEC_ASN1DecoderClearFilterProc(p7dcx->dcx);
}
- break;
-
- case SEC_OID_PKCS7_SIGNED_DATA:
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- case SEC_OID_PKCS7_DIGESTED_DATA:
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
-
- if (before && dest == &(rootcinfo->content))
- break; /* we're not there yet */
+ } else if (NSS_CMSType_IsWrapper(p7dcx->type)) {
+ if (!before || dest != &(rootcinfo->content)) {
- if (p7dcx->content.pointer == NULL)
- p7dcx->content = rootcinfo->content;
+ if (p7dcx->content.pointer == NULL)
+ p7dcx->content = rootcinfo->content;
- /* get this data type's inner contentInfo */
- cinfo = NSS_CMSContent_GetContentInfo(p7dcx->content.pointer,
+ /* get this data type's inner contentInfo */
+ cinfo = NSS_CMSContent_GetContentInfo(p7dcx->content.pointer,
p7dcx->type);
- if (before && dest == &(cinfo->contentType)) {
- /* at this point, set up the &%$&$ back pointer */
- /* we cannot do it later, because the content itself is optional! */
- /* please give me C++ */
- switch (p7dcx->type) {
- case SEC_OID_PKCS7_SIGNED_DATA:
- p7dcx->content.signedData->cmsg = p7dcx->cmsg;
- break;
- case SEC_OID_PKCS7_DIGESTED_DATA:
- p7dcx->content.digestedData->cmsg = p7dcx->cmsg;
- break;
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- p7dcx->content.envelopedData->cmsg = p7dcx->cmsg;
- break;
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
- p7dcx->content.encryptedData->cmsg = p7dcx->cmsg;
- break;
- default:
- PORT_Assert(0);
- break;
+ if (before && dest == &(cinfo->contentType)) {
+ /* at this point, set up the &%$&$ back pointer */
+ /* we cannot do it later, because the content itself
+ * is optional! */
+ switch (p7dcx->type) {
+ case SEC_OID_PKCS7_SIGNED_DATA:
+ p7dcx->content.signedData->cmsg = p7dcx->cmsg;
+ break;
+ case SEC_OID_PKCS7_DIGESTED_DATA:
+ p7dcx->content.digestedData->cmsg = p7dcx->cmsg;
+ break;
+ case SEC_OID_PKCS7_ENVELOPED_DATA:
+ p7dcx->content.envelopedData->cmsg = p7dcx->cmsg;
+ break;
+ case SEC_OID_PKCS7_ENCRYPTED_DATA:
+ p7dcx->content.encryptedData->cmsg = p7dcx->cmsg;
+ break;
+ default:
+ p7dcx->content.genericData->cmsg = p7dcx->cmsg;
+ break;
+ }
}
- }
- if (before && dest == &(cinfo->rawContent)) {
- /* we want the ASN.1 decoder to deliver the decoded bytes to us
- ** from now on
- */
- SEC_ASN1DecoderSetFilterProc(p7dcx->dcx,
+ if (before && dest == &(cinfo->rawContent)) {
+ /* we want the ASN.1 decoder to deliver the decoded bytes to us
+ ** from now on
+ */
+ SEC_ASN1DecoderSetFilterProc(p7dcx->dcx,
nss_cms_decoder_update_filter,
p7dcx, (PRBool)(p7dcx->cb != NULL));
- /* we're right in front of the data */
- if (nss_cms_before_data(p7dcx) != SECSuccess) {
- SEC_ASN1DecoderClearFilterProc(p7dcx->dcx);
- /* stop all processing */
- p7dcx->error = PORT_GetError();
+ /* we're right in front of the data */
+ if (nss_cms_before_data(p7dcx) != SECSuccess) {
+ SEC_ASN1DecoderClearFilterProc(p7dcx->dcx);
+ /* stop all processing */
+ p7dcx->error = PORT_GetError();
+ }
}
- }
- if (after && dest == &(cinfo->rawContent)) {
- /* we're right after of the data */
- if (nss_cms_after_data(p7dcx) != SECSuccess)
- p7dcx->error = PORT_GetError();
+ if (after && dest == &(cinfo->rawContent)) {
+ /* we're right after of the data */
+ if (nss_cms_after_data(p7dcx) != SECSuccess)
+ p7dcx->error = PORT_GetError();
- /* we don't need to see the contents anymore */
- SEC_ASN1DecoderClearFilterProc(p7dcx->dcx);
+ /* we don't need to see the contents anymore */
+ SEC_ASN1DecoderClearFilterProc(p7dcx->dcx);
+ }
}
- break;
-
-#if 0 /* NIH */
- case SEC_OID_PKCS7_AUTHENTICATED_DATA:
-#endif
- default:
+ } else {
/* unsupported or unknown message type - fail gracefully */
p7dcx->error = SEC_ERROR_UNSUPPORTED_MESSAGE_TYPE;
- break;
}
}
@@ -269,7 +252,8 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx)
p7dcx->content.encryptedData);
break;
default:
- return SECFailure;
+ rv = NSS_CMSGenericWrapperData_Decode_BeforeData(p7dcx->type,
+ p7dcx->content.genericData);
}
if (rv != SECSuccess)
return SECFailure;
@@ -280,7 +264,7 @@ nss_cms_before_data(NSSCMSDecoderContext *p7dcx)
cinfo = NSS_CMSContent_GetContentInfo(p7dcx->content.pointer, p7dcx->type);
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
- if (childtype == SEC_OID_PKCS7_DATA) {
+ if (NSS_CMSType_IsData(childtype)) {
cinfo->content.pointer = (void *) nss_cms_create_decoder_data(poolp);
if (cinfo->content.pointer == NULL)
/* set memory error */
@@ -395,7 +379,8 @@ nss_cms_after_data(NSSCMSDecoderContext *p7dcx)
/* do nothing */
break;
default:
- rv = SECFailure;
+ rv = NSS_CMSGenericWrapperData_Decode_AfterData(p7dcx->type,
+ p7dcx->content.genericData);
break;
}
done:
@@ -430,7 +415,8 @@ nss_cms_after_end(NSSCMSDecoderContext *p7dcx)
case SEC_OID_PKCS7_DATA:
break;
default:
- rv = SECFailure; /* we should not have got that far... */
+ rv = NSS_CMSGenericWrapperData_Decode_AfterEnd(p7dcx->type,
+ p7dcx->content.genericData);
break;
}
return rv;
@@ -469,7 +455,7 @@ nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx,
goto loser;
}
- if (cinfo->ciphcx != NULL) {
+ if (cinfo->private && cinfo->private->ciphcx != NULL) {
/*
* we are decrypting.
*
@@ -483,7 +469,7 @@ nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx,
unsigned int buflen; /* length available for decrypted data */
/* find out about the length of decrypted data */
- buflen = NSS_CMSCipherContext_DecryptLength(cinfo->ciphcx, len, final);
+ buflen = NSS_CMSCipherContext_DecryptLength(cinfo->private->ciphcx, len, final);
/*
* it might happen that we did not provide enough data for a full
@@ -514,7 +500,7 @@ nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx,
* any output (see above), but we still need to call NSS_CMSCipherContext_Decrypt to
* keep track of incoming data
*/
- rv = NSS_CMSCipherContext_Decrypt(cinfo->ciphcx, buf, &outlen, buflen,
+ rv = NSS_CMSCipherContext_Decrypt(cinfo->private->ciphcx, buf, &outlen, buflen,
data, len, final);
if (rv != SECSuccess) {
p7dcx->error = PORT_GetError();
@@ -534,8 +520,8 @@ nss_cms_decoder_work_data(NSSCMSDecoderContext *p7dcx,
/*
* Update the running digests with plaintext bytes (if we need to).
*/
- if (cinfo->digcx)
- NSS_CMSDigestContext_Update(cinfo->digcx, data, len);
+ if (cinfo->private && cinfo->private->digcx)
+ NSS_CMSDigestContext_Update(cinfo->private->digcx, data, len);
/* at this point, we have the plain decoded & decrypted data
** which is either more encoded DER (which we need to hand to the child
diff --git a/security/nss/lib/smime/cmsdigdata.c b/security/nss/lib/smime/cmsdigdata.c
index e3eb4159d..ba061d57c 100644
--- a/security/nss/lib/smime/cmsdigdata.c
+++ b/security/nss/lib/smime/cmsdigdata.c
@@ -117,7 +117,8 @@ NSS_CMSDigestedData_Encode_BeforeStart(NSSCMSDigestedData *digd)
SECItem *dummy;
version = NSS_CMS_DIGESTED_DATA_VERSION_DATA;
- if (NSS_CMSContentInfo_GetContentTypeTag(&(digd->contentInfo)) != SEC_OID_PKCS7_DATA)
+ if (!NSS_CMSType_IsData(NSS_CMSContentInfo_GetContentTypeTag(
+ &(digd->contentInfo))))
version = NSS_CMS_DIGESTED_DATA_VERSION_ENCAP;
dummy = SEC_ASN1EncodeInteger(digd->cmsg->poolp, &(digd->version), version);
@@ -134,11 +135,16 @@ NSS_CMSDigestedData_Encode_BeforeStart(NSSCMSDigestedData *digd)
SECStatus
NSS_CMSDigestedData_Encode_BeforeData(NSSCMSDigestedData *digd)
{
+ SECStatus rv =NSS_CMSContentInfo_Private_Init(&digd->contentInfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
/* set up the digests */
if (digd->digestAlg.algorithm.len != 0 && digd->digest.len == 0) {
/* if digest is already there, do nothing */
- digd->contentInfo.digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
- if (digd->contentInfo.digcx == NULL)
+ digd->contentInfo.private->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
+ if (digd->contentInfo.private->digcx == NULL)
return SECFailure;
}
return SECSuccess;
@@ -156,12 +162,12 @@ NSS_CMSDigestedData_Encode_AfterData(NSSCMSDigestedData *digd)
{
SECStatus rv = SECSuccess;
/* did we have digest calculation going on? */
- if (digd->contentInfo.digcx) {
- rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx,
+ if (digd->contentInfo.private && digd->contentInfo.private->digcx) {
+ rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.private->digcx,
digd->cmsg->poolp,
&(digd->digest));
/* error has been set by NSS_CMSDigestContext_FinishSingle */
- digd->contentInfo.digcx = NULL;
+ digd->contentInfo.private->digcx = NULL;
}
return rv;
@@ -177,12 +183,19 @@ NSS_CMSDigestedData_Encode_AfterData(NSSCMSDigestedData *digd)
SECStatus
NSS_CMSDigestedData_Decode_BeforeData(NSSCMSDigestedData *digd)
{
+ SECStatus rv;
+
/* is there a digest algorithm yet? */
if (digd->digestAlg.algorithm.len == 0)
return SECFailure;
- digd->contentInfo.digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
- if (digd->contentInfo.digcx == NULL)
+ rv = NSS_CMSContentInfo_Private_Init(&digd->contentInfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
+
+ digd->contentInfo.private->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg));
+ if (digd->contentInfo.private->digcx == NULL)
return SECFailure;
return SECSuccess;
@@ -200,12 +213,12 @@ NSS_CMSDigestedData_Decode_AfterData(NSSCMSDigestedData *digd)
{
SECStatus rv = SECSuccess;
/* did we have digest calculation going on? */
- if (digd->contentInfo.digcx) {
- rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.digcx,
+ if (digd->contentInfo.private && digd->contentInfo.private->digcx) {
+ rv = NSS_CMSDigestContext_FinishSingle(digd->contentInfo.private->digcx,
digd->cmsg->poolp,
&(digd->cdigest));
/* error has been set by NSS_CMSDigestContext_FinishSingle */
- digd->contentInfo.digcx = NULL;
+ digd->contentInfo.private->digcx = NULL;
}
return rv;
diff --git a/security/nss/lib/smime/cmsencdata.c b/security/nss/lib/smime/cmsencdata.c
index a14a3b7c7..caa892e5b 100644
--- a/security/nss/lib/smime/cmsencdata.c
+++ b/security/nss/lib/smime/cmsencdata.c
@@ -181,6 +181,7 @@ NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd)
NSSCMSContentInfo *cinfo;
PK11SymKey *bulkkey;
SECAlgorithmID *algid;
+ SECStatus rv;
cinfo = &(encd->contentInfo);
@@ -192,12 +193,16 @@ NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd)
if (algid == NULL)
return SECFailure;
+ rv = NSS_CMSContentInfo_Private_Init(cinfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
/* this may modify algid (with IVs generated in a token).
* it is therefore essential that algid is a pointer to the "real" contentEncAlg,
* not just to a copy */
- cinfo->ciphcx = NSS_CMSCipherContext_StartEncrypt(encd->cmsg->poolp, bulkkey, algid);
+ cinfo->private->ciphcx = NSS_CMSCipherContext_StartEncrypt(encd->cmsg->poolp, bulkkey, algid);
PK11_FreeSymKey(bulkkey);
- if (cinfo->ciphcx == NULL)
+ if (cinfo->private->ciphcx == NULL)
return SECFailure;
return SECSuccess;
@@ -209,9 +214,9 @@ NSS_CMSEncryptedData_Encode_BeforeData(NSSCMSEncryptedData *encd)
SECStatus
NSS_CMSEncryptedData_Encode_AfterData(NSSCMSEncryptedData *encd)
{
- if (encd->contentInfo.ciphcx) {
- NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
- encd->contentInfo.ciphcx = NULL;
+ if (encd->contentInfo.private && encd->contentInfo.private->ciphcx) {
+ NSS_CMSCipherContext_Destroy(encd->contentInfo.private->ciphcx);
+ encd->contentInfo.private->ciphcx = NULL;
}
/* nothing to do after data */
@@ -244,8 +249,14 @@ NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd)
NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
- cinfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
- if (cinfo->ciphcx == NULL)
+ rv = NSS_CMSContentInfo_Private_Init(cinfo);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = SECFailure;
+
+ cinfo->private->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
+ if (cinfo->private->ciphcx == NULL)
goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */
@@ -264,9 +275,9 @@ loser:
SECStatus
NSS_CMSEncryptedData_Decode_AfterData(NSSCMSEncryptedData *encd)
{
- if (encd->contentInfo.ciphcx) {
- NSS_CMSCipherContext_Destroy(encd->contentInfo.ciphcx);
- encd->contentInfo.ciphcx = NULL;
+ if (encd->contentInfo.private && encd->contentInfo.private->ciphcx) {
+ NSS_CMSCipherContext_Destroy(encd->contentInfo.private->ciphcx);
+ encd->contentInfo.private->ciphcx = NULL;
}
return SECSuccess;
diff --git a/security/nss/lib/smime/cmsencode.c b/security/nss/lib/smime/cmsencode.c
index 419b5d707..221d5c7d3 100644
--- a/security/nss/lib/smime/cmsencode.c
+++ b/security/nss/lib/smime/cmsencode.c
@@ -159,19 +159,7 @@ nss_cms_encoder_notify(void *arg, PRBool before, void *dest, int depth)
* Watch for the content field, at which point we want to instruct
* the ASN.1 encoder to start taking bytes from the buffer.
*/
- switch (p7ecx->type) {
- default:
- case SEC_OID_UNKNOWN:
- /* we're still in the root message */
- if (after && dest == &(rootcinfo->contentType)) {
- /* got the content type OID now - so find out the type tag */
- p7ecx->type = NSS_CMSContentInfo_GetContentTypeTag(rootcinfo);
- /* set up a pointer to our current content */
- p7ecx->content = rootcinfo->content;
- }
- break;
-
- case SEC_OID_PKCS7_DATA:
+ if (NSS_CMSType_IsData(p7ecx->type)) {
if (before && dest == &(rootcinfo->rawContent)) {
/* just set up encoder to grab from user - no encryption or digesting */
if ((item = rootcinfo->content.data) != NULL)
@@ -180,13 +168,7 @@ nss_cms_encoder_notify(void *arg, PRBool before, void *dest, int depth)
SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx);
SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */
}
- break;
-
- case SEC_OID_PKCS7_SIGNED_DATA:
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- case SEC_OID_PKCS7_DIGESTED_DATA:
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
-
+ } else if (NSS_CMSType_IsWrapper(p7ecx->type)) {
/* when we know what the content is, we encode happily until we reach the inner content */
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type);
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
@@ -199,7 +181,7 @@ nss_cms_encoder_notify(void *arg, PRBool before, void *dest, int depth)
p7ecx->error = PORT_GetError();
}
if (before && dest == &(cinfo->rawContent)) {
- if (childtype == SEC_OID_PKCS7_DATA && (item = cinfo->content.data) != NULL)
+ if (NSS_CMSType_IsData(childtype) && (item = cinfo->content.data) != NULL)
/* we have data - feed it in */
(void)nss_cms_encoder_work_data(p7ecx, NULL, item->data, item->len, PR_TRUE, PR_TRUE);
else
@@ -211,7 +193,14 @@ nss_cms_encoder_notify(void *arg, PRBool before, void *dest, int depth)
p7ecx->error = PORT_GetError();
SEC_ASN1EncoderClearNotifyProc(p7ecx->ecx); /* no need to get notified anymore */
}
- break;
+ } else {
+ /* we're still in the root message */
+ if (after && dest == &(rootcinfo->contentType)) {
+ /* got the content type OID now - so find out the type tag */
+ p7ecx->type = NSS_CMSContentInfo_GetContentTypeTag(rootcinfo);
+ /* set up a pointer to our current content */
+ p7ecx->content = rootcinfo->content;
+ }
}
}
@@ -247,7 +236,11 @@ nss_cms_before_data(NSSCMSEncoderContext *p7ecx)
rv = NSS_CMSEncryptedData_Encode_BeforeData(p7ecx->content.encryptedData);
break;
default:
- rv = SECFailure;
+ if (NSS_CMSType_IsWrapper(p7ecx->type)) {
+ rv = NSS_CMSGenericWrapperData_Encode_BeforeData(p7ecx->type, p7ecx->content.genericData);
+ } else {
+ rv = SECFailure;
+ }
}
if (rv != SECSuccess)
return SECFailure;
@@ -258,14 +251,7 @@ nss_cms_before_data(NSSCMSEncoderContext *p7ecx)
cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type);
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
- switch (childtype) {
- case SEC_OID_PKCS7_SIGNED_DATA:
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- case SEC_OID_PKCS7_ENCRYPTED_DATA:
- case SEC_OID_PKCS7_DIGESTED_DATA:
-#if 0
- case SEC_OID_PKCS7_DATA: /* XXX here also??? maybe yes! */
-#endif
+ if (NSS_CMSType_IsWrapper(childtype)) {
/* in these cases, we need to set up a child encoder! */
/* create new encoder context */
childp7ecx = PORT_ZAlloc(sizeof(NSSCMSEncoderContext));
@@ -303,11 +289,8 @@ nss_cms_before_data(NSSCMSEncoderContext *p7ecx)
case SEC_OID_PKCS7_ENCRYPTED_DATA:
rv = NSS_CMSEncryptedData_Encode_BeforeStart(cinfo->content.encryptedData);
break;
- case SEC_OID_PKCS7_DATA:
- rv = SECSuccess;
- break;
default:
- PORT_Assert(0);
+ rv = NSS_CMSGenericWrapperData_Encode_BeforeStart(childp7ecx->type, cinfo->content.genericData);
break;
}
if (rv != SECSuccess)
@@ -327,7 +310,8 @@ nss_cms_before_data(NSSCMSEncoderContext *p7ecx)
* Indicate that we are streaming. We will be streaming until we
* get past the contents bytes.
*/
- SEC_ASN1EncoderSetStreaming(childp7ecx->ecx);
+ if (!cinfo->private || !cinfo->private->dontStream)
+ SEC_ASN1EncoderSetStreaming(childp7ecx->ecx);
/*
* The notify function will watch for the contents field.
@@ -346,15 +330,11 @@ nss_cms_before_data(NSSCMSEncoderContext *p7ecx)
goto loser;
p7ecx->childp7ecx = childp7ecx;
- break;
-
- case SEC_OID_PKCS7_DATA:
+ } else if (NSS_CMSType_IsData(childtype)) {
p7ecx->childp7ecx = NULL;
- break;
- default:
+ } else {
/* we do not know this type */
p7ecx->error = SEC_ERROR_BAD_DER;
- break;
}
return SECSuccess;
@@ -387,11 +367,12 @@ nss_cms_after_data(NSSCMSEncoderContext *p7ecx)
case SEC_OID_PKCS7_ENCRYPTED_DATA:
rv = NSS_CMSEncryptedData_Encode_AfterData(p7ecx->content.encryptedData);
break;
- case SEC_OID_PKCS7_DATA:
- /* do nothing */
- break;
default:
- rv = SECFailure;
+ if (NSS_CMSType_IsWrapper(p7ecx->type)) {
+ rv = NSS_CMSGenericWrapperData_Encode_AfterData(p7ecx->type, p7ecx->content.genericData);
+ } else {
+ rv = SECFailure;
+ }
break;
}
return rv;
@@ -432,23 +413,23 @@ nss_cms_encoder_work_data(NSSCMSEncoderContext *p7ecx, SECItem *dest,
}
/* Update the running digest. */
- if (len && cinfo->digcx != NULL)
- NSS_CMSDigestContext_Update(cinfo->digcx, data, len);
+ if (len && cinfo->private && cinfo->private->digcx != NULL)
+ NSS_CMSDigestContext_Update(cinfo->private->digcx, data, len);
/* Encrypt this chunk. */
- if (cinfo->ciphcx != NULL) {
+ if (cinfo->private && cinfo->private->ciphcx != NULL) {
unsigned int inlen; /* length of data being encrypted */
unsigned int outlen; /* length of encrypted data */
unsigned int buflen; /* length available for encrypted data */
inlen = len;
- buflen = NSS_CMSCipherContext_EncryptLength(cinfo->ciphcx, inlen, final);
+ buflen = NSS_CMSCipherContext_EncryptLength(cinfo->private->ciphcx, inlen, final);
if (buflen == 0) {
/*
* No output is expected, but the input data may be buffered
* so we still have to call Encrypt.
*/
- rv = NSS_CMSCipherContext_Encrypt(cinfo->ciphcx, NULL, NULL, 0,
+ rv = NSS_CMSCipherContext_Encrypt(cinfo->private->ciphcx, NULL, NULL, 0,
data, inlen, final);
if (final) {
len = 0;
@@ -465,7 +446,7 @@ nss_cms_encoder_work_data(NSSCMSEncoderContext *p7ecx, SECItem *dest,
if (buf == NULL) {
rv = SECFailure;
} else {
- rv = NSS_CMSCipherContext_Encrypt(cinfo->ciphcx, buf, &outlen, buflen,
+ rv = NSS_CMSCipherContext_Encrypt(cinfo->private->ciphcx, buf, &outlen, buflen,
data, inlen, final);
data = buf;
len = outlen;
@@ -486,7 +467,7 @@ nss_cms_encoder_work_data(NSSCMSEncoderContext *p7ecx, SECItem *dest,
done:
- if (cinfo->ciphcx != NULL) {
+ if (cinfo->private && cinfo->private->ciphcx != NULL) {
if (dest != NULL) {
dest->data = buf;
dest->len = len;
@@ -532,6 +513,7 @@ NSS_CMSEncoder_Start(NSSCMSMessage *cmsg,
NSSCMSEncoderContext *p7ecx;
SECStatus rv;
NSSCMSContentInfo *cinfo;
+ SECOidTag tag;
NSS_CMSMessage_SetEncodingParams(cmsg, pwfn, pwfn_arg, decrypt_key_cb, decrypt_key_cb_arg,
detached_digestalgs, detached_digests);
@@ -551,7 +533,8 @@ NSS_CMSEncoder_Start(NSSCMSMessage *cmsg,
cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
- switch (NSS_CMSContentInfo_GetContentTypeTag(cinfo)) {
+ tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
+ switch (tag) {
case SEC_OID_PKCS7_SIGNED_DATA:
rv = NSS_CMSSignedData_Encode_BeforeStart(cinfo->content.signedData);
break;
@@ -565,7 +548,12 @@ NSS_CMSEncoder_Start(NSSCMSMessage *cmsg,
rv = NSS_CMSEncryptedData_Encode_BeforeStart(cinfo->content.encryptedData);
break;
default:
- rv = SECFailure;
+ if (NSS_CMSType_IsWrapper(tag)) {
+ rv = NSS_CMSGenericWrapperData_Encode_AfterData(tag,
+ p7ecx->content.genericData);
+ } else {
+ rv = SECFailure;
+ }
break;
}
if (rv != SECSuccess) {
@@ -587,7 +575,8 @@ NSS_CMSEncoder_Start(NSSCMSMessage *cmsg,
* Indicate that we are streaming. We will be streaming until we
* get past the contents bytes.
*/
- SEC_ASN1EncoderSetStreaming(p7ecx->ecx);
+ if (!cinfo->private || !cinfo->private->dontStream)
+ SEC_ASN1EncoderSetStreaming(p7ecx->ecx);
/*
* The notify function will watch for the contents field.
@@ -640,7 +629,7 @@ NSS_CMSEncoder_Update(NSSCMSEncoderContext *p7ecx, const char *data, unsigned lo
}
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
- if (childtype != SEC_OID_PKCS7_DATA)
+ if (!NSS_CMSType_IsData(childtype))
return SECFailure;
/* and we must not have preset data */
if (cinfo->content.data != NULL)
@@ -746,7 +735,7 @@ NSS_CMSEncoder_Finish(NSSCMSEncoderContext *p7ecx)
goto loser;
}
childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
- if (childtype == SEC_OID_PKCS7_DATA && cinfo->content.data == NULL) {
+ if (NSS_CMSType_IsData(childtype) && cinfo->content.data == NULL) {
SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx);
/* now that TakeFromBuf is off, this will kick this encoder to finish encoding */
rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0);
diff --git a/security/nss/lib/smime/cmsenvdata.c b/security/nss/lib/smime/cmsenvdata.c
index c575a995e..73cafabcb 100644
--- a/security/nss/lib/smime/cmsenvdata.c
+++ b/security/nss/lib/smime/cmsenvdata.c
@@ -270,6 +270,7 @@ NSS_CMSEnvelopedData_Encode_BeforeData(NSSCMSEnvelopedData *envd)
NSSCMSContentInfo *cinfo;
PK11SymKey *bulkkey;
SECAlgorithmID *algid;
+ SECStatus rv;
cinfo = &(envd->contentInfo);
@@ -281,12 +282,16 @@ NSS_CMSEnvelopedData_Encode_BeforeData(NSSCMSEnvelopedData *envd)
if (algid == NULL)
return SECFailure;
+ rv = NSS_CMSContentInfo_Private_Init(cinfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
/* this may modify algid (with IVs generated in a token).
* it is essential that algid is a pointer to the contentEncAlg data, not a
* pointer to a copy! */
- cinfo->ciphcx = NSS_CMSCipherContext_StartEncrypt(envd->cmsg->poolp, bulkkey, algid);
+ cinfo->private->ciphcx = NSS_CMSCipherContext_StartEncrypt(envd->cmsg->poolp, bulkkey, algid);
PK11_FreeSymKey(bulkkey);
- if (cinfo->ciphcx == NULL)
+ if (cinfo->private->ciphcx == NULL)
return SECFailure;
return SECSuccess;
@@ -298,9 +303,9 @@ NSS_CMSEnvelopedData_Encode_BeforeData(NSSCMSEnvelopedData *envd)
SECStatus
NSS_CMSEnvelopedData_Encode_AfterData(NSSCMSEnvelopedData *envd)
{
- if (envd->contentInfo.ciphcx) {
- NSS_CMSCipherContext_Destroy(envd->contentInfo.ciphcx);
- envd->contentInfo.ciphcx = NULL;
+ if (envd->contentInfo.private && envd->contentInfo.private->ciphcx) {
+ NSS_CMSCipherContext_Destroy(envd->contentInfo.private->ciphcx);
+ envd->contentInfo.private->ciphcx = NULL;
}
/* nothing else to do after data */
@@ -380,8 +385,13 @@ NSS_CMSEnvelopedData_Decode_BeforeData(NSSCMSEnvelopedData *envd)
bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo);
- cinfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
- if (cinfo->ciphcx == NULL)
+ rv = NSS_CMSContentInfo_Private_Init(cinfo);
+ if (rv != SECSuccess) {
+ goto loser;
+ }
+ rv = SECFailure;
+ cinfo->private->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
+ if (cinfo->private->ciphcx == NULL)
goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */
@@ -401,9 +411,9 @@ loser:
SECStatus
NSS_CMSEnvelopedData_Decode_AfterData(NSSCMSEnvelopedData *envd)
{
- if (envd && envd->contentInfo.ciphcx) {
- NSS_CMSCipherContext_Destroy(envd->contentInfo.ciphcx);
- envd->contentInfo.ciphcx = NULL;
+ if (envd && envd->contentInfo.private && envd->contentInfo.private->ciphcx) {
+ NSS_CMSCipherContext_Destroy(envd->contentInfo.private->ciphcx);
+ envd->contentInfo.private->ciphcx = NULL;
}
return SECSuccess;
diff --git a/security/nss/lib/smime/cmslocal.h b/security/nss/lib/smime/cmslocal.h
index 666eeb033..8aafec8ff 100644
--- a/security/nss/lib/smime/cmslocal.h
+++ b/security/nss/lib/smime/cmslocal.h
@@ -54,9 +54,25 @@
extern const SEC_ASN1Template NSSCMSContentInfoTemplate[];
+struct NSSCMSContentInfoPrivateStr {
+ NSSCMSCipherContext *ciphcx;
+ NSSCMSDigestContext *digcx;
+ PRBool dontStream;
+};
+
/************************************************************************/
SEC_BEGIN_PROTOS
+/*
+ * private content Info stuff
+ */
+
+/* initialize the private content info field. If this returns
+ * SECSuccess, the cinfo->private field is safe to dereference.
+ */
+SECStatus NSS_CMSContentInfo_Private_Init(NSSCMSContentInfo *cinfo);
+
+
/***********************************************************************
* cmscipher.c - en/decryption routines
***********************************************************************/
@@ -340,7 +356,34 @@ NSS_CMSAttributeArray_SetAttr(PLArenaPool *poolp, NSSCMSAttribute ***attrs, SECO
extern SECStatus
NSS_CMSSignedData_AddTempCertificate(NSSCMSSignedData *sigd, CERTCertificate *cert);
+
/************************************************************************/
+
+/*
+ * local functions to handle user defined S/MIME content types
+ */
+
+
+PRBool NSS_CMSType_IsWrapper(SECOidTag type);
+PRBool NSS_CMSType_IsData(SECOidTag type);
+size_t NSS_CMSType_GetContentSize(SECOidTag type);
+const SEC_ASN1Template * NSS_CMSType_GetTemplate(SECOidTag type);
+
+void NSS_CMSGenericWrapperData_Destroy(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Decode_BeforeData(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Decode_AfterData(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Decode_AfterEnd(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Encode_BeforeStart(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Encode_BeforeData(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+SECStatus NSS_CMSGenericWrapperData_Encode_AfterData(SECOidTag type,
+ NSSCMSGenericWrapperData *gd);
+
SEC_END_PROTOS
#endif /* _CMSLOCAL_H_ */
diff --git a/security/nss/lib/smime/cmsmessage.c b/security/nss/lib/smime/cmsmessage.c
index 1b3d69c74..787a287bf 100644
--- a/security/nss/lib/smime/cmsmessage.c
+++ b/security/nss/lib/smime/cmsmessage.c
@@ -81,6 +81,7 @@ NSS_CMSMessage_Create(PLArenaPool *poolp)
PORT_FreeArena(poolp, PR_FALSE);
return NULL;
}
+ NSS_CMSContentInfo_Private_Init(&(cmsg->contentInfo));
cmsg->poolp = poolp;
cmsg->poolp_is_ours = poolp_is_ours;
@@ -234,11 +235,12 @@ NSS_CMSMessage_ContainsCertsOrCrls(NSSCMSMessage *cmsg)
/* descend into CMS message */
for (cinfo = &(cmsg->contentInfo); cinfo != NULL; cinfo = NSS_CMSContentInfo_GetChildContentInfo(cinfo)) {
- if (NSS_CMSContentInfo_GetContentTypeTag(cinfo) != SEC_OID_PKCS7_SIGNED_DATA)
+ if (!NSS_CMSType_IsData(NSS_CMSContentInfo_GetContentTypeTag(cinfo)))
continue; /* next level */
if (NSS_CMSSignedData_ContainsCertsOrCrls(cinfo->content.signedData))
return PR_TRUE;
+ /* callback here for generic wrappers? */
}
return PR_FALSE;
}
@@ -259,6 +261,7 @@ NSS_CMSMessage_IsEncrypted(NSSCMSMessage *cmsg)
case SEC_OID_PKCS7_ENCRYPTED_DATA:
return PR_TRUE;
default:
+ /* callback here for generic wrappers? */
break;
}
}
@@ -289,6 +292,7 @@ NSS_CMSMessage_IsSigned(NSSCMSMessage *cmsg)
return PR_TRUE;
break;
default:
+ /* callback here for generic wrappers? */
break;
}
}
diff --git a/security/nss/lib/smime/cmssigdata.c b/security/nss/lib/smime/cmssigdata.c
index 0ba771d65..f396ec77f 100644
--- a/security/nss/lib/smime/cmssigdata.c
+++ b/security/nss/lib/smime/cmssigdata.c
@@ -217,17 +217,22 @@ loser:
SECStatus
NSS_CMSSignedData_Encode_BeforeData(NSSCMSSignedData *sigd)
{
+ SECStatus rv;
if (!sigd) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
/* set up the digests */
if (sigd->digests && sigd->digests[0]) {
- sigd->contentInfo.digcx = NULL; /* don't attempt to make new ones. */
+ sigd->contentInfo.private->digcx = NULL; /* don't attempt to make new ones. */
} else if (sigd->digestAlgorithms != NULL) {
- sigd->contentInfo.digcx =
+ sigd->contentInfo.private->digcx =
NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
- if (sigd->contentInfo.digcx == NULL)
+ if (sigd->contentInfo.private->digcx == NULL)
return SECFailure;
}
return SECSuccess;
@@ -267,11 +272,11 @@ NSS_CMSSignedData_Encode_AfterData(NSSCMSSignedData *sigd)
cinfo = &(sigd->contentInfo);
/* did we have digest calculation going on? */
- if (cinfo->digcx) {
- rv = NSS_CMSDigestContext_FinishMultiple(cinfo->digcx, poolp,
+ if (cinfo->private && cinfo->private->digcx) {
+ rv = NSS_CMSDigestContext_FinishMultiple(cinfo->private->digcx, poolp,
&(sigd->digests));
/* error has been set by NSS_CMSDigestContext_FinishMultiple */
- cinfo->digcx = NULL;
+ cinfo->private->digcx = NULL;
if (rv != SECSuccess)
goto loser;
}
@@ -392,15 +397,20 @@ loser:
SECStatus
NSS_CMSSignedData_Decode_BeforeData(NSSCMSSignedData *sigd)
{
+ SECStatus rv;
if (!sigd) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
+ rv = NSS_CMSContentInfo_Private_Init(&sigd->contentInfo);
+ if (rv != SECSuccess) {
+ return SECFailure;
+ }
/* set up the digests */
if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) {
/* if digests are already there, do nothing */
- sigd->contentInfo.digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
- if (sigd->contentInfo.digcx == NULL)
+ sigd->contentInfo.private->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms);
+ if (sigd->contentInfo.private->digcx == NULL)
return SECFailure;
}
return SECSuccess;
@@ -421,11 +431,11 @@ NSS_CMSSignedData_Decode_AfterData(NSSCMSSignedData *sigd)
}
/* did we have digest calculation going on? */
- if (sigd->contentInfo.digcx) {
- rv = NSS_CMSDigestContext_FinishMultiple(sigd->contentInfo.digcx,
+ if (sigd->contentInfo.private && sigd->contentInfo.private->digcx) {
+ rv = NSS_CMSDigestContext_FinishMultiple(sigd->contentInfo.private->digcx,
sigd->cmsg->poolp, &(sigd->digests));
/* error set by NSS_CMSDigestContext_FinishMultiple */
- sigd->contentInfo.digcx = NULL;
+ sigd->contentInfo.private->digcx = NULL;
}
return rv;
}
diff --git a/security/nss/lib/smime/cmst.h b/security/nss/lib/smime/cmst.h
index 82f24da14..f894dd122 100644
--- a/security/nss/lib/smime/cmst.h
+++ b/security/nss/lib/smime/cmst.h
@@ -98,6 +98,8 @@ typedef struct NSSCMSRecipientInfoStr NSSCMSRecipientInfo;
typedef struct NSSCMSDigestedDataStr NSSCMSDigestedData;
typedef struct NSSCMSEncryptedDataStr NSSCMSEncryptedData;
+typedef struct NSSCMSGenericWrapperDataStr NSSCMSGenericWrapperData;
+
typedef struct NSSCMSSMIMEKEAParametersStr NSSCMSSMIMEKEAParameters;
typedef struct NSSCMSAttributeStr NSSCMSAttribute;
@@ -108,6 +110,13 @@ typedef struct NSSCMSEncoderContextStr NSSCMSEncoderContext;
typedef struct NSSCMSCipherContextStr NSSCMSCipherContext;
typedef struct NSSCMSDigestContextStr NSSCMSDigestContext;
+typedef struct NSSCMSContentInfoPrivateStr NSSCMSContentInfoPrivate;
+
+typedef SECStatus (*NSSCMSGenericWrapperDataCallback)
+ (NSSCMSGenericWrapperData *);
+typedef void (*NSSCMSGenericWrapperDataDestroy)
+ (NSSCMSGenericWrapperData *);
+
/*
* Type of function passed to NSSCMSDecode or NSSCMSDecoderStart.
* If specified, this is where the content bytes (only) will be "sent"
@@ -142,6 +151,7 @@ union NSSCMSContentUnion {
NSSCMSEncryptedData * encryptedData;
NSSCMSEnvelopedData * envelopedData;
NSSCMSSignedData * signedData;
+ NSSCMSGenericWrapperData * genericData;
/* or anonymous pointer to something */
void * pointer;
};
@@ -164,8 +174,8 @@ struct NSSCMSContentInfoStr {
* (only used by creation code) */
SECOidTag contentEncAlgTag; /* oid tag of encryption algorithm
* (only used by creation code) */
- NSSCMSCipherContext *ciphcx; /* context for en/decryption going on */
- NSSCMSDigestContext *digcx; /* context for digesting going on */
+ NSSCMSContentInfoPrivate *private; /* place for NSS private info */
+ void *reserved; /* keep binary compatibility */
};
/* =============================================================================
@@ -186,6 +196,18 @@ struct NSSCMSMessageStr {
void * decrypt_key_cb_arg;
};
+/* ============================================================================
+ * GENERIC WRAPPER
+ *
+ * used for user defined types.
+ */
+struct NSSCMSGenericWrapperDataStr {
+ NSSCMSContentInfo contentInfo;
+ /* ---- local; not part of encoding ------ */
+ NSSCMSMessage * cmsg;
+ /* wrapperspecific data starts here */
+};
+
/* =============================================================================
* SIGNEDDATA
*/
diff --git a/security/nss/lib/smime/cmsutil.c b/security/nss/lib/smime/cmsutil.c
index ddd87870a..b4839d3bf 100644
--- a/security/nss/lib/smime/cmsutil.c
+++ b/security/nss/lib/smime/cmsutil.c
@@ -243,8 +243,7 @@ NSS_CMSUtil_GetTemplateByTypeTag(SECOidTag type)
template = NSSCMSDigestedDataTemplate;
break;
default:
- case SEC_OID_PKCS7_DATA:
- template = NULL;
+ template = NSS_CMSType_GetTemplate(type);
break;
}
return template;
@@ -269,8 +268,7 @@ NSS_CMSUtil_GetSizeByTypeTag(SECOidTag type)
size = sizeof(NSSCMSDigestedData);
break;
default:
- case SEC_OID_PKCS7_DATA:
- size = 0;
+ size = NSS_CMSType_GetContentSize(type);
break;
}
return size;
@@ -300,6 +298,9 @@ NSS_CMSContent_GetContentInfo(void *msg, SECOidTag type)
break;
default:
cinfo = NULL;
+ if (NSS_CMSType_IsWrapper(type)) {
+ cinfo = &(c.genericData->contentInfo);
+ }
}
return cinfo;
}
diff --git a/security/nss/lib/smime/manifest.mn b/security/nss/lib/smime/manifest.mn
index a72b41377..1f5421f35 100644
--- a/security/nss/lib/smime/manifest.mn
+++ b/security/nss/lib/smime/manifest.mn
@@ -69,6 +69,7 @@ CSRCS = \
cmsreclist.c \
cmssigdata.c \
cmssiginfo.c \
+ cmsudf.c \
cmsutil.c \
smimemessage.c \
smimeutil.c \
diff --git a/security/nss/lib/smime/smime.def b/security/nss/lib/smime/smime.def
index 39ccc45bb..bddf03f4e 100644
--- a/security/nss/lib/smime/smime.def
+++ b/security/nss/lib/smime/smime.def
@@ -273,3 +273,11 @@ SEC_PKCS12AddCertOrChainAndKey;
;+ local:
;+ *;
;+};
+;+NSS_3.12.10 { # NSS 3.12.10 release
+;+ global:
+NSS_CMSType_RegisterContentType;
+NSS_CMSContentInfo_SetDontStream;
+NSS_SMIMEUtil_CreateMSSMIMEEncKeyPrefs;
+;+ local:
+;+ *;
+;+};