/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* * NSS_CMSEnvelopedData_GetContentInfo - return pointer to this envelopedData's contentinfo
*/
NSSCMSContentInfo *
NSS_CMSEnvelopedData_GetContentInfo(NSSCMSEnvelopedData *envd)
{ return &(envd->contentInfo);
}
/* * NSS_CMSEnvelopedData_AddRecipient - add a recipientinfo to the enveloped data msg * * rip must be created on the same pool as edp - this is not enforced, though.
*/
SECStatus
NSS_CMSEnvelopedData_AddRecipient(NSSCMSEnvelopedData *edp, NSSCMSRecipientInfo *rip)
{ void *mark;
SECStatus rv;
/* XXX compare pools, if not same, copy rip into edp's pool */
/* * NSS_CMSEnvelopedData_Encode_BeforeStart - prepare this envelopedData for encoding * * at this point, we need * - recipientinfos set up with recipient's certificates * - a content encryption algorithm (if none, 3DES will be used) * * this function will generate a random content encryption key (aka bulk key), * initialize the recipientinfos with certificate identification and wrap the bulk key * using the proper algorithm for every certificiate. * it will finally set the bulk algorithm and key so that the encode step can find it.
*/
SECStatus
NSS_CMSEnvelopedData_Encode_BeforeStart(NSSCMSEnvelopedData *envd)
{ int version;
NSSCMSRecipientInfo **recipientinfos;
NSSCMSContentInfo *cinfo;
PK11SymKey *bulkkey = NULL;
SECOidTag bulkalgtag;
CK_MECHANISM_TYPE type;
PK11SlotInfo *slot;
SECStatus rv;
SECItem *dummy;
PLArenaPool *poolp; externconst SEC_ASN1Template NSSCMSRecipientInfoTemplate[]; void *mark = NULL; int i;
if (cinfo == NULL) {
PORT_SetError(SEC_ERROR_BAD_DATA); goto loser;
}
recipientinfos = envd->recipientInfos; if (recipientinfos == NULL) {
PORT_SetError(SEC_ERROR_BAD_DATA); #if 0
PORT_SetErrorString("Cannot find recipientinfos to encode."); #endif goto loser;
}
version = NSS_CMS_ENVELOPED_DATA_VERSION_REG; if (envd->originatorInfo != NULL || envd->unprotectedAttr != NULL) {
version = NSS_CMS_ENVELOPED_DATA_VERSION_ADV;
} else { for (i = 0; recipientinfos[i] != NULL; i++) { if (NSS_CMSRecipientInfo_GetVersion(recipientinfos[i]) != 0) {
version = NSS_CMS_ENVELOPED_DATA_VERSION_ADV; break;
}
}
}
dummy = SEC_ASN1EncodeInteger(poolp, &(envd->version), version); if (dummy == NULL) goto loser;
/* now we need to have a proper content encryption algorithm * on the SMIME level, we would figure one out by looking at SMIME capabilities * we cannot do that on our level, so if none is set already, we'll just go
* with one of the mandatory algorithms (3DES) */ if ((bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo)) == SEC_OID_UNKNOWN) {
rv = NSS_CMSContentInfo_SetContentEncAlg(poolp, cinfo, SEC_OID_DES_EDE3_CBC, NULL, 168); if (rv != SECSuccess) goto loser;
bulkalgtag = SEC_OID_DES_EDE3_CBC;
}
/* generate a random bulk key suitable for content encryption alg */
type = PK11_AlgtagToMechanism(bulkalgtag);
slot = PK11_GetBestSlot(type, envd->cmsg->pwfn_arg); if (slot == NULL) goto loser; /* error has been set by PK11_GetBestSlot */
/* this is expensive... */
bulkkey = PK11_KeyGen(slot, type, NULL,
NSS_CMSContentInfo_GetBulkKeySize(cinfo) / 8,
envd->cmsg->pwfn_arg);
PK11_FreeSlot(slot); if (bulkkey == NULL) goto loser; /* error has been set by PK11_KeyGen */
mark = PORT_ArenaMark(poolp);
/* Encrypt the bulk key with the public key of each recipient. */ for (i = 0; recipientinfos[i] != NULL; i++) {
rv = NSS_CMSRecipientInfo_WrapBulkKey(recipientinfos[i], bulkkey, bulkalgtag); if (rv != SECSuccess) goto loser; /* error has been set by NSS_CMSRecipientInfo_EncryptBulkKey */ /* could be: alg not supported etc. */
}
/* the recipientinfos are all finished. now sort them by DER for SET OF encoding */
rv = NSS_CMSArray_SortByDER((void **)envd->recipientInfos,
NSSCMSRecipientInfoTemplate, NULL); if (rv != SECSuccess) goto loser; /* error has been set by NSS_CMSArray_SortByDER */
/* store the bulk key in the contentInfo so that the encoder can find it */
NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);
PORT_ArenaUnmark(poolp, mark);
PK11_FreeSymKey(bulkkey);
return SECSuccess;
loser: if (mark != NULL)
PORT_ArenaRelease(poolp, mark); if (bulkkey)
PK11_FreeSymKey(bulkkey);
return SECFailure;
}
/* * 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;
}
/* * NSS_CMSEnvelopedData_Encode_AfterData - finalize this envelopedData for encoding
*/
SECStatus
NSS_CMSEnvelopedData_Encode_AfterData(NSSCMSEnvelopedData *envd)
{ if (envd->contentInfo.privateInfo && envd->contentInfo.privateInfo->ciphcx) {
NSS_CMSCipherContext_Destroy(envd->contentInfo.privateInfo->ciphcx);
envd->contentInfo.privateInfo->ciphcx = NULL;
}
/* nothing else to do after data */ return SECSuccess;
}
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;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.