Esempio n. 1
0
/*
 * SecCmsEncryptedDataEncodeBeforeStart - do all the necessary things to a EncryptedData
 *     before encoding begins.
 *
 * In particular:
 *  - set the correct version value.
 *  - get the encryption key
 */
OSStatus
SecCmsEncryptedDataEncodeBeforeStart(SecCmsEncryptedDataRef encd)
{
    int version;
    SecSymmetricKeyRef bulkkey = NULL;
    CSSM_DATA_PTR dummy;
    SecCmsContentInfoRef cinfo = &(encd->contentInfo);

    if (SecCmsArrayIsEmpty((void **)encd->unprotectedAttr))
	version = SEC_CMS_ENCRYPTED_DATA_VERSION;
    else
	version = SEC_CMS_ENCRYPTED_DATA_VERSION_UPATTR;
    
    dummy = SEC_ASN1EncodeInteger (encd->cmsg->poolp, &(encd->version), version);
    if (dummy == NULL)
	return SECFailure;

    /* now get content encryption key (bulk key) by using our cmsg callback */
    if (encd->cmsg->decrypt_key_cb)
	bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, 
		    SecCmsContentInfoGetContentEncAlg(cinfo));
    if (bulkkey == NULL)
	return SECFailure;

    /* store the bulk key in the contentInfo so that the encoder can find it */
    SecCmsContentInfoSetBulkKey(cinfo, bulkkey);
    CFRelease(bulkkey); /* This assumes the decrypt_key_cb hands us a copy of the key --mb */

    return SECSuccess;
}
Esempio n. 2
0
/*
 * SecCmsEncryptedDataEncodeBeforeData - set up encryption
 */
OSStatus
SecCmsEncryptedDataEncodeBeforeData(SecCmsEncryptedDataRef encd)
{
    SecCmsContentInfoRef cinfo;
    SecSymmetricKeyRef bulkkey;
    SECAlgorithmID *algid;

    cinfo = &(encd->contentInfo);

    /* find bulkkey and algorithm - must have been set by SecCmsEncryptedDataEncodeBeforeStart */
    bulkkey = SecCmsContentInfoGetBulkKey(cinfo);
    if (bulkkey == NULL)
	return SECFailure;
    algid = SecCmsContentInfoGetContentEncAlg(cinfo);
    if (algid == NULL)
	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 = SecCmsCipherContextStartEncrypt(encd->cmsg->poolp, bulkkey, algid);
    CFRelease(bulkkey);
    if (cinfo->ciphcx == NULL)
	return SECFailure;

    return SECSuccess;
}
Esempio n. 3
0
/*
 * SecCmsEncryptedDataDecodeBeforeData - find bulk key & set up decryption
 */
OSStatus
SecCmsEncryptedDataDecodeBeforeData(SecCmsEncryptedDataRef encd)
{
    SecSymmetricKeyRef bulkkey = NULL;
    SecCmsContentInfoRef cinfo;
    SECAlgorithmID *bulkalg;
    OSStatus rv = SECFailure;

    cinfo = &(encd->contentInfo);

    bulkalg = SecCmsContentInfoGetContentEncAlg(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;

    SecCmsContentInfoSetBulkKey(cinfo, bulkkey);

    cinfo->ciphcx = SecCmsCipherContextStartDecrypt(bulkkey, bulkalg);
    if (cinfo->ciphcx == NULL)
	goto loser;		/* error has been set by SecCmsCipherContextStartDecrypt */

#if 1
    // @@@ Not done yet
#else
    /* 
     * HACK ALERT!!
     * For PKCS5 Encryption Algorithms, the bulkkey is actually a different
     * structure.  Therefore, we need to set the bulkkey to the actual key 
     * prior to freeing it.
     */
    if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) {
	SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey;
	bulkkey = keyPwd->key;
    }
#endif

    /* we are done with (this) bulkkey now. */
    CFRelease(bulkkey);

    rv = SECSuccess;

loser:
    return rv;
}
Esempio n. 4
0
/*
 * SecCmsEnvelopedDataDecodeBeforeData - find our recipientinfo, 
 * derive bulk key & set up our contentinfo
 */
OSStatus
SecCmsEnvelopedDataDecodeBeforeData(SecCmsEnvelopedData *envd)
{
    SecCmsRecipientInfo *ri;
    SecSymmetricKeyRef bulkkey = NULL;
    SECOidTag bulkalgtag;
    SECAlgorithmID *bulkalg;
    OSStatus rv = SECFailure;
    SecCmsContentInfo *cinfo;
    SecCmsRecipient **recipient_list = NULL;
    SecCmsRecipient *recipient;
    int rlIndex;

    if (SecCmsArrayCount((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 = nss_cms_FindCertAndKeyByRecipientList(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 = SecCmsContentInfoGetContentEncAlgTag(cinfo);
    bulkkey = SecCmsRecipientInfoUnwrapBulkKey(ri,recipient->subIndex,
						    recipient->cert,
						    recipient->privkey,
						    bulkalgtag);
    if (bulkkey == NULL) {
	/* no success finding a bulk key */
	goto loser;
    }

    SecCmsContentInfoSetBulkKey(cinfo, bulkkey);
    // @@@ See 3401088 for details.  We need to CFRelease cinfo->bulkkey before recipient->privkey gets CFReleased. It's created with SecKeyCreate which is not safe currently.  If the private key's SecKeyRef from which we extracted the CSP gets CFRelease before the builkkey does we crash.  We should really fix SecKeyCreate which is a huge hack currently.  To work around this we add recipient->privkey to the cinfo so it gets when cinfo is destroyed.
    CFRetain(recipient->privkey);
    cinfo->privkey = recipient->privkey;

    bulkalg = SecCmsContentInfoGetContentEncAlg(cinfo);

    cinfo->ciphcx = SecCmsCipherContextStartDecrypt(bulkkey, bulkalg);
    if (cinfo->ciphcx == NULL)
	goto loser;		/* error has been set by SecCmsCipherContextStartDecrypt */

#if 1
    // @@@ Fix me
#else
    /* 
     * HACK ALERT!!
     * For PKCS5 Encryption Algorithms, the bulkkey is actually a different
     * structure.  Therefore, we need to set the bulkkey to the actual key 
     * prior to freeing it.
     */
    if (SEC_PKCS5IsAlgorithmPBEAlg(bulkalg)) {
	SEC_PKCS5KeyAndPassword *keyPwd = (SEC_PKCS5KeyAndPassword *)bulkkey;
	bulkkey = keyPwd->key;
    }
#endif

    rv = SECSuccess;

loser:
    if (bulkkey)
	CFRelease(bulkkey);
    if (recipient_list != NULL)
	nss_cms_recipient_list_destroy(recipient_list);
    return rv;
}