if (pms != NULL) { CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;
if (pms || !pwSpec->master_secret) {
ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms){    ssl3CipherSpec *         pwSpec     = ss->ssl3->pwSpec;    const ssl3BulkCipherDef *cipher_def = pwSpec->cipher_def;    const ssl3KEADef *       kea_def    = ss->ssl3->hs.kea_def;    unsigned char *   cr     = (unsigned char *)&ss->ssl3->hs.client_random;    unsigned char *   sr     = (unsigned char *)&ss->ssl3->hs.server_random;    PK11SymKey *      symKey = NULL;    PK11SlotInfo *    slot   = NULL;    void *            pwArg  = ss->pkcs11PinArg;    PRBool            isTLS  = (PRBool)(kea_def->tls_keygen ||                                (pwSpec->version > SSL_LIBRARY_VERSION_3_0));    PRBool            skipKeysAndIVs = (PRBool)    					((cipher_def->calg == calg_fortezza) ||					 (cipher_def->calg == calg_null));    CK_MECHANISM_TYPE master_derive;    CK_MECHANISM_TYPE key_derive;    CK_MECHANISM_TYPE bulk_mechanism;    SECItem           params;    int               keySize;    CK_FLAGS          keyFlags;    CK_SSL3_KEY_MAT_PARAMS key_material_params;    CK_SSL3_KEY_MAT_OUT    returnedKeys;    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss));    PORT_Assert( ssl_HaveSpecWriteLock(ss));    PORT_Assert(ss->ssl3->prSpec == ss->ssl3->pwSpec);    if (isTLS) {	master_derive = CKM_TLS_MASTER_KEY_DERIVE;	key_derive    = CKM_TLS_KEY_AND_MAC_DERIVE;	keyFlags      = CKF_SIGN | CKF_VERIFY;    } else {	master_derive = CKM_SSL3_MASTER_KEY_DERIVE;	key_derive    = CKM_SSL3_KEY_AND_MAC_DERIVE;	keyFlags      = 0;    }    if (pms != NULL) {	CK_SSL3_MASTER_KEY_DERIVE_PARAMS master_params;	/* XXX We're supposed to check the version numbers.	** How can we do that with PKCS#11 ??	*/	master_params.pVersion                     = NULL;	master_params.RandomInfo.pClientRandom     = cr;	master_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;	master_params.RandomInfo.pServerRandom     = sr;	master_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;	params.data = (unsigned char *) &master_params;	params.len  = sizeof(master_params);	pwSpec->master_secret = PK11_DeriveWithFlags((PK11SymKey *)pms, 					master_derive, &params, key_derive, 					CKA_DERIVE, 0, keyFlags);	if (pwSpec->master_secret == NULL) {	    /* Generate a faux master secret in the same slot as the old one. */	    PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms);	    PK11SymKey *   fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);	    PK11_FreeSlot(slot);	    if (fpms != NULL) {		pwSpec->master_secret = PK11_DeriveWithFlags(fpms, 					master_derive, &params, key_derive, 					CKA_DERIVE, 0, keyFlags);		PK11_FreeSymKey(fpms);	    }	}    }    if (pwSpec->master_secret == NULL) {	/* Generate a faux master secret from the internal slot. */	PK11SlotInfo *  slot = PK11_GetInternalSlot();	PK11SymKey *    fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot);	PK11_FreeSlot(slot);	if (fpms != NULL) {	    pwSpec->master_secret = PK11_DeriveWithFlags(fpms, 					master_derive, &params, key_derive, 					CKA_DERIVE, 0, keyFlags);	    if (pwSpec->master_secret == NULL) {	    	pwSpec->master_secret = fpms; /* use the fpms as the master. */		fpms = NULL;	    }	}	if (fpms) {	    PK11_FreeSymKey(fpms);    	}    }    if (pwSpec->master_secret == NULL) {	ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);	return SECFailure;    }    /*     * generate the key material     */    key_material_params.ulMacSizeInBits = pwSpec->mac_size           * BPB;    key_material_params.ulKeySizeInBits = cipher_def->secret_key_size* BPB;    key_material_params.ulIVSizeInBits  = cipher_def->iv_size        * BPB;    key_material_params.bIsExport = (CK_BBOOL)(kea_def->is_limited);    /* was:	(CK_BBOOL)(cipher_def->keygen_mode != kg_strong); */    key_material_params.RandomInfo.pClientRandom     = cr;    key_material_params.RandomInfo.ulClientRandomLen = SSL3_RANDOM_LENGTH;    key_material_params.RandomInfo.pServerRandom     = sr;    key_material_params.RandomInfo.ulServerRandomLen = SSL3_RANDOM_LENGTH;    key_material_params.pReturnedKeyMaterial         = &returnedKeys;    returnedKeys.pIVClient = pwSpec->client.write_iv;    returnedKeys.pIVServer = pwSpec->server.write_iv;    keySize                = cipher_def->key_size;    if (skipKeysAndIVs) {	keySize                             = 0;        key_material_params.ulKeySizeInBits = 0;        key_material_params.ulIVSizeInBits  = 0;    	returnedKeys.pIVClient              = NULL;    	returnedKeys.pIVServer              = NULL;    }    bulk_mechanism = (CK_MECHANISM_TYPE) cipher_def->calg;    params.data    = (unsigned char *)&key_material_params;    params.len     = sizeof(key_material_params);    /* CKM_SSL3_KEY_AND_MAC_DERIVE is defined to set ENCRYPT, DECRYPT, and     * DERIVE by DEFAULT */    symKey = PK11_Derive(pwSpec->master_secret, key_derive, &params,                         bulk_mechanism, CKA_ENCRYPT, keySize);    if (!symKey) {	ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);	return SECFailure;    }    /* we really should use the actual mac'ing mechanism here, but we     * don't because these types are used to map keytype anyway and both     * mac's map to the same keytype.     */    slot  = PK11_GetSlotFromKey(symKey);    PK11_FreeSlot(slot); /* slot is held until the key is freed */    pwSpec->client.write_mac_key =    	PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,	    CKM_SSL3_SHA1_MAC, returnedKeys.hClientMacSecret, PR_TRUE, pwArg);    if (pwSpec->client.write_mac_key == NULL ) {	goto loser;	/* loser sets err */    }    pwSpec->server.write_mac_key =    	PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,	    CKM_SSL3_SHA1_MAC, returnedKeys.hServerMacSecret, PR_TRUE, pwArg);    if (pwSpec->server.write_mac_key == NULL ) {	goto loser;	/* loser sets err */    }    if (!skipKeysAndIVs) {	pwSpec->client.write_key =		PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,		     bulk_mechanism, returnedKeys.hClientKey, PR_TRUE, pwArg);	if (pwSpec->client.write_key == NULL ) {	    goto loser;	/* loser sets err */	}	pwSpec->server.write_key =		PK11_SymKeyFromHandle(slot, symKey, PK11_OriginDerive,		     bulk_mechanism, returnedKeys.hServerKey, PR_TRUE, pwArg);	if (pwSpec->server.write_key == NULL ) {	    goto loser;	/* loser sets err */	}    }    PK11_FreeSymKey(symKey);    return SECSuccess;loser:    if (symKey) PK11_FreeSymKey(symKey);    ssl_MapLowLevelError(SSL_ERROR_SESSION_KEY_GEN_FAILURE);    return SECFailure;}