{ CKA_LABEL,            NULL, 0 },
get_token_cert(  NSSToken *token,  nssSession *sessionOpt,  CK_OBJECT_HANDLE handle){    NSSCertificate *rvCert;    NSSArena *arena;    nssSession *session;    PRStatus nssrv;    CK_ULONG template_size;    CK_ATTRIBUTE cert_template[] = {	{ CKA_CERTIFICATE_TYPE, NULL, 0 },	{ CKA_ID,               NULL, 0 },	{ CKA_VALUE,            NULL, 0 },	{ CKA_ISSUER,           NULL, 0 },	{ CKA_SERIAL_NUMBER,    NULL, 0 },	{ CKA_LABEL,            NULL, 0 },	{ CKA_SUBJECT,          NULL, 0 },	{ CKA_NETSCAPE_EMAIL,   NULL, 0 }    };    template_size = sizeof(cert_template) / sizeof(cert_template[0]);    session = (sessionOpt) ? sessionOpt : token->defaultSession;    arena = nssArena_Create();    if (!arena) {	return NULL;    }    rvCert = nss_ZNEW(arena, NSSCertificate);    if (!rvCert) {	NSSArena_Destroy(arena);	return NULL;    }    nssrv = nssPKIObject_Initialize(&rvCert->object, arena,                                     token->trustDomain, NULL);    if (nssrv != PR_SUCCESS) {	goto loser;    }    nssrv = nssCKObject_GetAttributes(handle,                                       cert_template, template_size,                                      arena, session, token->slot);    if (nssrv != PR_SUCCESS) {	goto loser;    }    rvCert->type = nss_cert_type_from_ck_attrib(&cert_template[0]);    NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[1], &rvCert->id);    NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[2], &rvCert->encoding);    NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[3], &rvCert->issuer);    NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[4], &rvCert->serial);    NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[5],  rvCert->nickname);    NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[6], &rvCert->subject);    NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[7],  rvCert->email);    /* XXX this would be better accomplished by dividing attributes to     * retrieve into "required" and "optional"     */    if (rvCert->encoding.size == 0 ||        rvCert->issuer.size == 0 ||        rvCert->serial.size == 0 ||        rvCert->subject.size == 0)     {	/* received a bum object from the token */	goto loser;    }#ifdef NSS_3_4_CODE    /* nss 3.4 database doesn't associate email address with cert */    if (!rvCert->email) {	nssDecodedCert *dc;	NSSASCII7 *email;	dc = nssCertificate_GetDecoding(rvCert);	if (dc) {	    email = dc->getEmailAddress(dc);	    if (email) 	    	rvCert->email = nssUTF8_Duplicate(email, arena);	} else {	    goto loser;	}    }    /* nss 3.4 must deal with tokens that do not follow the PKCS#11     * standard and return decoded serial numbers.  The easiest way to     * work around this is just to grab the serial # from the full encoding     */    if (PR_TRUE) {	nssDecodedCert *dc;	dc = nssCertificate_GetDecoding(rvCert);	if (dc) {	    PRStatus sn_stat;	    sn_stat = dc->getDERSerialNumber(dc, &rvCert->serial, arena);	    if (sn_stat != PR_SUCCESS) {		goto loser;	    }	} else {	    goto loser;	}    }#endif    return rvCert;loser:    nssPKIObject_Destroy(&rvCert->object);    return (NSSCertificate *)NULL;}