dstat = SEC_ASN1DecodeItem (poolp, &caps,
dstat = SEC_QuickDERDecodeItem (poolp, &caps,
smime_choose_cipher (CERTCertificate *scert, CERTCertificate **rcerts){    PRArenaPool *poolp;    long chosen_cipher;    int *cipher_abilities;    int *cipher_votes;    int strong_mapi;    int rcount, mapi, max, i;	PRBool isFortezza = PK11_FortezzaHasKEA(scert);    if (smime_policy_bits == 0) {	PORT_SetError (SEC_ERROR_BAD_EXPORT_ALGORITHM);	return -1;    }    chosen_cipher = SMIME_RC2_CBC_40;		/* the default, LCD */    poolp = PORT_NewArena (1024);		/* XXX what is right value? */    if (poolp == NULL)	goto done;    cipher_abilities = (int*)PORT_ArenaZAlloc (poolp,					 smime_symmetric_count * sizeof(int));    if (cipher_abilities == NULL)	goto done;    cipher_votes = (int*)PORT_ArenaZAlloc (poolp,				     smime_symmetric_count * sizeof(int));    if (cipher_votes == NULL)	goto done;    /*     * XXX Should have a #define somewhere which specifies default     * strong cipher.  (Or better, a way to configure, which would     * take Fortezza into account as well.)     */    /* If the user has the Fortezza preference turned on, make     *  that the strong cipher. Otherwise, use triple-DES. */    strong_mapi = -1;    if (isFortezza) {	for(i=0;i < smime_current_pref_index && strong_mapi < 0;i++)	{	    if (smime_prefs[i] == SMIME_FORTEZZA)		strong_mapi = smime_mapi_by_cipher(SMIME_FORTEZZA);	}    }    if (strong_mapi == -1)	strong_mapi = smime_mapi_by_cipher (SMIME_DES_EDE3_168);    PORT_Assert (strong_mapi >= 0);    for (rcount = 0; rcerts[rcount] != NULL; rcount++) {	SECItem *profile;	smime_capability **caps;	int capi, pref;	SECStatus dstat;	pref = smime_symmetric_count;	profile = CERT_FindSMimeProfile (rcerts[rcount]);	if (profile != NULL && profile->data != NULL && profile->len > 0) {	    caps = NULL;	    dstat = SEC_ASN1DecodeItem (poolp, &caps,					smime_capabilities_template,					profile);	    if (dstat == SECSuccess && caps != NULL) {		for (capi = 0; caps[capi] != NULL; capi++) {		    smime_fill_capability (caps[capi]);		    mapi = smime_mapi_by_cipher (caps[capi]->cipher);		    if (mapi >= 0) {			cipher_abilities[mapi]++;			cipher_votes[mapi] += pref;			--pref;		    }		}	    }	} else {	    SECKEYPublicKey *key;	    unsigned int pklen_bits;	    /*	     * 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]);	    if (key != NULL) {		pklen_bits = SECKEY_PublicKeyStrength (key) * 8;		SECKEY_DestroyPublicKey (key);		if (pklen_bits > 512) {		    cipher_abilities[strong_mapi]++;		    cipher_votes[strong_mapi] += pref;		}	    }	}	if (profile != NULL)	    SECITEM_FreeItem (profile, PR_TRUE);    }    max = 0;    for (mapi = 0; mapi < smime_symmetric_count; mapi++) {	if (cipher_abilities[mapi] != rcount)	    continue;	if (! smime_cipher_allowed (smime_cipher_maps[mapi].cipher))	    continue;	if (!isFortezza  && (smime_cipher_maps[mapi].cipher == SMIME_FORTEZZA))		continue;	if (cipher_votes[mapi] > max) {	    chosen_cipher = smime_cipher_maps[mapi].cipher;	    max = cipher_votes[mapi];	} /* XXX else if a tie, let scert break it? */    }done:    if (poolp != NULL)	PORT_FreeArena (poolp, PR_FALSE);    return chosen_cipher;}