CK_KEY_TYPE key_type = -1;
CK_KEY_TYPE key_type = CKK_INVALID_KEY_TYPE;
CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession,    CK_MECHANISM_PTR pMechanism,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,    						CK_OBJECT_HANDLE_PTR phKey){    PK11Object *key;    PK11Session *session;    PRBool checkWeak = PR_FALSE;    CK_ULONG key_length = 0;    CK_KEY_TYPE key_type = -1;    CK_OBJECT_CLASS objclass = CKO_SECRET_KEY;    CK_RV crv = CKR_OK;    CK_BBOOL cktrue = CK_TRUE;    int i;    PK11Slot *slot = pk11_SlotFromSessionHandle(hSession);    char buf[MAX_KEY_LEN];    enum {pk11_pbe, pk11_pbe_hmac, pk11_ssl, pk11_bulk} key_gen_type;    SECOidTag algtag = SEC_OID_UNKNOWN;    SSL3RSAPreMasterSecret *rsa_pms;    CK_VERSION *version;    /* in very old versions of NSS, there were implementation errors with key      * generation methods.  We want to beable to read these, but not      * produce them any more.  The affected algorithm was 3DES.     */    PRBool faultyPBE3DES = PR_FALSE;    /*     * now lets create an object to hang the attributes off of     */    key = pk11_NewObject(slot); /* fill in the handle later */    if (key == NULL) {	return CKR_HOST_MEMORY;    }    /*     * load the template values into the object     */    for (i=0; i < (int) ulCount; i++) {	if (pTemplate[i].type == CKA_VALUE_LEN) {	    key_length = *(CK_ULONG *)pTemplate[i].pValue;	    continue;	}	crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));	if (crv != CKR_OK) break;    }    if (crv != CKR_OK) {	pk11_FreeObject(key);	return crv;    }    /* make sure we don't have any class, key_type, or value fields */    pk11_DeleteAttributeType(key,CKA_CLASS);    pk11_DeleteAttributeType(key,CKA_KEY_TYPE);    pk11_DeleteAttributeType(key,CKA_VALUE);    /* Now Set up the parameters to generate the key (based on mechanism) */    key_gen_type = pk11_bulk; /* bulk key by default */    switch (pMechanism->mechanism) {    case CKM_CDMF_KEY_GEN:    case CKM_DES_KEY_GEN:    case CKM_DES2_KEY_GEN:    case CKM_DES3_KEY_GEN:	checkWeak = PR_TRUE;    case CKM_RC2_KEY_GEN:    case CKM_RC4_KEY_GEN:    case CKM_GENERIC_SECRET_KEY_GEN:    case CKM_AES_KEY_GEN:#if NSS_SOFTOKEN_DOES_RC5    case CKM_RC5_KEY_GEN:#endif	crv = nsc_SetupBulkKeyGen(pMechanism->mechanism,&key_type,&key_length);	break;    case CKM_SSL3_PRE_MASTER_KEY_GEN:	key_type = CKK_GENERIC_SECRET;	key_length = 48;	key_gen_type = pk11_ssl;	break;    case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC:	faultyPBE3DES = PR_TRUE;    case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN:    case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN:    case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN:	key_gen_type = pk11_pbe_hmac;	key_type = CKK_GENERIC_SECRET;	break;    case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC:    case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC:    case CKM_NETSCAPE_PBE_SHA1_DES_CBC:    case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC:    case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4:    case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4:    case CKM_PBE_SHA1_DES3_EDE_CBC:    case CKM_PBE_SHA1_DES2_EDE_CBC:    case CKM_PBE_SHA1_RC2_128_CBC:    case CKM_PBE_SHA1_RC2_40_CBC:    case CKM_PBE_SHA1_RC4_128:    case CKM_PBE_SHA1_RC4_40:    case CKM_PBE_MD5_DES_CBC:    case CKM_PBE_MD2_DES_CBC:	key_gen_type = pk11_pbe;	crv = nsc_SetupPBEKeyGen(pMechanism->mechanism,&algtag,							&key_type,&key_length);	break;    default:	crv = CKR_MECHANISM_INVALID;	break;    }    /* make sure we aren't going to overflow the buffer */    if (sizeof(buf) < key_length) {	/* someone is getting pretty optimistic about how big their key can	 * be... */        crv = CKR_TEMPLATE_INCONSISTENT;    }    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    /* if there was no error,     * key_type *MUST* be set in the switch statement above */    PORT_Assert( key_type != -1 );    /*     * now to the actual key gen.     */    switch (key_gen_type) {    case pk11_pbe_hmac:	crv = pk11_pbe_hmac_key_gen(pMechanism, buf, &key_length,	                            faultyPBE3DES);	break;    case pk11_pbe:	crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length,			       faultyPBE3DES);	break;    case pk11_ssl:	rsa_pms = (SSL3RSAPreMasterSecret *)buf;	version = (CK_VERSION *)pMechanism->pParameter;	rsa_pms->client_version[0] = version->major;        rsa_pms->client_version[1] = version->minor;        crv = 	    NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random));	break;    case pk11_bulk:	/* get the key, check for weak keys and repeat if found */	do {            crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length);	} while (crv == CKR_OK && checkWeak && 			pk11_IsWeakKey((unsigned char *)buf,key_type));	break;    }    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    /* Add the class, key_type, and value */    crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    crv = pk11_AddAttributeType(key,CKA_KEY_TYPE,&key_type,sizeof(CK_KEY_TYPE));    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    crv = pk11_AddAttributeType(key,CKA_CLASS,&objclass,sizeof(CK_OBJECT_CLASS));    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    crv = pk11_AddAttributeType(key,CKA_VALUE,buf,key_length);    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    /* get the session */    session = pk11_SessionFromHandle(hSession);    if (session == NULL) {	pk11_FreeObject(key);        return CKR_SESSION_HANDLE_INVALID;    }    /*     * handle the base object stuff     */    crv = pk11_handleObject(key,session);    pk11_FreeSession(session);    if (crv != CKR_OK) {	pk11_FreeObject(key);	return crv;    }    if (pk11_isTrue(key,CKA_SENSITIVE)) {	pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL));    }    if (!pk11_isTrue(key,CKA_EXTRACTABLE)) {	pk11_forceAttribute(key,CKA_NEVER_EXTRACTABLE,&cktrue,sizeof(CK_BBOOL));    }    *phKey = key->handle;    return CKR_OK;}