if (ssl3->hs.kea_def->kea == kea_ecdhe_rsa) {
if (ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa) {
ssl3_HandleFinished(sslSocket *ss, SSL3Opaque *b, PRUint32 length,		    const SSL3Hashes *hashes){    ssl3State *       ssl3	   = ss->ssl3;    sslSessionID *    sid	   = ss->sec.ci.sid;    PK11SymKey *      wrappingKey  = NULL;    PK11SlotInfo *    symKeySlot;    void *            pwArg        = ss->pkcs11PinArg;    SECStatus         rv;    PRBool            isServer     = ss->sec.isServer;    PRBool            isTLS;    PRBool            doStepUp;    CK_MECHANISM_TYPE mechanism    = CKM_INVALID_MECHANISM;    SSL3KEAType       effectiveExchKeyType;    PORT_Assert( ssl_HaveRecvBufLock(ss) );    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );    SSL_TRC(3, ("%d: SSL3[%d]: handle finished handshake",    	SSL_GETPID(), ss->fd));    if (ssl3->hs.ws != wait_finished) {	SSL3_SendAlert(ss, alert_fatal, unexpected_message);    	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_FINISHED);	return SECFailure;    }    isTLS = (PRBool)(ssl3->crSpec->version > SSL_LIBRARY_VERSION_3_0);    if (isTLS) {	TLSFinished tlsFinished;	if (length != sizeof tlsFinished) {	    (void)SSL3_SendAlert(ss, alert_fatal, decode_error);	    PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);	    return SECFailure;	}	rv = ssl3_ComputeTLSFinished(ssl3->crSpec, !isServer, 	                             hashes, &tlsFinished);	if (rv != SECSuccess ||	    0 != PORT_Memcmp(&tlsFinished, b, length)) {	    (void)SSL3_SendAlert(ss, alert_fatal, decrypt_error);	    PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);	    return SECFailure;	}    } else {	if (length != sizeof(SSL3Hashes)) {	    (void)ssl3_IllegalParameter(ss);	    PORT_SetError(SSL_ERROR_RX_MALFORMED_FINISHED);	    return SECFailure;	}	if (0 != PORT_Memcmp(hashes, b, length)) {	    (void)ssl3_HandshakeFailure(ss);	    PORT_SetError(SSL_ERROR_BAD_HANDSHAKE_HASH_VALUE);	    return SECFailure;	}    }    doStepUp = (PRBool)(!isServer && ssl3->hs.rehandshake);    ssl_GetXmitBufLock(ss);	/*************************************/    if ((isServer && !ssl3->hs.isResuming) ||	(!isServer && ssl3->hs.isResuming)) {	PRInt32 flags = 0;	rv = ssl3_SendChangeCipherSpecs(ss);	if (rv != SECSuccess) {	    goto xmit_loser;	/* err is set. */	}	/* If this thread is in SSL_SecureSend (trying to write some data) 	** or if it is going to step up, 	** then set the ssl_SEND_FLAG_FORCE_INTO_BUFFER flag, so that the 	** last two handshake messages (change cipher spec and finished) 	** will be sent in the same send/write call as the application data.	*/	if (doStepUp || ss->writerThread == PR_GetCurrentThread()) {	    flags = ssl_SEND_FLAG_FORCE_INTO_BUFFER;	}	rv = ssl3_SendFinished(ss, flags);	if (rv != SECSuccess) {	    goto xmit_loser;	/* err is set. */	}    }    /* Optimization: don't cache this connection if we're going to step up. */    if (doStepUp) {	ssl_FreeSID(sid);	ss->sec.ci.sid     = sid = NULL;	ssl3->hs.rehandshake = PR_FALSE;	rv = ssl3_SendClientHello(ss);xmit_loser:	ssl_ReleaseXmitBufLock(ss);	return rv;	/* err code is set if appropriate. */    }    ssl_ReleaseXmitBufLock(ss);	/*************************************/    /* The first handshake is now completed. */    ss->handshake           = NULL;    ss->firstHsDone         = PR_TRUE;    ss->gs.writeOffset = 0;    ss->gs.readOffset  = 0;    if (ssl3->hs.kea_def->kea == kea_ecdhe_rsa) {	effectiveExchKeyType = kt_rsa;    } else {	effectiveExchKeyType = ssl3->hs.kea_def->exchKeyType;    }  if (sid->cached == never_cached) {    /* fill in the sid */    sid->u.ssl3.cipherSuite = ssl3->hs.cipher_suite;    sid->u.ssl3.compression = ssl3->hs.compression;    sid->u.ssl3.policy      = ssl3->policy;    sid->u.ssl3.exchKeyType = effectiveExchKeyType;    sid->version            = ss->version;    sid->authAlgorithm      = ss->sec.authAlgorithm;    sid->authKeyBits        = ss->sec.authKeyBits;    sid->keaType            = ss->sec.keaType;    sid->keaKeyBits         = ss->sec.keaKeyBits;    sid->lastAccessTime     = sid->creationTime = ssl_Time();    sid->expirationTime     = sid->creationTime + ssl3_sid_timeout;    sid->localCert          = CERT_DupCertificate(ss->sec.localCert);    ssl_GetSpecReadLock(ss);	/*************************************/    symKeySlot = PK11_GetSlotFromKey(ssl3->crSpec->master_secret);    if (!isServer) {	int  wrapKeyIndex;	int  incarnation;	/* these next few functions are mere accessors and don't fail. */	sid->u.ssl3.masterWrapIndex  = wrapKeyIndex =				       PK11_GetCurrentWrapIndex(symKeySlot);	PORT_Assert(wrapKeyIndex == 0);	/* array has only one entry! */	sid->u.ssl3.masterWrapSeries = incarnation =				       PK11_GetSlotSeries(symKeySlot);	sid->u.ssl3.masterSlotID   = PK11_GetSlotID(symKeySlot);	sid->u.ssl3.masterModuleID = PK11_GetModuleID(symKeySlot);	sid->u.ssl3.masterValid    = PR_TRUE;	/* Get the default wrapping key, for wrapping the master secret before	 * placing it in the SID cache entry. */	wrappingKey = PK11_GetWrapKey(symKeySlot, wrapKeyIndex,				      CKM_INVALID_MECHANISM, incarnation,				      pwArg);	if (wrappingKey) {	    mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */	} else {	    int keyLength;	    /* if the wrappingKey doesn't exist, attempt to create it.	     * Note: we intentionally ignore errors here.  If we cannot	     * generate a wrapping key, it is not fatal to this SSL connection,	     * but we will not be able to restart this session.	     */	    mechanism = PK11_GetBestWrapMechanism(symKeySlot);	    keyLength = PK11_GetBestKeyLength(symKeySlot, mechanism);	    /* Zero length means fixed key length algorithm, or error.	     * It's ambiguous.	     */	    wrappingKey = PK11_KeyGen(symKeySlot, mechanism, NULL,                                      keyLength, pwArg);	    if (wrappingKey) {	    	PK11_SetWrapKey(symKeySlot, wrapKeyIndex, wrappingKey);	    }	}    } else if (!ss->noCache) {	/* server socket using session cache. */	mechanism = PK11_GetBestWrapMechanism(symKeySlot);	if (mechanism != CKM_INVALID_MECHANISM) {	    wrappingKey =	    	getWrappingKey(ss, symKeySlot, effectiveExchKeyType,			       mechanism, pwArg);	    if (wrappingKey) {		mechanism = PK11_GetMechanism(wrappingKey); /* can't fail. */	    }	}    }    sid->u.ssl3.masterWrapMech = mechanism;    PK11_FreeSlot(symKeySlot);    rv = SECFailure;    if (wrappingKey) {	SECItem msItem;	msItem.data = sid->u.ssl3.keys.wrapped_master_secret;	msItem.len  = sizeof sid->u.ssl3.keys.wrapped_master_secret;	rv = PK11_WrapSymKey(mechanism, NULL, wrappingKey,			     ssl3->crSpec->master_secret, &msItem);	/* rv is examined below. */	sid->u.ssl3.keys.wrapped_master_secret_len = msItem.len;	PK11_FreeSymKey(wrappingKey);    }    ssl_ReleaseSpecReadLock(ss);  /*************************************/    /* If the wrap failed, we don't cache the sid.     * The connection continues normally however.     */    if (!ss->noCache && rv == SECSuccess) {	if (ss->sec.cache) {	    (*ss->sec.cache)(sid);    	} else {	    PORT_SetError(SSL_ERROR_SERVER_CACHE_NOT_CONFIGURED);	    return SECFailure;	}    }  }    ss->ssl3->hs.ws = idle_handshake;    /* Do the handshake callback for sslv3 here. */    if (ss->handshakeCallback != NULL) {	(ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);    }    return SECSuccess;}