/* * NSS_CMSEnvelopedData_Encode_BeforeData - set up encryption * * it is essential that this is called before the contentEncAlg is encoded, because * setting up the encryption may generate IVs and thus change it! */ SECStatus NSS_CMSEnvelopedData_Encode_BeforeData(NSSCMSEnvelopedData *envd) { NSSCMSContentInfo *cinfo; PK11SymKey *bulkkey; SECAlgorithmID *algid; SECStatus rv; cinfo = &(envd->contentInfo); /* find bulkkey and algorithm - must have been set by NSS_CMSEnvelopedData_Encode_BeforeStart */ bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo); if (bulkkey == NULL) return SECFailure; algid = NSS_CMSContentInfo_GetContentEncAlg(cinfo); 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->privateInfo->ciphcx = NSS_CMSCipherContext_StartEncrypt(envd->cmsg->poolp, bulkkey, algid); PK11_FreeSymKey(bulkkey); if (cinfo->privateInfo->ciphcx == NULL) return SECFailure; return SECSuccess; }
SECStatus NSS_CMSContentInfo_SetDontStream(NSSCMSContentInfo *cinfo, PRBool dontStream) { SECStatus rv; if (cinfo == NULL) { return SECFailure; } 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->privateInfo->dontStream = dontStream; return SECSuccess; }
/* * NSS_CMSDigestedData_Encode_BeforeData - do all the necessary things to a DigestedData * before the encapsulated data is passed through the encoder. * * In detail: * - set up the digests if necessary */ 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.privateInfo->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg)); if (digd->contentInfo.privateInfo->digcx == NULL) return SECFailure; } return SECSuccess; }
/* * NSS_CMSContentInfo_GetChildContentInfo - get content's contentInfo (if it exists) */ NSSCMSContentInfo * NSS_CMSContentInfo_GetChildContentInfo(NSSCMSContentInfo *cinfo) { NSSCMSContentInfo *ccinfo = NULL; if (cinfo == NULL) { return NULL; } SECOidTag tag = NSS_CMSContentInfo_GetContentTypeTag(cinfo); switch (tag) { case SEC_OID_PKCS7_SIGNED_DATA: if (cinfo->content.signedData != NULL) { ccinfo = &(cinfo->content.signedData->contentInfo); } break; case SEC_OID_PKCS7_ENVELOPED_DATA: if (cinfo->content.envelopedData != NULL) { ccinfo = &(cinfo->content.envelopedData->contentInfo); } break; case SEC_OID_PKCS7_DIGESTED_DATA: if (cinfo->content.digestedData != NULL) { ccinfo = &(cinfo->content.digestedData->contentInfo); } break; case SEC_OID_PKCS7_ENCRYPTED_DATA: 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; } if (ccinfo && !ccinfo->privateInfo) { NSS_CMSContentInfo_Private_Init(ccinfo); } return ccinfo; }
/* * NSS_CMSDigestedData_Decode_BeforeData - do all the necessary things to a DigestedData * before the encapsulated data is passed through the encoder. * * In detail: * - set up the digests if necessary */ SECStatus NSS_CMSDigestedData_Decode_BeforeData(NSSCMSDigestedData *digd) { SECStatus rv; /* is there a digest algorithm yet? */ if (digd->digestAlg.algorithm.len == 0) return SECFailure; rv = NSS_CMSContentInfo_Private_Init(&digd->contentInfo); if (rv != SECSuccess) { return SECFailure; } digd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartSingle(&(digd->digestAlg)); if (digd->contentInfo.privateInfo->digcx == NULL) return SECFailure; return SECSuccess; }
/* * NSS_CMSEncryptedData_Decode_BeforeData - find bulk key & set up decryption */ SECStatus NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd) { PK11SymKey *bulkkey = NULL; NSSCMSContentInfo *cinfo; SECAlgorithmID *bulkalg; SECStatus rv = SECFailure; cinfo = &(encd->contentInfo); bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo); if (encd->cmsg->decrypt_key_cb == NULL) /* no callback? no key../ */ goto loser; bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg); if (bulkkey == NULL) /* no success finding a bulk key */ goto loser; NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey); rv = NSS_CMSContentInfo_Private_Init(cinfo); if (rv != SECSuccess) { goto loser; } rv = SECFailure; cinfo->privateInfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg); if (cinfo->privateInfo->ciphcx == NULL) goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */ /* we are done with (this) bulkkey now. */ PK11_FreeSymKey(bulkkey); rv = SECSuccess; loser: return rv; }
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; } /* handle issue with Windows 2003 servers and kerberos */ if (sigd->digestAlgorithms != NULL) { int i; for (i=0; sigd->digestAlgorithms[i] != NULL; i++) { SECAlgorithmID *algid = sigd->digestAlgorithms[i]; SECOidTag senttag= SECOID_FindOIDTag(&algid->algorithm); SECOidTag maptag = NSS_CMSUtil_MapSignAlgs(senttag); if (maptag != senttag) { SECOidData *hashoid = SECOID_FindOIDByTag(maptag); rv = SECITEM_CopyItem(sigd->cmsg->poolp, &algid->algorithm ,&hashoid->oid); if (rv != SECSuccess) { return rv; } } } } /* set up the digests */ if (sigd->digestAlgorithms != NULL && sigd->digests == NULL) { /* if digests are already there, do nothing */ sigd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); if (sigd->contentInfo.privateInfo->digcx == NULL) return SECFailure; } return SECSuccess; }
/* * NSS_CMSMessage_Create - create a CMS message object * * "poolp" - arena to allocate memory from, or NULL if new arena should be created */ NSSCMSMessage * NSS_CMSMessage_Create(PLArenaPool *poolp) { void *mark = NULL; NSSCMSMessage *cmsg; PRBool poolp_is_ours = PR_FALSE; if (poolp == NULL) { poolp = PORT_NewArena (1024); /* XXX what is right value? */ if (poolp == NULL) return NULL; poolp_is_ours = PR_TRUE; } if (!poolp_is_ours) mark = PORT_ArenaMark(poolp); cmsg = (NSSCMSMessage *)PORT_ArenaZAlloc (poolp, sizeof(NSSCMSMessage)); if (cmsg == NULL) { if (!poolp_is_ours) { if (mark) { PORT_ArenaRelease(poolp, mark); } } else PORT_FreeArena(poolp, PR_FALSE); return NULL; } NSS_CMSContentInfo_Private_Init(&(cmsg->contentInfo)); cmsg->poolp = poolp; cmsg->poolp_is_ours = poolp_is_ours; cmsg->refCount = 1; if (mark) PORT_ArenaUnmark(poolp, mark); return cmsg; }
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.privateInfo->digcx = NULL; /* don't attempt to make new ones. */ } else if (sigd->digestAlgorithms != NULL) { sigd->contentInfo.privateInfo->digcx = NSS_CMSDigestContext_StartMultiple(sigd->digestAlgorithms); if (sigd->contentInfo.privateInfo->digcx == NULL) return SECFailure; } return SECSuccess; }
/* * NSS_CMSEnvelopedData_Decode_BeforeData - find our recipientinfo, * derive bulk key & set up our contentinfo */ SECStatus NSS_CMSEnvelopedData_Decode_BeforeData(NSSCMSEnvelopedData *envd) { NSSCMSRecipientInfo *ri; PK11SymKey *bulkkey = NULL; SECOidTag bulkalgtag; SECAlgorithmID *bulkalg; SECStatus rv = SECFailure; NSSCMSContentInfo *cinfo; NSSCMSRecipient **recipient_list = NULL; NSSCMSRecipient *recipient; int rlIndex; if (NSS_CMSArray_Count((void **)envd->recipientInfos) == 0) { PORT_SetError(SEC_ERROR_BAD_DATA); #if 0 PORT_SetErrorString("No recipient data in envelope."); #endif goto loser; } /* look if one of OUR cert's issuerSN is on the list of recipients, and if so, */ /* get the cert and private key for it right away */ recipient_list = nss_cms_recipient_list_create(envd->recipientInfos); if (recipient_list == NULL) goto loser; /* what about multiple recipientInfos that match? * especially if, for some reason, we could not produce a bulk key with the first match?! * we could loop & feed partial recipient_list to PK11_FindCertAndKeyByRecipientList... * maybe later... */ rlIndex = PK11_FindCertAndKeyByRecipientListNew(recipient_list, envd->cmsg->pwfn_arg); /* if that fails, then we're not an intended recipient and cannot decrypt */ if (rlIndex < 0) { PORT_SetError(SEC_ERROR_NOT_A_RECIPIENT); #if 0 PORT_SetErrorString("Cannot decrypt data because proper key cannot be found."); #endif goto loser; } recipient = recipient_list[rlIndex]; if (!recipient->cert || !recipient->privkey) { /* XXX should set an error code ?!? */ goto loser; } /* get a pointer to "our" recipientinfo */ ri = envd->recipientInfos[recipient->riIndex]; cinfo = &(envd->contentInfo); bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo); if (bulkalgtag == SEC_OID_UNKNOWN) { PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); } else bulkkey = NSS_CMSRecipientInfo_UnwrapBulkKey(ri,recipient->subIndex, recipient->cert, recipient->privkey, bulkalgtag); if (bulkkey == NULL) { /* no success finding a bulk key */ goto loser; } NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey); bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo); rv = NSS_CMSContentInfo_Private_Init(cinfo); if (rv != SECSuccess) { goto loser; } rv = SECFailure; cinfo->privateInfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg); if (cinfo->privateInfo->ciphcx == NULL) goto loser; /* error has been set by NSS_CMSCipherContext_StartDecrypt */ rv = SECSuccess; loser: if (bulkkey) PK11_FreeSymKey(bulkkey); if (recipient_list != NULL) nss_cms_recipient_list_destroy(recipient_list); return rv; }