status = pk11_PRF(&pms, "master secret", &crsr, &master);
status = pk11_PRF(&pms, "master secret", &crsr, &master, isFIPS);
CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession,	 CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey,	 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, 						CK_OBJECT_HANDLE_PTR phKey){    PK11Session *   session;    PK11Slot    *   slot	= pk11_SlotFromSessionHandle(hSession);    PK11Object  *   key;    PK11Object  *   sourceKey;    PK11Attribute * att;    PK11Attribute * att2;    unsigned char * buf;    SHA1Context *   sha;    MD5Context *    md5;    MD2Context *    md2;    CK_ULONG        macSize;    CK_ULONG        tmpKeySize;    CK_ULONG        IVSize;    CK_ULONG        keySize	= 0;    CK_RV           crv 	= CKR_OK;    CK_BBOOL        cktrue	= CK_TRUE;    CK_KEY_TYPE     keyType	= CKK_GENERIC_SECRET;    CK_OBJECT_CLASS classType	= CKO_SECRET_KEY;    CK_KEY_DERIVATION_STRING_DATA *stringPtr;    PRBool          isTLS = PR_FALSE;    PRBool          isDH = PR_FALSE;    SECStatus       rv;    int             i;    unsigned int    outLen;    unsigned char   sha_out[SHA1_LENGTH];    unsigned char   key_block[NUM_MIXERS * MD5_LENGTH];    unsigned char   key_block2[MD5_LENGTH];    /*     * now lets create an object to hang the attributes off of     */    if (phKey) *phKey = CK_INVALID_HANDLE;    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) ulAttributeCount; i++) {	crv = pk11_AddAttributeType(key,pk11_attr_expand(&pTemplate[i]));	if (crv != CKR_OK) break;	if (pTemplate[i].type == CKA_KEY_TYPE) {	    keyType = *(CK_KEY_TYPE *)pTemplate[i].pValue;	}	if (pTemplate[i].type == CKA_VALUE_LEN) {	    keySize = *(CK_ULONG *)pTemplate[i].pValue;	}    }    if (crv != CKR_OK) { pk11_FreeObject(key); return crv; }    if (keySize == 0) {	keySize = pk11_MapKeySize(keyType);    }    /* Derive can only create SECRET KEY's currently... */    classType = CKO_SECRET_KEY;    crv = pk11_forceAttribute (key,CKA_CLASS,&classType,sizeof(classType));    if (crv != CKR_OK) {	pk11_FreeObject(key);	return crv;    }    /* look up the base key we're deriving with */     session = pk11_SessionFromHandle(hSession);    if (session == NULL) {	pk11_FreeObject(key);        return CKR_SESSION_HANDLE_INVALID;    }    sourceKey = pk11_ObjectFromHandle(hBaseKey,session);    pk11_FreeSession(session);    if (sourceKey == NULL) {	pk11_FreeObject(key);        return CKR_KEY_HANDLE_INVALID;    }    /* don't use key derive to expose sensitive keys */    crv = pk11_DeriveSensitiveCheck(sourceKey,key);    if (crv != CKR_OK) {	pk11_FreeObject(key);	pk11_FreeObject(sourceKey);        return crv;    }    /* get the value of the base key */    att = pk11_FindAttribute(sourceKey,CKA_VALUE);    if (att == NULL) {	pk11_FreeObject(key);	pk11_FreeObject(sourceKey);        return CKR_KEY_HANDLE_INVALID;    }    switch (pMechanism->mechanism) {    /*     * generate the master secret      */    case CKM_TLS_MASTER_KEY_DERIVE:    case CKM_TLS_MASTER_KEY_DERIVE_DH:	isTLS = PR_TRUE;	/* fall thru */    case CKM_SSL3_MASTER_KEY_DERIVE:    case CKM_SSL3_MASTER_KEY_DERIVE_DH:      {	CK_SSL3_MASTER_KEY_DERIVE_PARAMS *ssl3_master;	SSL3RSAPreMasterSecret *rsa_pms;        if ((pMechanism->mechanism == CKM_SSL3_MASTER_KEY_DERIVE_DH) ||            (pMechanism->mechanism == CKM_TLS_MASTER_KEY_DERIVE_DH))		isDH = PR_TRUE;	/* first do the consistancy checks */	if (!isDH && (att->attrib.ulValueLen != SSL3_PMS_LENGTH)) {	    crv = CKR_KEY_TYPE_INCONSISTENT;	    break;	}	att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);	if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=					CKK_GENERIC_SECRET)) {	    if (att2) pk11_FreeAttribute(att2);	    crv = CKR_KEY_FUNCTION_NOT_PERMITTED;	    break;	}	pk11_FreeAttribute(att2);	if (keyType != CKK_GENERIC_SECRET) {	    crv = CKR_KEY_FUNCTION_NOT_PERMITTED;	    break;	}	if ((keySize != 0) && (keySize != SSL3_MASTER_SECRET_LENGTH)) {	    crv = CKR_KEY_FUNCTION_NOT_PERMITTED;	    break;	}	/* finally do the key gen */	ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *)					pMechanism->pParameter;	if (ssl3_master->pVersion) {	    PK11SessionObject *sessKey = pk11_narrowToSessionObject(key);	    rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue;	    /* don't leak more key material then necessary for SSL to work */	    if ((sessKey == NULL) || sessKey->wasDerived) {		ssl3_master->pVersion->major = 0xff;		ssl3_master->pVersion->minor = 0xff;	    } else {		ssl3_master->pVersion->major = rsa_pms->client_version[0];		ssl3_master->pVersion->minor = rsa_pms->client_version[1];	    }	}	if (ssl3_master->RandomInfo.ulClientRandomLen != SSL3_RANDOM_LENGTH) {	   crv = CKR_MECHANISM_PARAM_INVALID;	   break;	}	if (ssl3_master->RandomInfo.ulServerRandomLen != SSL3_RANDOM_LENGTH) {	   crv = CKR_MECHANISM_PARAM_INVALID;	   break;	}        if (isTLS) {	    unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];	    SECItem crsr = { siBuffer, NULL, 0 };	    SECItem master = { siBuffer, NULL, 0 };	    SECItem pms = { siBuffer, NULL, 0 };	    SECStatus status;	    pms.data = (unsigned char*)att->attrib.pValue;	    pms.len = att->attrib.ulValueLen;	    master.data = key_block;	    master.len = SSL3_MASTER_SECRET_LENGTH;	    crsr.data = crsrdata;	    crsr.len = sizeof(crsrdata);	    PORT_Memcpy(crsrdata, ssl3_master->RandomInfo.pClientRandom,							 SSL3_RANDOM_LENGTH);	    PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 		ssl3_master->RandomInfo.pServerRandom, SSL3_RANDOM_LENGTH);	    status = pk11_PRF(&pms, "master secret", &crsr, &master);	    if (status != SECSuccess) {	    	crv = CKR_FUNCTION_FAILED;		break;	    }	} else {	    /* now allocate the hash contexts */	    md5 = MD5_NewContext();	    if (md5 == NULL) { 		crv = CKR_HOST_MEMORY;		break;	    }	    sha = SHA1_NewContext();	    if (sha == NULL) { 		PORT_Free(md5);		crv = CKR_HOST_MEMORY;		break;	    }            for (i = 0; i < 3; i++) {              SHA1_Begin(sha);              SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));              SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 			  att->attrib.ulValueLen);              SHA1_Update(sha, ssl3_master->RandomInfo.pClientRandom,				ssl3_master->RandomInfo.ulClientRandomLen);              SHA1_Update(sha, ssl3_master->RandomInfo.pServerRandom, 				ssl3_master->RandomInfo.ulServerRandomLen);              SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);              PORT_Assert(outLen == SHA1_LENGTH);              MD5_Begin(md5);              MD5_Update(md5, (const unsigned char*)att->attrib.pValue, 			 att->attrib.ulValueLen);              MD5_Update(md5, sha_out, outLen);              MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);              PORT_Assert(outLen == MD5_LENGTH);            }	    PORT_Free(md5);	    PORT_Free(sha);	}	/* store the results */	crv = pk11_forceAttribute			(key,CKA_VALUE,key_block,SSL3_MASTER_SECRET_LENGTH);	if (crv != CKR_OK) break;	keyType = CKK_GENERIC_SECRET;	crv = pk11_forceAttribute (key,CKA_KEY_TYPE,&keyType,sizeof(keyType));	if (isTLS) {	    /* TLS's master secret is used to "sign" finished msgs with PRF. */	    /* XXX This seems like a hack.   But PK11_Derive only accepts 	     * one "operation" argument. */	    crv = pk11_forceAttribute(key,CKA_SIGN,  &cktrue,sizeof(CK_BBOOL));	    if (crv != CKR_OK) break;	    crv = pk11_forceAttribute(key,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL));	    if (crv != CKR_OK) break;	    /* While we're here, we might as well force this, too. */	    crv = pk11_forceAttribute(key,CKA_DERIVE,&cktrue,sizeof(CK_BBOOL));	    if (crv != CKR_OK) break;	}	break;      }    case CKM_TLS_KEY_AND_MAC_DERIVE:	isTLS = PR_TRUE;	/* fall thru */    case CKM_SSL3_KEY_AND_MAC_DERIVE:      {	CK_SSL3_KEY_MAT_PARAMS *ssl3_keys;	CK_SSL3_KEY_MAT_OUT *   ssl3_keys_out;	CK_ULONG                effKeySize;	crv = pk11_DeriveSensitiveCheck(sourceKey,key);	if (crv != CKR_OK) break;	if (att->attrib.ulValueLen != SSL3_MASTER_SECRET_LENGTH) {	    crv = CKR_KEY_FUNCTION_NOT_PERMITTED;	    break;	}	att2 = pk11_FindAttribute(sourceKey,CKA_KEY_TYPE);	if ((att2 == NULL) || (*(CK_KEY_TYPE *)att2->attrib.pValue !=					CKK_GENERIC_SECRET)) {	    if (att2) pk11_FreeAttribute(att2);	    crv = CKR_KEY_FUNCTION_NOT_PERMITTED;	    break;	}	pk11_FreeAttribute(att2);	md5 = MD5_NewContext();	if (md5 == NULL) { 	    crv = CKR_HOST_MEMORY;	    break;	}	sha = SHA1_NewContext();	if (sha == NULL) { 	    PORT_Free(md5);	    crv = CKR_HOST_MEMORY;	    break;	}	ssl3_keys = (CK_SSL3_KEY_MAT_PARAMS *) pMechanism->pParameter;	/*	 * clear out our returned keys so we can recover on failure	 */	ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial;	ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE;	ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE;	ssl3_keys_out->hClientKey       = CK_INVALID_HANDLE;	ssl3_keys_out->hServerKey       = CK_INVALID_HANDLE;	/*	 * generate the key material: This looks amazingly similar to the	 * PMS code, and is clearly crying out for a function to provide it.	 */	if (isTLS) {	    SECStatus     status;	    SECItem       master = { siBuffer, NULL, 0 };	    SECItem       srcr   = { siBuffer, NULL, 0 };	    SECItem       keyblk = { siBuffer, NULL, 0 };	    unsigned char srcrdata[SSL3_RANDOM_LENGTH * 2];	    master.data = (unsigned char*)att->attrib.pValue;	    master.len  = att->attrib.ulValueLen;	    srcr.data   = srcrdata;	    srcr.len    = sizeof srcrdata;	    keyblk.data = key_block;	    keyblk.len  = sizeof key_block;	    PORT_Memcpy(srcrdata, 	                ssl3_keys->RandomInfo.pServerRandom,			SSL3_RANDOM_LENGTH);	    PORT_Memcpy(srcrdata + SSL3_RANDOM_LENGTH, 		        ssl3_keys->RandomInfo.pClientRandom, 			SSL3_RANDOM_LENGTH);	    status = pk11_PRF(&master, "key expansion", &srcr, &keyblk);	    if (status != SECSuccess) {		goto key_and_mac_derive_fail;	    }	} else {	    /* key_block = 	     *     MD5(master_secret + SHA('A' + master_secret + 	     *                      ServerHello.random + ClientHello.random)) +	     *     MD5(master_secret + SHA('BB' + master_secret + 	     *                      ServerHello.random + ClientHello.random)) +	     *     MD5(master_secret + SHA('CCC' + master_secret + 	     *                      ServerHello.random + ClientHello.random)) +	     *     [...];	     */	    for (i = 0; i < NUM_MIXERS; i++) {	      SHA1_Begin(sha);	      SHA1_Update(sha, (unsigned char*) mixers[i], strlen(mixers[i]));	      SHA1_Update(sha, (const unsigned char*)att->attrib.pValue, 			  att->attrib.ulValueLen);              SHA1_Update(sha, ssl3_keys->RandomInfo.pServerRandom, 				ssl3_keys->RandomInfo.ulServerRandomLen);              SHA1_Update(sha, ssl3_keys->RandomInfo.pClientRandom,				ssl3_keys->RandomInfo.ulClientRandomLen);	      SHA1_End(sha, sha_out, &outLen, SHA1_LENGTH);	      PORT_Assert(outLen == SHA1_LENGTH);	      MD5_Begin(md5);	      MD5_Update(md5, (const unsigned char*)att->attrib.pValue,			 att->attrib.ulValueLen);	      MD5_Update(md5, sha_out, outLen);	      MD5_End(md5, &key_block[i*MD5_LENGTH], &outLen, MD5_LENGTH);	      PORT_Assert(outLen == MD5_LENGTH);	    }	}	/*	 * Put the key material where it goes.	 */	i = 0;			/* now shows how much consumed */	macSize    = ssl3_keys->ulMacSizeInBits/8;	effKeySize = ssl3_keys->ulKeySizeInBits/8;	IVSize     = ssl3_keys->ulIVSizeInBits/8;	if (keySize == 0) {	    effKeySize = keySize;	}	/* 	 * The key_block is partitioned as follows:	 * client_write_MAC_secret[CipherSpec.hash_size]	 */	crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,					 &ssl3_keys_out->hClientMacSecret);	if (crv != CKR_OK)	    goto key_and_mac_derive_fail;	i += macSize;	/* 	 * server_write_MAC_secret[CipherSpec.hash_size]	 */	crv = pk11_buildSSLKey(hSession,key,PR_TRUE,&key_block[i],macSize,					    &ssl3_keys_out->hServerMacSecret);	if (crv != CKR_OK) {	    goto key_and_mac_derive_fail;	}	i += macSize;	if (keySize) {	    if (!ssl3_keys->bIsExport) {		/* 		** Generate Domestic write keys and IVs.		** client_write_key[CipherSpec.key_material]		*/		crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],					keySize, &ssl3_keys_out->hClientKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		i += keySize;		/* 		** server_write_key[CipherSpec.key_material]		*/		crv = pk11_buildSSLKey(hSession,key,PR_FALSE,&key_block[i],					keySize, &ssl3_keys_out->hServerKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		i += keySize;		/* 		** client_write_IV[CipherSpec.IV_size]		*/		PORT_Memcpy(ssl3_keys_out->pIVClient, &key_block[i], IVSize);		i += IVSize;		/* 		** server_write_IV[CipherSpec.IV_size]		*/		PORT_Memcpy(ssl3_keys_out->pIVServer, &key_block[i], IVSize);	    	i += IVSize;		PORT_Assert(i <= sizeof key_block);	    } else if (!isTLS) {		/*		** Generate SSL3 Export write keys and IVs.		** client_write_key[CipherSpec.key_material]		** final_client_write_key = MD5(client_write_key +		**                   ClientHello.random + ServerHello.random);		*/		MD5_Begin(md5);		MD5_Update(md5, &key_block[i], effKeySize);            	MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,				ssl3_keys->RandomInfo.ulClientRandomLen);            	MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 				ssl3_keys->RandomInfo.ulServerRandomLen);		MD5_End(md5, key_block2, &outLen, MD5_LENGTH);		i += effKeySize;		crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,				 	keySize,&ssl3_keys_out->hClientKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		/*		** server_write_key[CipherSpec.key_material]		** final_server_write_key = MD5(server_write_key +		**                    ServerHello.random + ClientHello.random);		*/		MD5_Begin(md5);		MD5_Update(md5, &key_block[i], effKeySize);            	MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 				ssl3_keys->RandomInfo.ulServerRandomLen);            	MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,				ssl3_keys->RandomInfo.ulClientRandomLen);		MD5_End(md5, key_block2, &outLen, MD5_LENGTH);		i += effKeySize;		crv = pk11_buildSSLKey(hSession,key,PR_FALSE,key_block2,					 keySize,&ssl3_keys_out->hServerKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		/*		** client_write_IV = 		**	MD5(ClientHello.random + ServerHello.random);		*/		MD5_Begin(md5);            	MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,				ssl3_keys->RandomInfo.ulClientRandomLen);            	MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 				ssl3_keys->RandomInfo.ulServerRandomLen);		MD5_End(md5, key_block2, &outLen, MD5_LENGTH);		PORT_Memcpy(ssl3_keys_out->pIVClient, key_block2, IVSize);		/*		** server_write_IV = 		**	MD5(ServerHello.random + ClientHello.random);		*/		MD5_Begin(md5);            	MD5_Update(md5, ssl3_keys->RandomInfo.pServerRandom, 				ssl3_keys->RandomInfo.ulServerRandomLen);            	MD5_Update(md5, ssl3_keys->RandomInfo.pClientRandom,				ssl3_keys->RandomInfo.ulClientRandomLen);		MD5_End(md5, key_block2, &outLen, MD5_LENGTH);		PORT_Memcpy(ssl3_keys_out->pIVServer, key_block2, IVSize);	    } else {		/*		** Generate TLS Export write keys and IVs.		*/		SECStatus     status;		SECItem       secret = { siBuffer, NULL, 0 };		SECItem       crsr   = { siBuffer, NULL, 0 };		SECItem       keyblk = { siBuffer, NULL, 0 };		unsigned char crsrdata[SSL3_RANDOM_LENGTH * 2];		crsr.data   = crsrdata;		crsr.len    = sizeof crsrdata;		PORT_Memcpy(crsrdata, 		            ssl3_keys->RandomInfo.pClientRandom, 			    SSL3_RANDOM_LENGTH);		PORT_Memcpy(crsrdata + SSL3_RANDOM_LENGTH, 			    ssl3_keys->RandomInfo.pServerRandom,			    SSL3_RANDOM_LENGTH);		/*		** client_write_key[CipherSpec.key_material]		** final_client_write_key = PRF(client_write_key, 		**                              "client write key",		**                              client_random + server_random);		*/		secret.data = &key_block[i];		secret.len  = effKeySize;		i          += effKeySize;		keyblk.data = key_block2;		keyblk.len  = sizeof key_block2;		status = pk11_PRF(&secret, "client write key", &crsr, &keyblk);		if (status != SECSuccess) {		    goto key_and_mac_derive_fail;		}		crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2, 				       keySize, &ssl3_keys_out->hClientKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		/*		** server_write_key[CipherSpec.key_material]		** final_server_write_key = PRF(server_write_key,		**                              "server write key",		**                              client_random + server_random);		*/		secret.data = &key_block[i];		secret.len  = effKeySize;		i          += effKeySize;		keyblk.data = key_block2;		keyblk.len  = sizeof key_block2;		status = pk11_PRF(&secret, "server write key", &crsr, &keyblk);		if (status != SECSuccess) {		    goto key_and_mac_derive_fail;		}		crv = pk11_buildSSLKey(hSession, key, PR_FALSE, key_block2, 				       keySize, &ssl3_keys_out->hServerKey);		if (crv != CKR_OK) {		    goto key_and_mac_derive_fail;		}		/*		** iv_block = PRF("", "IV block", 		**                    client_random + server_random);		** client_write_IV[SecurityParameters.IV_size]		** server_write_IV[SecurityParameters.IV_size]		*/		if (IVSize) {		    secret.data = NULL;		    secret.len  = 0;		    keyblk.data = &key_block[i];		    keyblk.len  = 2 * IVSize;		    status = pk11_PRF(&secret, "IV block", &crsr, &keyblk);		    if (status != SECSuccess) {			goto key_and_mac_derive_fail;		    }		    PORT_Memcpy(ssl3_keys_out->pIVClient, keyblk.data, IVSize);		    PORT_Memcpy(ssl3_keys_out->pIVServer, keyblk.data + IVSize,                                IVSize);		}	    }	}	crv = CKR_OK;	if (0) {key_and_mac_derive_fail:	    if (crv == CKR_OK)	    	crv = CKR_FUNCTION_FAILED;	    pk11_freeSSLKeys(hSession, ssl3_keys_out);	}	MD5_DestroyContext(md5, PR_TRUE);	SHA1_DestroyContext(sha, PR_TRUE);	pk11_FreeObject(key);	key = NULL;	break;      }    case CKM_CONCATENATE_BASE_AND_KEY:      {	PK11Object *newKey;	crv = pk11_DeriveSensitiveCheck(sourceKey,key);	if (crv != CKR_OK) break;	session = pk11_SessionFromHandle(hSession);	if (session == NULL) {            crv = CKR_SESSION_HANDLE_INVALID;	    break;    	}	newKey = pk11_ObjectFromHandle(*(CK_OBJECT_HANDLE *)					pMechanism->pParameter,session);	pk11_FreeSession(session);	if ( newKey == NULL) {            crv = CKR_KEY_HANDLE_INVALID;	    break;	}	if (pk11_isTrue(newKey,CKA_SENSITIVE)) {	    crv = pk11_forceAttribute(newKey,CKA_SENSITIVE,&cktrue,							sizeof(CK_BBOOL));	    if (crv != CKR_OK) {		pk11_FreeObject(newKey);		break;	    }	}	att2 = pk11_FindAttribute(newKey,CKA_VALUE);	if (att2 == NULL) {	    pk11_FreeObject(newKey);            crv = CKR_KEY_HANDLE_INVALID;	    break;	}	tmpKeySize = att->attrib.ulValueLen+att2->attrib.ulValueLen;	if (keySize == 0) keySize = tmpKeySize;	if (keySize > tmpKeySize) {	    pk11_FreeObject(newKey);	    pk11_FreeAttribute(att2);	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	buf = (unsigned char*)PORT_Alloc(tmpKeySize);	if (buf == NULL) {	    pk11_FreeAttribute(att2);	    pk11_FreeObject(newKey);	    crv = CKR_HOST_MEMORY;		    break;	}	PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);	PORT_Memcpy(buf+att->attrib.ulValueLen,				att2->attrib.pValue,att2->attrib.ulValueLen);	crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);	PORT_ZFree(buf,tmpKeySize);	pk11_FreeAttribute(att2);	pk11_FreeObject(newKey);	break;      }    case CKM_CONCATENATE_BASE_AND_DATA:	stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;	tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;	if (keySize == 0) keySize = tmpKeySize;	if (keySize > tmpKeySize) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	buf = (unsigned char*)PORT_Alloc(tmpKeySize);	if (buf == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	PORT_Memcpy(buf,att->attrib.pValue,att->attrib.ulValueLen);	PORT_Memcpy(buf+att->attrib.ulValueLen,stringPtr->pData,							stringPtr->ulLen);	crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);	PORT_ZFree(buf,tmpKeySize);	break;    case CKM_CONCATENATE_DATA_AND_BASE:	stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;	tmpKeySize = att->attrib.ulValueLen+stringPtr->ulLen;	if (keySize == 0) keySize = tmpKeySize;	if (keySize > tmpKeySize) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	buf = (unsigned char*)PORT_Alloc(tmpKeySize);	if (buf == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	PORT_Memcpy(buf,stringPtr->pData,stringPtr->ulLen);	PORT_Memcpy(buf+stringPtr->ulLen,att->attrib.pValue,							att->attrib.ulValueLen);	crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);	PORT_ZFree(buf,tmpKeySize);	break;    case CKM_XOR_BASE_AND_DATA:	stringPtr = (CK_KEY_DERIVATION_STRING_DATA *)pMechanism->pParameter;	tmpKeySize = PR_MIN(att->attrib.ulValueLen,stringPtr->ulLen);	if (keySize == 0) keySize = tmpKeySize;	if (keySize > tmpKeySize) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	buf = (unsigned char*)PORT_Alloc(keySize);	if (buf == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}		PORT_Memcpy(buf,att->attrib.pValue,keySize);	for (i=0; i < (int)keySize; i++) {	    buf[i] ^= stringPtr->pData[i];	}	crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);	PORT_ZFree(buf,keySize);	break;    case CKM_EXTRACT_KEY_FROM_KEY:      {	/* the following assumes 8 bits per byte */	CK_ULONG extract = *(CK_EXTRACT_PARAMS *)pMechanism->pParameter;	CK_ULONG shift   = extract & 0x7;      /* extract mod 8 the fast way */	CK_ULONG offset  = extract >> 3;       /* extract div 8 the fast way */	if (keySize == 0)  {	    crv = CKR_TEMPLATE_INCOMPLETE;	    break;	}	/* make sure we have enough bits in the original key */	if (att->attrib.ulValueLen < 			(offset + keySize + ((shift != 0)? 1 :0)) ) {	    crv = CKR_MECHANISM_PARAM_INVALID;	    break;	}	buf = (unsigned char*)PORT_Alloc(keySize);	if (buf == NULL) {	    crv = CKR_HOST_MEMORY;	    break;	}	/* copy the bits we need into the new key */		for (i=0; i < (int)keySize; i++) {	    unsigned char *value =			 ((unsigned char *)att->attrib.pValue)+offset+i;	    if (shift) {	        buf[i] = (value[0] << (shift)) | (value[1] >> (8 - shift));	    } else {		buf[i] = value[0];	    }	}	crv = pk11_forceAttribute (key,CKA_VALUE,buf,keySize);	PORT_ZFree(buf,keySize);	break;      }    case CKM_MD2_KEY_DERIVATION:	if (keySize == 0) keySize = MD2_LENGTH;	if (keySize > MD2_LENGTH) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	/* now allocate the hash contexts */	md2 = MD2_NewContext();	if (md2 == NULL) { 	    crv = CKR_HOST_MEMORY;	    break;	}	MD2_Begin(md2);	MD2_Update(md2,(const unsigned char*)att->attrib.pValue,		   att->attrib.ulValueLen);	MD2_End(md2,key_block,&outLen,MD2_LENGTH);	MD2_DestroyContext(md2, PR_TRUE);	crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);	break;    case CKM_MD5_KEY_DERIVATION:	if (keySize == 0) keySize = MD5_LENGTH;	if (keySize > MD5_LENGTH) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	/* now allocate the hash contexts */	md5 = MD5_NewContext();	if (md5 == NULL) { 	    crv = CKR_HOST_MEMORY;	    break;	}	MD5_Begin(md5);	MD5_Update(md5,(const unsigned char*)att->attrib.pValue,		   att->attrib.ulValueLen);	MD5_End(md5,key_block,&outLen,MD5_LENGTH);	MD5_DestroyContext(md5, PR_TRUE);	crv = pk11_forceAttribute (key,CKA_VALUE,key_block,keySize);	break;     case CKM_SHA1_KEY_DERIVATION:	if (keySize == 0) keySize = SHA1_LENGTH;	if (keySize > SHA1_LENGTH) {	    crv = CKR_TEMPLATE_INCONSISTENT;	    break;	}	/* now allocate the hash contexts */	sha = SHA1_NewContext();	if (sha == NULL) { 	    crv = CKR_HOST_MEMORY;	    break;	}	SHA1_Begin(sha);	SHA1_Update(sha,(const unsigned char*)att->attrib.pValue,		    att->attrib.ulValueLen);	SHA1_End(sha,key_block,&outLen,SHA1_LENGTH);	SHA1_DestroyContext(sha, PR_TRUE);	crv = pk11_forceAttribute(key,CKA_VALUE,key_block,keySize);	break;    case CKM_DH_PKCS_DERIVE:      {	SECItem  derived,  dhPublic;	SECItem  dhPrime,  dhValue;	/* sourceKey - values for the local existing low key */	/* get prime and value attributes */	crv = pk11_Attribute2SecItem(NULL, &dhPrime, sourceKey, CKA_PRIME); 	if (crv != SECSuccess) break;	crv = pk11_Attribute2SecItem(NULL, &dhValue, sourceKey, CKA_VALUE); 	if (crv != SECSuccess) { 	    PORT_Free(dhPrime.data);	    break;	}	dhPublic.data = pMechanism->pParameter;	dhPublic.len  = pMechanism->ulParameterLen;	/* calculate private value - oct */	rv = DH_Derive(&dhPublic, &dhPrime, &dhValue, &derived, keySize); 	PORT_Free(dhPrime.data);	PORT_Free(dhValue.data);     	if (rv == SECSuccess) {	    pk11_forceAttribute(key, CKA_VALUE, derived.data, derived.len);	    PORT_ZFree(derived.data, derived.len);	} else	    crv = CKR_HOST_MEMORY;	    	break;      }    default:	crv = CKR_MECHANISM_INVALID;    }    pk11_FreeAttribute(att);    pk11_FreeObject(sourceKey);    if (crv != CKR_OK) { 	if (key) pk11_FreeObject(key);	return crv;    }    /* link the key object into the list */    if (key) {	PK11SessionObject *sessKey = pk11_narrowToSessionObject(key);	PORT_Assert(sessKey);	/* get the session */	sessKey->wasDerived = PR_TRUE;	session = pk11_SessionFromHandle(hSession);	if (session == NULL) {	    pk11_FreeObject(key);	    return CKR_HOST_MEMORY;	}	crv = pk11_handleObject(key,session);	pk11_FreeSession(session);	*phKey = key->handle;	pk11_FreeObject(key);    }    return crv;}