if (type == NSSCMSRecipientID_IssuerSN) { ri->cert = CERT_DupCertificate(cert); if (ri->cert == NULL) goto loser; spki = &(cert->subjectPublicKeyInfo); } else { PORT_Assert(pubKey); spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
if (DERinput) {  SECItem newinput; SECStatus rv = SECITEM_CopyItem(poolp, &newinput, DERinput); if (SECSuccess != rv) goto loser; rv = SEC_QuickDERDecodeItem(poolp, ri, NSSCMSRecipientInfoTemplate, &newinput); if (SECSuccess != rv) goto loser; }  switch (type) { case NSSCMSRecipientID_IssuerSN: { ri->cert = CERT_DupCertificate(cert); if (NULL == ri->cert) goto loser; spki = &(cert->subjectPublicKeyInfo); break; }  case NSSCMSRecipientID_SubjectKeyID: { PORT_Assert(pubKey); spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey); break; }  case NSSCMSRecipientID_BrandNew: goto done; break;  default:  goto loser; break;
nss_cmsrecipientinfo_create(NSSCMSMessage *cmsg, NSSCMSRecipientIDSelector type,                            CERTCertificate *cert, SECKEYPublicKey *pubKey,                             SECItem *subjKeyID){    NSSCMSRecipientInfo *ri;    void *mark;    SECOidTag certalgtag;    SECStatus rv = SECSuccess;    NSSCMSRecipientEncryptedKey *rek;    NSSCMSOriginatorIdentifierOrKey *oiok;    unsigned long version;    SECItem *dummy;    PLArenaPool *poolp;    CERTSubjectPublicKeyInfo *spki, *freeSpki = NULL;    NSSCMSRecipientIdentifier *rid;    poolp = cmsg->poolp;    mark = PORT_ArenaMark(poolp);    ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));    if (ri == NULL)	goto loser;    ri->cmsg = cmsg;    if (type == NSSCMSRecipientID_IssuerSN) {	ri->cert = CERT_DupCertificate(cert);	if (ri->cert == NULL)	    goto loser;	spki = &(cert->subjectPublicKeyInfo);    } else {	PORT_Assert(pubKey);	spki = freeSpki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);    }    certalgtag = SECOID_GetAlgorithmTag(&(spki->algorithm));    rid = &ri->ri.keyTransRecipientInfo.recipientIdentifier;    switch (certalgtag) {    case SEC_OID_PKCS1_RSA_ENCRYPTION:	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;	rid->identifierType = type;	if (type == NSSCMSRecipientID_IssuerSN) {	    rid->id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);	    if (rid->id.issuerAndSN == NULL) {	      break;	    }	} else if (type == NSSCMSRecipientID_SubjectKeyID){	    NSSCMSKeyTransRecipientInfoEx *riExtra;	    rid->id.subjectKeyID = PORT_ArenaNew(poolp, SECItem);	    if (rid->id.subjectKeyID == NULL) {		rv = SECFailure;		PORT_SetError(SEC_ERROR_NO_MEMORY);		break;	    } 	    SECITEM_CopyItem(poolp, rid->id.subjectKeyID, subjKeyID);	    if (rid->id.subjectKeyID->data == NULL) {		rv = SECFailure;		PORT_SetError(SEC_ERROR_NO_MEMORY);		break;	    }	    riExtra = &ri->ri.keyTransRecipientInfoEx;	    riExtra->version = 0;	    riExtra->pubKey = SECKEY_CopyPublicKey(pubKey);	    if (riExtra->pubKey == NULL) {		rv = SECFailure;		PORT_SetError(SEC_ERROR_NO_MEMORY);		break;	    }	} else {	    PORT_SetError(SEC_ERROR_INVALID_ARGS);	    rv = SECFailure;	}	break;    case SEC_OID_MISSI_KEA_DSS_OLD:    case SEC_OID_MISSI_KEA_DSS:    case SEC_OID_MISSI_KEA:        PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID);	if (type == NSSCMSRecipientID_SubjectKeyID) {	    rv = SECFailure;	    break;	}	/* backward compatibility - this is not really a keytrans operation */	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;	/* hardcoded issuerSN choice for now */	ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType = NSSCMSRecipientID_IssuerSN;	ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert);	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {	    rv = SECFailure;	    break;	}	break;    case SEC_OID_X942_DIFFIE_HELMAN_KEY: /* dh-public-number */        PORT_Assert(type != NSSCMSRecipientID_SubjectKeyID);	if (type == NSSCMSRecipientID_SubjectKeyID) {	    rv = SECFailure;	    break;	}	/* a key agreement op */	ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) {	    rv = SECFailure;	    break;	}	/* we do not support the case where multiple recipients 	 * share the same KeyAgreeRecipientInfo and have multiple RecipientEncryptedKeys	 * in this case, we would need to walk all the recipientInfos, take the	 * ones that do KeyAgreement algorithms and join them, algorithm by algorithm	 * Then, we'd generate ONE ukm and OriginatorIdentifierOrKey */	/* only epheremal-static Diffie-Hellman is supported for now	 * this is the only form of key agreement that provides potential anonymity	 * of the sender, plus we do not have to include certs in the message */	/* force single recipientEncryptedKey for now */	if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL) {	    rv = SECFailure;	    break;	}	/* hardcoded IssuerSN choice for now */	rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN;	if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) {	    rv = SECFailure;	    break;	}	oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);	/* see RFC2630 12.3.1.1 */	oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey;	rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys,				    (void *)rek);	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;    }    if (rv == SECFailure)	goto loser;    /* set version */    switch (ri->recipientInfoType) {    case NSSCMSRecipientInfoID_KeyTrans:	if (ri->ri.keyTransRecipientInfo.recipientIdentifier.identifierType == NSSCMSRecipientID_IssuerSN)	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_ISSUERSN;	else	    version = NSS_CMS_KEYTRANS_RECIPIENT_INFO_VERSION_SUBJKEY;	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyTransRecipientInfo.version), version);	if (dummy == NULL)	    goto loser;	break;    case NSSCMSRecipientInfoID_KeyAgree:	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.keyAgreeRecipientInfo.version),						NSS_CMS_KEYAGREE_RECIPIENT_INFO_VERSION);	if (dummy == NULL)	    goto loser;	break;    case NSSCMSRecipientInfoID_KEK:	/* NOTE: this cannot happen as long as we do not support any KEK algorithm */	dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version),						NSS_CMS_KEK_RECIPIENT_INFO_VERSION);	if (dummy == NULL)	    goto loser;	break;        }    PORT_ArenaUnmark (poolp, mark);    if (freeSpki)      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);    return ri;loser:    if (freeSpki)      SECKEY_DestroySubjectPublicKeyInfo(freeSpki);    PORT_ArenaRelease (poolp, mark);    return NULL;}