NSSCMSRecipientInfo *ri; void *mark; SECOidTag certalgtag; SECStatus rv = SECSuccess; NSSCMSRecipientEncryptedKey *rek; NSSCMSOriginatorIdentifierOrKey *oiok; unsigned long version; SECItem *dummy; PLArenaPool *poolp;  poolp = cmsg->poolp;  mark = PORT_ArenaMark(poolp);  ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo)); if (ri == NULL) goto loser;  ri->cmsg = cmsg; ri->cert = CERT_DupCertificate(cert); if (ri->cert == NULL) goto loser;  certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));  switch (certalgtag) { case SEC_OID_PKCS1_RSA_ENCRYPTION: ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;  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_MISSI_KEA_DSS_OLD: case SEC_OID_MISSI_KEA_DSS: case SEC_OID_MISSI_KEA:  ri->recipientInfoType = NSSCMSRecipientInfoID_KeyTrans;  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:   ri->recipientInfoType = NSSCMSRecipientInfoID_KeyAgree;  if (ri->ri.keyTransRecipientInfo.recipientIdentifier.id.issuerAndSN == NULL) { rv = SECFailure; break; }      if ((rek = NSS_CMSRecipientEncryptedKey_Create(poolp)) == NULL) { rv = SECFailure; break; }   rek->recipientIdentifier.identifierType = NSSCMSKeyAgreeRecipientID_IssuerSN; if ((rek->recipientIdentifier.id.issuerAndSN = CERT_GetCertIssuerAndSN(poolp, cert)) == NULL) { rv = SECFailure; break; }  oiok = &(ri->ri.keyAgreeRecipientInfo.originatorIdentifierOrKey);   oiok->identifierType = NSSCMSOriginatorIDOrKey_OriginatorPublicKey;  rv = NSS_CMSArray_Add(poolp, (void ***)&ri->ri.keyAgreeRecipientInfo.recipientEncryptedKeys, (void *)rek);  break; default:   PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); rv = SECFailure; break; }  if (rv == SECFailure) goto loser;   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:  dummy = SEC_ASN1EncodeInteger(poolp, &(ri->ri.kekRecipientInfo.version), NSS_CMS_KEK_RECIPIENT_INFO_VERSION); if (dummy == NULL) goto loser; break;  }  PORT_ArenaUnmark (poolp, mark); return ri;  loser: PORT_ArenaRelease (poolp, mark); return NULL;
return nss_cmsrecipientinfo_create(cmsg, NSSCMSRecipientID_IssuerSN, cert, NULL, NULL);
NSS_CMSRecipientInfo_Create(NSSCMSMessage *cmsg, CERTCertificate *cert){    NSSCMSRecipientInfo *ri;    void *mark;    SECOidTag certalgtag;    SECStatus rv = SECSuccess;    NSSCMSRecipientEncryptedKey *rek;    NSSCMSOriginatorIdentifierOrKey *oiok;    unsigned long version;    SECItem *dummy;    PLArenaPool *poolp;    poolp = cmsg->poolp;    mark = PORT_ArenaMark(poolp);    ri = (NSSCMSRecipientInfo *)PORT_ArenaZAlloc(poolp, sizeof(NSSCMSRecipientInfo));    if (ri == NULL)	goto loser;    ri->cmsg = cmsg;    ri->cert = CERT_DupCertificate(cert);    if (ri->cert == NULL)	goto loser;    certalgtag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));    switch (certalgtag) {    case SEC_OID_PKCS1_RSA_ENCRYPTION:	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_MISSI_KEA_DSS_OLD:    case SEC_OID_MISSI_KEA_DSS:    case SEC_OID_MISSI_KEA:	/* 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 */	/* 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);    return ri;loser:    PORT_ArenaRelease (poolp, mark);    return NULL;}