if (SEC_ASN1DecodeItem(poolp, &caps, NSSSMIMECapabilitiesTemplate, profile) == SECSuccess &&
if (SEC_QuickDERDecodeItem(poolp, &caps, NSSSMIMECapabilitiesTemplate, profile) == SECSuccess &&
smime_choose_cipher(CERTCertificate *scert, CERTCertificate **rcerts){    PRArenaPool *poolp;    long cipher;    long chosen_cipher;    int *cipher_abilities;    int *cipher_votes;    int weak_mapi;    int strong_mapi;    int rcount, mapi, max, i;    PRBool scert_is_fortezza = (scert == NULL) ? PR_FALSE : PK11_FortezzaHasKEA(scert);    chosen_cipher = SMIME_RC2_CBC_40;		/* the default, LCD */    weak_mapi = smime_mapi_by_cipher(chosen_cipher);    poolp = PORT_NewArena (1024);		/* XXX what is right value? */    if (poolp == NULL)	goto done;    cipher_abilities = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));    cipher_votes     = (int *)PORT_ArenaZAlloc(poolp, smime_cipher_map_count * sizeof(int));    if (cipher_votes == NULL || cipher_abilities == NULL)	goto done;    /* If the user has the Fortezza preference turned on, make     *  that the strong cipher. Otherwise, use triple-DES. */    strong_mapi = smime_mapi_by_cipher (SMIME_DES_EDE3_168);    if (scert_is_fortezza) {	mapi = smime_mapi_by_cipher(SMIME_FORTEZZA);	if (mapi >= 0 && smime_cipher_map[mapi].enabled)	    strong_mapi = mapi;    }    /* walk all the recipient's certs */    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {	SECItem *profile;	NSSSMIMECapability **caps;	int pref;	/* the first cipher that matches in the user's SMIME profile gets	 * "smime_cipher_map_count" votes; the next one gets "smime_cipher_map_count" - 1	 * and so on. If every cipher matches, the last one gets 1 (one) vote */	pref = smime_cipher_map_count;	/* find recipient's SMIME profile */	profile = CERT_FindSMimeProfile(rcerts[rcount]);	if (profile != NULL && profile->data != NULL && profile->len > 0) {	    /* we have a profile (still DER-encoded) */	    caps = NULL;	    /* decode it */	    if (SEC_ASN1DecodeItem(poolp, &caps, NSSSMIMECapabilitiesTemplate, profile) == SECSuccess &&		    caps != NULL)	    {		/* walk the SMIME capabilities for this recipient */		for (i = 0; caps[i] != NULL; i++) {		    cipher = nss_SMIME_FindCipherForSMIMECap(caps[i]);		    mapi = smime_mapi_by_cipher(cipher);		    if (mapi >= 0) {			/* found the cipher */			cipher_abilities[mapi]++;			cipher_votes[mapi] += pref;			--pref;		    }		}	    }	} else {	    /* no profile found - so we can only assume that the user can do	     * the mandatory algorithms which is RC2-40 (weak crypto) and 3DES (strong crypto) */	    SECKEYPublicKey *key;	    unsigned int pklen_bits;	    /*	     * if recipient's public key length is > 512, vote for a strong cipher	     * please not that the side effect of this is that if only one recipient	     * has an export-level public key, the strong cipher is disabled.	     *	     * XXX This is probably only good for RSA keys.  What I would	     * really like is a function to just say;  Is the public key in	     * this cert an export-length key?  Then I would not have to	     * know things like the value 512, or the kind of key, or what	     * a subjectPublicKeyInfo is, etc.	     */	    key = CERT_ExtractPublicKey(rcerts[rcount]);	    pklen_bits = 0;	    if (key != NULL) {		pklen_bits = SECKEY_PublicKeyStrength (key) * 8;		SECKEY_DestroyPublicKey (key);	    }	    if (pklen_bits > 512) {		/* cast votes for the strong algorithm */		cipher_abilities[strong_mapi]++;		cipher_votes[strong_mapi] += pref;		pref--;	    } 	    /* always cast (possibly less) votes for the weak algorithm */	    cipher_abilities[weak_mapi]++;	    cipher_votes[weak_mapi] += pref;	}	if (profile != NULL)	    SECITEM_FreeItem(profile, PR_TRUE);    }    /* find cipher that is agreeable by all recipients and that has the most votes */    max = 0;    for (mapi = 0; mapi < smime_cipher_map_count; mapi++) {	/* if not all of the recipients can do this, forget it */	if (cipher_abilities[mapi] != rcount)	    continue;	/* if cipher is not enabled or not allowed by policy, forget it */	if (!smime_cipher_map[mapi].enabled || !smime_cipher_map[mapi].allowed)	    continue;	/* if we're not doing fortezza, but the cipher is fortezza, forget it */	if (!scert_is_fortezza  && (smime_cipher_map[mapi].cipher == SMIME_FORTEZZA))	    continue;	/* now see if this one has more votes than the last best one */	if (cipher_votes[mapi] >= max) {	    /* if equal number of votes, prefer the ones further down in the list */	    /* with the expectation that these are higher rated ciphers */	    chosen_cipher = smime_cipher_map[mapi].cipher;	    max = cipher_votes[mapi];	}    }    /* if no common cipher was found, chosen_cipher stays at the default */done:    if (poolp != NULL)	PORT_FreeArena (poolp, PR_FALSE);    return chosen_cipher;}