if (freeSpki) SECKEY_DestroySubjectPublicKeyInfo(freeSpki);
NSS_CMSRecipientInfo_WrapBulkKey(NSSCMSRecipientInfo *ri, PK11SymKey *bulkkey, SECOidTag bulkalgtag){    CERTCertificate *cert;    SECOidTag certalgtag;    SECStatus rv = SECSuccess;    SECItem *params = NULL;    NSSCMSRecipientEncryptedKey *rek;    NSSCMSOriginatorIdentifierOrKey *oiok;    PLArenaPool *poolp;    poolp = ri->cmsg->poolp;    cert = ri->cert;    PORT_Assert (cert != NULL);    if (cert == NULL)	return SECFailure;    /* XXX set ri->recipientInfoType to the proper value here */    /* or should we look if it's been set already ? */    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));    switch (certalgtag) {    case SEC_OID_PKCS1_RSA_ENCRYPTION:	/* wrap the symkey */	if (NSS_CMSUtil_EncryptSymKey_RSA(poolp, cert, bulkkey, &ri->ri.keyTransRecipientInfo.encKey) != SECSuccess) {	    rv = SECFailure;	    break;	}	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, NULL);	break;    case SEC_OID_MISSI_KEA_DSS_OLD:    case SEC_OID_MISSI_KEA_DSS:    case SEC_OID_MISSI_KEA:	rv = NSS_CMSUtil_EncryptSymKey_MISSI(poolp, cert, bulkkey,					bulkalgtag,					&ri->ri.keyTransRecipientInfo.encKey,					&params, ri->cmsg->pwfn_arg);	if (rv != SECSuccess)	    break;	/* here, we DO need to pass the params to the wrap function because, with	 * RSA, there is no funny stuff going on with generation of IV vectors or so */	rv = SECOID_SetAlgorithmID(poolp, &(ri->ri.keyTransRecipientInfo.keyEncAlg), certalgtag, params);	break;    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */	rek = ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys[0];	if (rek == NULL) {	    rv = SECFailure;	    break;	}	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);	PORT_Assert(oiok->identifierType == NSSCMSOriginatorIDOrKey_OriginatorPublicKey);	/* see RFC2630 12.3.1.1 */	if (SECOID_SetAlgorithmID(poolp, &oiok->id.originatorPublicKey.algorithmIdentifier,				    SEC_OID_X942_DIFFIE_HELMAN_KEY, NULL) != SECSuccess) {	    rv = SECFailure;	    break;	}	/* this will generate a key pair, compute the shared secret, */	/* derive a key and ukm for the keyEncAlg out of it, encrypt the bulk key with */	/* the keyEncAlg, set encKey, keyEncAlg, publicKey etc. */	rv = NSS_CMSUtil_EncryptSymKey_ESDH(poolp, cert, bulkkey,					&rek->encKey,					&ri->ri.keyAgreeRecipientInfo.ukm,					&ri->ri.keyAgreeRecipientInfo.keyEncAlg,					&oiok->id.originatorPublicKey.publicKey);	break;    default:	/* other algorithms not supported yet */	/* NOTE that we do not support any KEK algorithm */	PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);	rv = SECFailure;	break;    }    return rv;}