Index: ./mozilla/security/nss/lib/smime/cms.h =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cms.h,v retrieving revision 1.23 retrieving revision 1.25 diff -u -p -r1.23 -r1.25 --- ./mozilla/security/nss/lib/smime/cms.h 25 Apr 2010 23:37:38 -0000 1.23 +++ ./mozilla/security/nss/lib/smime/cms.h 31 Jan 2011 23:56:29 -0000 1.25 @@ -37,7 +37,7 @@ /* * Interfaces of the CMS implementation. * - * $Id: cms.h,v 1.23 2010/04/25 23:37:38 nelson%bolyard.com Exp $ + * $Id: cms.h,v 1.25 2011/01/31 23:56:29 rrelyea%redhat.com Exp $ */ #ifndef _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, SE 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 Index: ./mozilla/security/nss/lib/smime/cmsasn1.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsasn1.c,v retrieving revision 1.7 retrieving revision 1.9 diff -u -p -r1.7 -r1.9 --- ./mozilla/security/nss/lib/smime/cmsasn1.c 6 Jun 2010 22:36:35 -0000 1.7 +++ ./mozilla/security/nss/lib/smime/cmsasn1.c 31 Jan 2011 23:56:30 -0000 1.9 @@ -37,7 +37,7 @@ /* * CMS ASN.1 templates * - * $Id: cmsasn1.c,v 1.7 2010/06/06 22:36:35 nelson%bolyard.com Exp $ + * $Id: cmsasn1.c,v 1.9 2011/01/31 23:56:30 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -479,6 +479,20 @@ const SEC_ASN1Template NSS_PointerToCMSE { SEC_ASN1_POINTER, 0, NSSCMSEncryptedDataTemplate } }; +const SEC_ASN1Template NSSCMSGenericWrapperDataTemplate[] = { + { SEC_ASN1_INLINE, + offsetof(NSSCMSGenericWrapperData,contentInfo), + NSSCMSEncapsulatedContentInfoTemplate }, +}; + +SEC_ASN1_CHOOSER_IMPLEMENT(NSSCMSGenericWrapperDataTemplate); + +const SEC_ASN1Template NSS_PointerToCMSGenericWrapperDataTemplate[] = { + { SEC_ASN1_POINTER, 0, NSSCMSGenericWrapperDataTemplate } +}; + +SEC_ASN1_CHOOSER_IMPLEMENT(NSS_PointerToCMSGenericWrapperDataTemplate); + /* ----------------------------------------------------------------------------- * FORTEZZA KEA */ @@ -547,15 +561,17 @@ nss_cms_choose_content_template(void *sr { 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)) { + type = NSS_CMSContentInfo_GetContentTypeTag(cinfo); + switch (type) { default: - theTemplate = SEC_ASN1_GET(SEC_PointerToAnyTemplate); + theTemplate = NSS_CMSType_GetTemplate(type); break; case SEC_OID_PKCS7_DATA: theTemplate = SEC_ASN1_GET(SEC_PointerToOctetStringTemplate); Index: ./mozilla/security/nss/lib/smime/cmscinfo.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmscinfo.c,v retrieving revision 1.7 retrieving revision 1.9 diff -u -p -r1.7 -r1.9 --- ./mozilla/security/nss/lib/smime/cmscinfo.c 25 Apr 2004 15:03:16 -0000 1.7 +++ ./mozilla/security/nss/lib/smime/cmscinfo.c 31 Jan 2011 23:56:30 -0000 1.9 @@ -37,7 +37,7 @@ /* * CMS contentInfo methods. * - * $Id: cmscinfo.c,v 1.7 2004/04/25 15:03:16 gerv%gerv.net Exp $ + * $Id: cmscinfo.c,v 1.9 2011/01/31 23:56:30 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -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(NSSCMSContent 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,56 @@ NSS_CMSContentInfo_Destroy(NSSCMSContent 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); + if (cinfo->content.signedData != NULL) { + ccinfo = &(cinfo->content.signedData->contentInfo); + } break; case SEC_OID_PKCS7_ENVELOPED_DATA: - ptr = (void *)cinfo->content.envelopedData; - ccinfo = &(cinfo->content.envelopedData->contentInfo); + if (cinfo->content.envelopedData != NULL) { + ccinfo = &(cinfo->content.envelopedData->contentInfo); + } break; case SEC_OID_PKCS7_DIGESTED_DATA: - ptr = (void *)cinfo->content.digestedData; - ccinfo = &(cinfo->content.digestedData->contentInfo); + if (cinfo->content.digestedData != NULL) { + ccinfo = &(cinfo->content.digestedData->contentInfo); + } break; case SEC_OID_PKCS7_ENCRYPTED_DATA: - ptr = (void *)cinfo->content.encryptedData; - ccinfo = &(cinfo->content.encryptedData->contentInfo); + if (cinfo->content.encryptedData != NULL) { + ccinfo = &(cinfo->content.encryptedData->contentInfo); + } break; case SEC_OID_PKCS7_DATA: default: + if (NSS_CMSType_IsWrapper(tag)) { + if (cinfo->content.genericData != NULL) { + 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 +192,9 @@ NSS_CMSContentInfo_SetContent(NSSCMSMess 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 +221,10 @@ NSS_CMSContentInfo_SetContent_Data(NSSCM { 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 +252,7 @@ NSS_CMSContentInfo_SetContent_EncryptedD return NSS_CMSContentInfo_SetContent(cmsg, cinfo, SEC_OID_PKCS7_ENCRYPTED_DATA, (void *)encd); } + /* * NSS_CMSContentInfo_GetContent - get pointer to inner content * @@ -223,7 +272,7 @@ NSS_CMSContentInfo_GetContent(NSSCMSCont case SEC_OID_PKCS7_ENCRYPTED_DATA: return cinfo->content.pointer; default: - return NULL; + return NSS_CMSType_IsWrapper(tag) ? cinfo->content.pointer : (NSS_CMSType_IsData(tag) ? cinfo->rawContent : NULL); } } @@ -232,6 +281,7 @@ NSS_CMSContentInfo_GetContent(NSSCMSCont * * this is typically only called by NSS_CMSMessage_GetContent() */ + SECItem * NSS_CMSContentInfo_GetInnerContent(NSSCMSContentInfo *cinfo) { @@ -240,26 +290,21 @@ NSS_CMSContentInfo_GetInnerContent(NSSCM 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. Index: ./mozilla/security/nss/lib/smime/cmsdecode.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsdecode.c,v retrieving revision 1.9.66.1 retrieving revision 1.11 diff -u -p -r1.9.66.1 -r1.11 --- ./mozilla/security/nss/lib/smime/cmsdecode.c 23 Dec 2010 18:03:41 -0000 1.9.66.1 +++ ./mozilla/security/nss/lib/smime/cmsdecode.c 28 Jan 2011 23:03:59 -0000 1.11 @@ -37,7 +37,7 @@ /* * CMS decoding. * - * $Id: cmsdecode.c,v 1.9.66.1 2010/12/23 18:03:41 kaie%kuix.de Exp $ + * $Id: cmsdecode.c,v 1.11 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -120,8 +120,7 @@ nss_cms_decoder_notify(void *arg, PRBool #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 /* 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 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->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 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 /* 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 * 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(NSSCMSDecoderC 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(NSSCMSDecoderC 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(NSSCMSDecoderC * 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(NSSCMSDecoderC /* * 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 Index: ./mozilla/security/nss/lib/smime/cmsdigdata.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsdigdata.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- ./mozilla/security/nss/lib/smime/cmsdigdata.c 25 Apr 2004 15:03:16 -0000 1.5 +++ ./mozilla/security/nss/lib/smime/cmsdigdata.c 28 Jan 2011 23:03:59 -0000 1.6 @@ -37,7 +37,7 @@ /* * CMS digestedData methods. * - * $Id: cmsdigdata.c,v 1.5 2004/04/25 15:03:16 gerv%gerv.net Exp $ + * $Id: cmsdigdata.c,v 1.6 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -117,7 +117,8 @@ NSS_CMSDigestedData_Encode_BeforeStart(N 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(N 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(NSS { 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(NSS 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(NSS { 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; Index: ./mozilla/security/nss/lib/smime/cmsencdata.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsencdata.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -p -r1.11 -r1.12 --- ./mozilla/security/nss/lib/smime/cmsencdata.c 3 Feb 2008 06:08:49 -0000 1.11 +++ ./mozilla/security/nss/lib/smime/cmsencdata.c 28 Jan 2011 23:03:59 -0000 1.12 @@ -37,7 +37,7 @@ /* * CMS encryptedData methods. * - * $Id: cmsencdata.c,v 1.11 2008/02/03 06:08:49 nelson%bolyard.com Exp $ + * $Id: cmsencdata.c,v 1.12 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -181,6 +181,7 @@ NSS_CMSEncryptedData_Encode_BeforeData(N NSSCMSContentInfo *cinfo; PK11SymKey *bulkkey; SECAlgorithmID *algid; + SECStatus rv; cinfo = &(encd->contentInfo); @@ -192,12 +193,16 @@ NSS_CMSEncryptedData_Encode_BeforeData(N 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(N 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(N 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; Index: ./mozilla/security/nss/lib/smime/cmsencode.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsencode.c,v retrieving revision 1.6.66.1 retrieving revision 1.10 diff -u -p -r1.6.66.1 -r1.10 --- ./mozilla/security/nss/lib/smime/cmsencode.c 23 Dec 2010 18:03:41 -0000 1.6.66.1 +++ ./mozilla/security/nss/lib/smime/cmsencode.c 1 Feb 2011 23:24:56 -0000 1.10 @@ -37,7 +37,7 @@ /* * CMS encoding. * - * $Id: cmsencode.c,v 1.6.66.1 2010/12/23 18:03:41 kaie%kuix.de Exp $ + * $Id: cmsencode.c,v 1.10 2011/02/01 23:24:56 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -92,8 +92,23 @@ nss_cms_encoder_out(void *arg, const cha #ifdef CMSDEBUG int i; + const char *data_name = "unknown"; - fprintf(stderr, "kind = %d, depth = %d, len = %d\n", data_kind, depth, len); + switch (data_kind) { + case SEC_ASN1_Identifier: + data_name = "identifier"; + break; + case SEC_ASN1_Length: + data_name = "length"; + break; + case SEC_ASN1_Contents: + data_name = "contents"; + break; + case SEC_ASN1_EndOfContents: + data_name = "end-of-contents"; + break; + } + fprintf(stderr, "kind = %s, depth = %d, len = %d\n", data_name, depth, len); for (i=0; i < len; i++) { fprintf(stderr, " %02x%s", (unsigned int)buf[i] & 0xff, ((i % 16) == 15) ? "\n" : ""); } @@ -159,34 +174,17 @@ nss_cms_encoder_notify(void *arg, PRBool * 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 (before && dest == &(rootcinfo->rawContent)) { + if (NSS_CMSType_IsData(p7ecx->type)) { + cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); + if (before && dest == &(cinfo->rawContent)) { /* just set up encoder to grab from user - no encryption or digesting */ - if ((item = rootcinfo->content.data) != NULL) + if ((item = cinfo->content.data) != NULL) (void)nss_cms_encoder_work_data(p7ecx, NULL, item->data, item->len, PR_TRUE, PR_TRUE); else 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,19 +197,32 @@ nss_cms_encoder_notify(void *arg, PRBool p7ecx->error = PORT_GetError(); } if (before && dest == &(cinfo->rawContent)) { - if (childtype == SEC_OID_PKCS7_DATA && (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 - /* else try to get it from user */ + if (p7ecx->childp7ecx == NULL) { + if ((NSS_CMSType_IsData(childtype) && (item = cinfo->content.data) != NULL)) { + /* we are the innermost non-data and we have data - feed it in */ + (void)nss_cms_encoder_work_data(p7ecx, NULL, item->data, item->len, PR_TRUE, PR_TRUE); + } else { + /* else we'll have to get data from user */ + SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx); + } + } else { + /* if we have a nested encoder, wait for its data */ SEC_ASN1EncoderSetTakeFromBuf(p7ecx->ecx); + } } if (after && dest == &(cinfo->rawContent)) { if (nss_cms_after_data(p7ecx) != SECSuccess) 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 +258,11 @@ nss_cms_before_data(NSSCMSEncoderContext 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 +273,7 @@ nss_cms_before_data(NSSCMSEncoderContext 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)); @@ -284,6 +292,8 @@ nss_cms_before_data(NSSCMSEncoderContext childp7ecx->output.destpoolp = NULL; childp7ecx->output.dest = NULL; childp7ecx->cmsg = p7ecx->cmsg; + childp7ecx->ecxupdated = PR_FALSE; + childp7ecx->childp7ecx = NULL; template = NSS_CMSUtil_GetTemplateByTypeTag(childtype); if (template == NULL) @@ -303,11 +313,8 @@ nss_cms_before_data(NSSCMSEncoderContext 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) @@ -321,17 +328,17 @@ nss_cms_before_data(NSSCMSEncoderContext if (childp7ecx->ecx == NULL) goto loser; - childp7ecx->ecxupdated = PR_FALSE; - /* * 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. */ + p7ecx->childp7ecx = childp7ecx; SEC_ASN1EncoderSetNotifyProc(childp7ecx->ecx, nss_cms_encoder_notify, childp7ecx); /* please note that we are NOT calling SEC_ASN1EncoderUpdate here to kick off the */ @@ -339,22 +346,11 @@ nss_cms_before_data(NSSCMSEncoderContext /* otherwise we'd be encoding data from a call of the notify function of the */ /* parent encoder (which would not work) */ - /* this will kick off the encoding process & encode everything up to the content bytes, - * at which point the notify function sets streaming mode (and possibly creates - * another child encoder). */ - if (SEC_ASN1EncoderUpdate(childp7ecx->ecx, NULL, 0) != SECSuccess) - 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; @@ -364,6 +360,7 @@ loser: if (childp7ecx->ecx) SEC_ASN1EncoderFinish(childp7ecx->ecx); PORT_Free(childp7ecx); + p7ecx->childp7ecx = NULL; } return SECFailure; } @@ -387,11 +384,12 @@ nss_cms_after_data(NSSCMSEncoderContext 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 +430,23 @@ nss_cms_encoder_work_data(NSSCMSEncoderC } /* 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 +463,7 @@ nss_cms_encoder_work_data(NSSCMSEncoderC 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; @@ -481,12 +479,12 @@ nss_cms_encoder_work_data(NSSCMSEncoderC * (which will encode it, then hand it back to the user or the parent encoder) * We don't encode the data if we're innermost and we're told not to include the data */ - if (p7ecx->ecx != NULL && len && (!innermost || cinfo->rawContent != NULL)) + if (p7ecx->ecx != NULL && len && (!innermost || cinfo->rawContent != cinfo->content.pointer)) rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, (const char *)data, len); done: - if (cinfo->ciphcx != NULL) { + if (cinfo->private && cinfo->private->ciphcx != NULL) { if (dest != NULL) { dest->data = buf; dest->len = len; @@ -532,6 +530,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 +550,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 +565,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_BeforeStart(tag, + p7ecx->content.genericData); + } else { + rv = SECFailure; + } break; } if (rv != SECSuccess) { @@ -587,7 +592,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. @@ -597,6 +603,7 @@ NSS_CMSEncoder_Start(NSSCMSMessage *cmsg /* this will kick off the encoding process & encode everything up to the content bytes, * at which point the notify function sets streaming mode (and possibly creates * a child encoder). */ + p7ecx->ecxupdated = PR_TRUE; if (SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0) != SECSuccess) { PORT_Free (p7ecx); return NULL; @@ -627,6 +634,13 @@ NSS_CMSEncoder_Update(NSSCMSEncoderConte /* hand data to the innermost decoder */ if (p7ecx->childp7ecx) { + /* tell the child to start encoding, up to its first data byte, if it + * hasn't started yet */ + if (!p7ecx->childp7ecx->ecxupdated) { + p7ecx->childp7ecx->ecxupdated = PR_TRUE; + if (SEC_ASN1EncoderUpdate(p7ecx->childp7ecx->ecx, NULL, 0) != SECSuccess) + return SECFailure; + } /* recursion here */ rv = NSS_CMSEncoder_Update(p7ecx->childp7ecx, data, len); } else { @@ -640,7 +654,7 @@ NSS_CMSEncoder_Update(NSSCMSEncoderConte } 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) @@ -721,6 +735,16 @@ NSS_CMSEncoder_Finish(NSSCMSEncoderConte * while we are already in NSS_CMSEncoder_Finish, but that's allright. */ if (p7ecx->childp7ecx) { + /* tell the child to start encoding, up to its first data byte, if it + * hasn't yet */ + if (!p7ecx->childp7ecx->ecxupdated) { + p7ecx->childp7ecx->ecxupdated = PR_TRUE; + rv = SEC_ASN1EncoderUpdate(p7ecx->childp7ecx->ecx, NULL, 0); + if (rv != SECSuccess) { + NSS_CMSEncoder_Finish(p7ecx->childp7ecx); /* frees p7ecx->childp7ecx */ + goto loser; + } + } rv = NSS_CMSEncoder_Finish(p7ecx->childp7ecx); /* frees p7ecx->childp7ecx */ if (rv != SECSuccess) goto loser; @@ -737,7 +761,6 @@ NSS_CMSEncoder_Finish(NSSCMSEncoderConte p7ecx->childp7ecx = NULL; - /* find out about our inner content type - must be data */ cinfo = NSS_CMSContent_GetContentInfo(p7ecx->content.pointer, p7ecx->type); if (!cinfo) { /* The original programmer didn't expect this to happen */ @@ -745,14 +768,10 @@ NSS_CMSEncoder_Finish(NSSCMSEncoderConte rv = SECFailure; goto loser; } - childtype = NSS_CMSContentInfo_GetContentTypeTag(cinfo); - if (childtype == SEC_OID_PKCS7_DATA && 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); - } - + SEC_ASN1EncoderClearTakeFromBuf(p7ecx->ecx); SEC_ASN1EncoderClearStreaming(p7ecx->ecx); + /* now that TakeFromBuf is off, this will kick this encoder to finish encoding */ + rv = SEC_ASN1EncoderUpdate(p7ecx->ecx, NULL, 0); if (p7ecx->error) rv = SECFailure; Index: ./mozilla/security/nss/lib/smime/cmsenvdata.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsenvdata.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -p -r1.11 -r1.12 --- ./mozilla/security/nss/lib/smime/cmsenvdata.c 3 Oct 2005 22:01:57 -0000 1.11 +++ ./mozilla/security/nss/lib/smime/cmsenvdata.c 28 Jan 2011 23:03:59 -0000 1.12 @@ -37,7 +37,7 @@ /* * CMS envelopedData methods. * - * $Id: cmsenvdata.c,v 1.11 2005/10/03 22:01:57 relyea%netscape.com Exp $ + * $Id: cmsenvdata.c,v 1.12 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -270,6 +270,7 @@ NSS_CMSEnvelopedData_Encode_BeforeData(N NSSCMSContentInfo *cinfo; PK11SymKey *bulkkey; SECAlgorithmID *algid; + SECStatus rv; cinfo = &(envd->contentInfo); @@ -281,12 +282,16 @@ NSS_CMSEnvelopedData_Encode_BeforeData(N 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(N 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(N 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; Index: ./mozilla/security/nss/lib/smime/cmslocal.h =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmslocal.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -p -r1.5 -r1.6 --- ./mozilla/security/nss/lib/smime/cmslocal.h 27 Jun 2005 22:21:18 -0000 1.5 +++ ./mozilla/security/nss/lib/smime/cmslocal.h 28 Jan 2011 23:03:59 -0000 1.6 @@ -42,7 +42,7 @@ * you. If that has a problem, then just move out what you need, changing * its name as appropriate! * - * $Id: cmslocal.h,v 1.5 2005/06/27 22:21:18 julien.pierre.bugs%sun.com Exp $ + * $Id: cmslocal.h,v 1.6 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #ifndef _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(PLArenaPoo 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_ */ Index: ./mozilla/security/nss/lib/smime/cmsmessage.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsmessage.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -p -r1.6 -r1.7 --- ./mozilla/security/nss/lib/smime/cmsmessage.c 25 Apr 2004 15:03:16 -0000 1.6 +++ ./mozilla/security/nss/lib/smime/cmsmessage.c 28 Jan 2011 23:03:59 -0000 1.7 @@ -37,7 +37,7 @@ /* * CMS message methods. * - * $Id: cmsmessage.c,v 1.6 2004/04/25 15:03:16 gerv%gerv.net Exp $ + * $Id: cmsmessage.c,v 1.7 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -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(NSSCM /* 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 case SEC_OID_PKCS7_ENCRYPTED_DATA: return PR_TRUE; default: + /* callback here for generic wrappers? */ break; } } @@ -289,6 +292,7 @@ NSS_CMSMessage_IsSigned(NSSCMSMessage *c return PR_TRUE; break; default: + /* callback here for generic wrappers? */ break; } } Index: ./mozilla/security/nss/lib/smime/cmssigdata.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmssigdata.c,v retrieving revision 1.29 retrieving revision 1.30 diff -u -p -r1.29 -r1.30 --- ./mozilla/security/nss/lib/smime/cmssigdata.c 27 Jun 2005 22:21:18 -0000 1.29 +++ ./mozilla/security/nss/lib/smime/cmssigdata.c 28 Jan 2011 23:03:59 -0000 1.30 @@ -37,7 +37,7 @@ /* * CMS signedData methods. * - * $Id: cmssigdata.c,v 1.29 2005/06/27 22:21:18 julien.pierre.bugs%sun.com Exp $ + * $Id: cmssigdata.c,v 1.30 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -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(NSSCM 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(NSSCM } /* 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; } Index: ./mozilla/security/nss/lib/smime/cmssiginfo.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmssiginfo.c,v retrieving revision 1.32.2.1 retrieving revision 1.33 diff -u -p -r1.32.2.1 -r1.33 --- ./mozilla/security/nss/lib/smime/cmssiginfo.c 28 Aug 2010 19:51:44 -0000 1.32.2.1 +++ ./mozilla/security/nss/lib/smime/cmssiginfo.c 28 Aug 2010 18:09:09 -0000 1.33 @@ -38,7 +38,7 @@ /* * CMS signerInfo methods. * - * $Id: cmssiginfo.c,v 1.32.2.1 2010/08/28 19:51:44 nelson%bolyard.com Exp $ + * $Id: cmssiginfo.c,v 1.33 2010/08/28 18:09:09 nelson%bolyard.com Exp $ */ #include "cmslocal.h" Index: ./mozilla/security/nss/lib/smime/cmst.h =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmst.h,v retrieving revision 1.10 retrieving revision 1.12 diff -u -p -r1.10 -r1.12 --- ./mozilla/security/nss/lib/smime/cmst.h 27 Jun 2005 22:21:19 -0000 1.10 +++ ./mozilla/security/nss/lib/smime/cmst.h 31 Jan 2011 23:56:30 -0000 1.12 @@ -37,7 +37,7 @@ /* * Header for CMS types. * - * $Id: cmst.h,v 1.10 2005/06/27 22:21:19 julien.pierre.bugs%sun.com Exp $ + * $Id: cmst.h,v 1.12 2011/01/31 23:56:30 rrelyea%redhat.com Exp $ */ #ifndef _CMST_H_ @@ -98,6 +98,8 @@ typedef struct NSSCMSRecipientInfoStr NS typedef struct NSSCMSDigestedDataStr NSSCMSDigestedData; typedef struct NSSCMSEncryptedDataStr NSSCMSEncryptedData; +typedef struct NSSCMSGenericWrapperDataStr NSSCMSGenericWrapperData; + typedef struct NSSCMSSMIMEKEAParametersStr NSSCMSSMIMEKEAParameters; typedef struct NSSCMSAttributeStr NSSCMSAttribute; @@ -108,6 +110,21 @@ typedef struct NSSCMSEncoderContextStr N typedef struct NSSCMSCipherContextStr NSSCMSCipherContext; typedef struct NSSCMSDigestContextStr NSSCMSDigestContext; +typedef struct NSSCMSContentInfoPrivateStr NSSCMSContentInfoPrivate; + +typedef SECStatus (*NSSCMSGenericWrapperDataCallback) + (NSSCMSGenericWrapperData *); +typedef void (*NSSCMSGenericWrapperDataDestroy) + (NSSCMSGenericWrapperData *); + +extern const SEC_ASN1Template NSSCMSGenericWrapperDataTemplate[]; +extern const SEC_ASN1Template NSS_PointerToCMSGenericWrapperDataTemplate[]; + +SEC_ASN1_CHOOSER_DECLARE(NSS_PointerToCMSGenericWrapperDataTemplate) +SEC_ASN1_CHOOSER_DECLARE(NSSCMSGenericWrapperDataTemplate) + + + /* * Type of function passed to NSSCMSDecode or NSSCMSDecoderStart. * If specified, this is where the content bytes (only) will be "sent" @@ -142,6 +159,7 @@ union NSSCMSContentUnion { NSSCMSEncryptedData * encryptedData; NSSCMSEnvelopedData * envelopedData; NSSCMSSignedData * signedData; + NSSCMSGenericWrapperData * genericData; /* or anonymous pointer to something */ void * pointer; }; @@ -164,8 +182,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 +204,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 */ Index: ./mozilla/security/nss/lib/smime/cmsudf.c =================================================================== RCS file: ./mozilla/security/nss/lib/smime/cmsudf.c diff -N ./mozilla/security/nss/lib/smime/cmsudf.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ./mozilla/security/nss/lib/smime/cmsudf.c 31 Jan 2011 23:56:30 -0000 1.2 @@ -0,0 +1,480 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is the Netscape security libraries. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1994-2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * CMS User Define Types + * + * $Id: cmsudf.c,v 1.2 2011/01/31 23:56:30 rrelyea%redhat.com Exp $ + */ + +#include "cmslocal.h" + +#include "prinit.h" +#include "pk11func.h" +#include "secitem.h" +#include "secoid.h" +#include "secerr.h" +#include "nss.h" + +typedef struct nsscmstypeInfoStr nsscmstypeInfo; +struct nsscmstypeInfoStr { + SECOidTag type; + SEC_ASN1Template *template; + size_t size; + PRBool isData; + NSSCMSGenericWrapperDataDestroy destroy; + NSSCMSGenericWrapperDataCallback decode_before; + NSSCMSGenericWrapperDataCallback decode_after; + NSSCMSGenericWrapperDataCallback decode_end; + NSSCMSGenericWrapperDataCallback encode_start; + NSSCMSGenericWrapperDataCallback encode_before; + NSSCMSGenericWrapperDataCallback encode_after; +}; + +/* make sure the global tables are only initialized once */ +static PRCallOnceType nsscmstypeOnce; +static PRCallOnceType nsscmstypeClearOnce; +/* lock for adding a new entry */ +static PRLock *nsscmstypeAddLock; +/* lock for the hash table */ +static PRLock *nsscmstypeHashLock; +/* the hash table itself */ +static PLHashTable *nsscmstypeHash; +/* arena to hold all the hash table data */ +static PRArenaPool *nsscmstypeArena; + +/* + * clean up our global tables + */ +SECStatus +nss_cmstype_shutdown(void *appData, void *reserved) +{ + if (nsscmstypeHashLock) { + PR_Lock(nsscmstypeHashLock); + } + if (nsscmstypeHash) { + PL_HashTableDestroy(nsscmstypeHash); + nsscmstypeHash = NULL; + } + if (nsscmstypeArena) { + PORT_FreeArena(nsscmstypeArena, PR_FALSE); + nsscmstypeArena = NULL; + } + if (nsscmstypeAddLock) { + PR_DestroyLock(nsscmstypeAddLock); + } + if (nsscmstypeHashLock) { + PRLock *oldLock = nsscmstypeHashLock; + nsscmstypeHashLock = NULL; + PR_Unlock(oldLock); + PR_DestroyLock(oldLock); + } + + /* don't clear out the PR_ONCE data if we failed our inital call */ + if (appData == NULL) { + nsscmstypeOnce = nsscmstypeClearOnce; + } + return SECSuccess; +} + +static PLHashNumber +nss_cmstype_hash_key(const void *key) +{ + return (PLHashNumber) key; +} + +static PRIntn +nss_cmstype_compare_keys(const void *v1, const void *v2) +{ + PLHashNumber value1 = (PLHashNumber) v1; + PLHashNumber value2 = (PLHashNumber) v2; + + return (value1 == value2); +} + +/* + * initialize our hash tables, called once on the first attemat to register + * a new SMIME type. + */ +static PRStatus +nss_cmstype_init(void) +{ + SECStatus rv; + + nsscmstypeHashLock = PR_NewLock(); + if (nsscmstypeHashLock == NULL) { + return PR_FAILURE; + } + nsscmstypeAddLock = PR_NewLock(); + if (nsscmstypeHashLock == NULL) { + goto fail; + } + nsscmstypeHash = PL_NewHashTable(64, nss_cmstype_hash_key, + nss_cmstype_compare_keys, PL_CompareValues, NULL, NULL); + if (nsscmstypeHash == NULL) { + goto fail; + } + nsscmstypeArena = PORT_NewArena(2048); + if (nsscmstypeArena == NULL) { + goto fail; + } + rv = NSS_RegisterShutdown(nss_cmstype_shutdown, NULL); + if (rv != SECSuccess) { + goto fail; + } + return PR_SUCCESS; + +fail: + nss_cmstype_shutdown(&nsscmstypeOnce, NULL); + return PR_FAILURE; +} + + +/* + * look up and registered SIME type + */ +static const nsscmstypeInfo * +nss_cmstype_lookup(SECOidTag type) +{ + nsscmstypeInfo *typeInfo = NULL;; + if (!nsscmstypeHash) { + return NULL; + } + PR_Lock(nsscmstypeHashLock); + if (nsscmstypeHash) { + typeInfo = PL_HashTableLookupConst(nsscmstypeHash, (void *)type); + } + PR_Unlock(nsscmstypeHashLock); + return typeInfo; +} + +/* + * add a new type to the SMIME type table + */ +static SECStatus +nss_cmstype_add(SECOidTag type, nsscmstypeInfo *typeinfo) +{ + PLHashEntry *entry; + + if (!nsscmstypeHash) { + /* assert? this shouldn't happen */ + return SECFailure; + } + PR_Lock(nsscmstypeHashLock); + /* this is really paranoia. If we really are racing nsscmstypeHash, we'll + * also be racing nsscmstypeHashLock... */ + if (!nsscmstypeHash) { + PR_Unlock(nsscmstypeHashLock); + return SECFailure; + } + entry = PL_HashTableAdd(nsscmstypeHash, (void *)type, typeinfo); + PR_Unlock(nsscmstypeHashLock); + return entry ? SECSuccess : SECFailure; +} + + +/* helper functions to manage new content types + */ + +PRBool +NSS_CMSType_IsWrapper(SECOidTag type) +{ + const nsscmstypeInfo *typeInfo = NULL; + + switch (type) { + 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 PR_TRUE; + default: + typeInfo = nss_cmstype_lookup(type); + if (typeInfo && !typeInfo->isData) { + return PR_TRUE; + } + } + return PR_FALSE; +} + +PRBool +NSS_CMSType_IsData(SECOidTag type) +{ + const nsscmstypeInfo *typeInfo = NULL; + + switch (type) { + case SEC_OID_PKCS7_DATA: + return PR_TRUE; + default: + typeInfo = nss_cmstype_lookup(type); + if (typeInfo && typeInfo->isData) { + return PR_TRUE; + } + } + return PR_FALSE; +} + +const SEC_ASN1Template * +NSS_CMSType_GetTemplate(SECOidTag type) +{ + const nsscmstypeInfo *typeInfo = nss_cmstype_lookup(type); + + if (typeInfo && typeInfo->template) { + return typeInfo->template; + } + return SEC_ASN1_GET(SEC_PointerToOctetStringTemplate); +} + +size_t +NSS_CMSType_GetContentSize(SECOidTag type) +{ + const nsscmstypeInfo *typeInfo = nss_cmstype_lookup(type); + + if (typeInfo) { + return typeInfo->size; + } + return sizeof(SECItem *); + +} + +void +NSS_CMSGenericWrapperData_Destroy(SECOidTag type, NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo = nss_cmstype_lookup(type); + + if (typeInfo && typeInfo->destroy) { + (*typeInfo->destroy)(gd); + } + +} + + +SECStatus +NSS_CMSGenericWrapperData_Decode_BeforeData(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->decode_before) { + return (*typeInfo->decode_before)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; + +} + +SECStatus +NSS_CMSGenericWrapperData_Decode_AfterData(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->decode_after) { + return (*typeInfo->decode_after)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; +} + +SECStatus +NSS_CMSGenericWrapperData_Decode_AfterEnd(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->decode_end) { + return (*typeInfo->decode_end)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; +} + +SECStatus +NSS_CMSGenericWrapperData_Encode_BeforeStart(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->encode_start) { + return (*typeInfo->encode_start)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; +} + +SECStatus +NSS_CMSGenericWrapperData_Encode_BeforeData(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->encode_before) { + return (*typeInfo->encode_before)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; +} + +SECStatus +NSS_CMSGenericWrapperData_Encode_AfterData(SECOidTag type, + NSSCMSGenericWrapperData *gd) +{ + const nsscmstypeInfo *typeInfo; + + /* short cut common case */ + if (type == SEC_OID_PKCS7_DATA) { + return SECSuccess; + } + + typeInfo = nss_cmstype_lookup(type); + if (typeInfo) { + if (typeInfo->encode_after) { + return (*typeInfo->encode_after)(gd); + } + /* decoder ops optional for data tags */ + if (typeInfo->isData) { + return SECSuccess; + } + } + /* expected a function, but none existed */ + return SECFailure; +} + + +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) +{ + PRStatus rc; + SECStatus rv; + nsscmstypeInfo *typeInfo; + const nsscmstypeInfo *exists; + + rc = PR_CallOnce( &nsscmstypeOnce, nss_cmstype_init); + if (rc == PR_FAILURE) { + return SECFailure; + } + PR_Lock(nsscmstypeAddLock); + exists = nss_cmstype_lookup(type); + if (exists) { + PR_Unlock(nsscmstypeAddLock); + /* already added */ + return SECSuccess; + } + typeInfo = PORT_ArenaNew(nsscmstypeArena, nsscmstypeInfo); + typeInfo->type =type; + typeInfo->size = size; + typeInfo->isData = isData; + typeInfo->template = template; + typeInfo->destroy = destroy; + typeInfo->decode_before = decode_before; + typeInfo->decode_after = decode_after; + typeInfo->decode_end = decode_end; + typeInfo->encode_start = encode_start; + typeInfo->encode_before = encode_before; + typeInfo->encode_after = encode_after; + rv = nss_cmstype_add(type, typeInfo); + PR_Unlock(nsscmstypeAddLock); + return rv; +} + Index: ./mozilla/security/nss/lib/smime/cmsutil.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/cmsutil.c,v retrieving revision 1.15 retrieving revision 1.16 diff -u -p -r1.15 -r1.16 --- ./mozilla/security/nss/lib/smime/cmsutil.c 10 Mar 2008 00:01:27 -0000 1.15 +++ ./mozilla/security/nss/lib/smime/cmsutil.c 28 Jan 2011 23:03:59 -0000 1.16 @@ -38,7 +38,7 @@ /* * CMS miscellaneous utility functions. * - * $Id: cmsutil.c,v 1.15 2008/03/10 00:01:27 wtc%google.com Exp $ + * $Id: cmsutil.c,v 1.16 2011/01/28 23:03:59 rrelyea%redhat.com Exp $ */ #include "cmslocal.h" @@ -243,8 +243,7 @@ NSS_CMSUtil_GetTemplateByTypeTag(SECOidT 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 t 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, break; default: cinfo = NULL; + if (NSS_CMSType_IsWrapper(type)) { + cinfo = &(c.genericData->contentInfo); + } } return cinfo; } Index: ./mozilla/security/nss/lib/smime/manifest.mn =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/manifest.mn,v retrieving revision 1.9 retrieving revision 1.11 diff -u -p -r1.9 -r1.11 --- ./mozilla/security/nss/lib/smime/manifest.mn 15 Aug 2007 15:30:03 -0000 1.9 +++ ./mozilla/security/nss/lib/smime/manifest.mn 28 Jan 2011 23:03:59 -0000 1.11 @@ -69,14 +69,13 @@ CSRCS = \ cmsreclist.c \ cmssigdata.c \ cmssiginfo.c \ + cmsudf.c \ cmsutil.c \ smimemessage.c \ smimeutil.c \ smimever.c \ $(NULL) -REQUIRES = dbm - LIBRARY_NAME = smime LIBRARY_VERSION = 3 Index: ./mozilla/security/nss/lib/smime/smime.def =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/smime.def,v retrieving revision 1.35 retrieving revision 1.37 diff -u -p -r1.35 -r1.37 --- ./mozilla/security/nss/lib/smime/smime.def 30 Sep 2008 04:24:55 -0000 1.35 +++ ./mozilla/security/nss/lib/smime/smime.def 31 Jan 2011 23:56:30 -0000 1.37 @@ -273,3 +273,23 @@ SEC_PKCS12AddCertOrChainAndKey; ;+ local: ;+ *; ;+}; +;+NSS_3.12.10 { # NSS 3.12.10 release +;+ global: +NSS_CMSType_RegisterContentType; +NSS_CMSContentInfo_SetDontStream; +NSS_SMIMEUtil_CreateMSSMIMEEncKeyPrefs; +;+# +;+# Data objects +;+# +;+# Don't export these DATA symbols on Windows because they don't work right. +;+# Use the SEC_ASN1_GET / SEC_ASN1_SUB / SEC_ASN1_XTRN macros to access them. +;+# +;+# See nssutil for other examples. +;+# +;;NSSCMSGenericWrapperDataTemplate DATA ; +;;NSS_PointerToCMSGenericWrapperDataTemplate DATA ; +NSS_Get_NSSCMSGenericWrapperDataTemplate; +NSS_Get_NSS_PointerToCMSGenericWrapperDataTemplate; +;+ local: +;+ *; +;+}; Index: ./mozilla/security/nss/lib/smime/smime.h =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/smime/smime.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -p -r1.8 -r1.9 --- ./mozilla/security/nss/lib/smime/smime.h 25 Apr 2004 15:03:16 -0000 1.8 +++ ./mozilla/security/nss/lib/smime/smime.h 11 Oct 2010 19:30:10 -0000 1.9 @@ -38,7 +38,7 @@ * Header file for routines specific to S/MIME. Keep things that are pure * pkcs7 out of here; this is for S/MIME policy, S/MIME interoperability, etc. * - * $Id: smime.h,v 1.8 2004/04/25 15:03:16 gerv%gerv.net Exp $ + * $Id: smime.h,v 1.9 2010/10/11 19:30:10 wtc%google.com Exp $ */ #ifndef _SECMIME_H_ @@ -83,7 +83,7 @@ extern SECStatus NSS_SMIMEUtil_EnableCip * Initialize the local recording of the S/MIME policy. * This function is called to allow/disallow a particular cipher. * - * XXX This is for a the current module, I think, so local, static storage + * XXX This is for the current module, I think, so local, static storage * XXX is okay. Is that correct, or could multiple uses of the same * XXX library expect to operate under different policies? * Index: ./mozilla/security/nss/lib/cryptohi/seckey.c =================================================================== RCS file: /cvsroot/mozilla/security/nss/lib/cryptohi/seckey.c,v retrieving revision 1.54 retrieving revision 1.54.2.1 diff -u -p -r1.54 -r1.54.2.1 --- ./mozilla/security/nss/lib/cryptohi/seckey.c 23 Jun 2010 02:13:56 -0000 1.54 +++ ./mozilla/security/nss/lib/cryptohi/seckey.c 28 Jan 2011 23:07:46 -0000 1.54.2.1 @@ -1000,6 +1000,15 @@ seckey_GetKeyType (SECOidTag tag) { case SEC_OID_ANSIX962_EC_PUBLIC_KEY: keyType = ecKey; break; + /* accommodate applications that hand us a signature type when they + * should be handing us a cipher type */ + case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION: + case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION: + keyType = rsaKey; + break; default: keyType = nullKey; }