ss->ssl3->hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
ss->ssl3.hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;
ssl3_HandleClientKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length){    SECKEYPrivateKey *serverKey         = NULL;    SECStatus         rv;const ssl3KEADef *    kea_def;#ifdef NSS_ENABLE_ECC    SECKEYPublicKey *serverPubKey       = NULL;#endif /* NSS_ENABLE_ECC */    SSL_TRC(3, ("%d: SSL3[%d]: handle client_key_exchange handshake",		SSL_GETPID(), ss->fd));    PORT_Assert( ssl_HaveRecvBufLock(ss) );    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );    if (ss->ssl3->hs.ws != wait_client_key) {	SSL3_SendAlert(ss, alert_fatal, unexpected_message);    	PORT_SetError(SSL_ERROR_RX_UNEXPECTED_CLIENT_KEY_EXCH);	return SECFailure;    }    kea_def   = ss->ssl3->hs.kea_def;#ifdef NSS_ENABLE_ECC    /* XXX Using SSLKEAType to index server certifiates     * does not work for (EC)DHE ciphers. Until we have     * an indexing mechanism general enough for all key     * exchange algorithms, we'll need to deal with each     * one seprately.     */    if ((kea_def->kea == kea_ecdhe_rsa) ||	(kea_def->kea == kea_ecdhe_ecdsa)) {	    if (ss->ephemeralECDHKeyPair != NULL) {		    serverKey = ss->ephemeralECDHKeyPair->privKey;		    ss->sec.keaKeyBits = 			SECKEY_PublicKeyStrengthInBits(ss->ephemeralECDHKeyPair->pubKey);	    }    } else {#endif /* NSS_ENABLE_ECC */    serverKey =  (ss->ssl3->hs.usedStepDownKey#ifdef DEBUG		 && kea_def->is_limited /* XXX OR cert is signing only */		 && kea_def->exchKeyType == kt_rsa 		 && ss->stepDownKeyPair != NULL#endif		 ) ? ss->stepDownKeyPair->privKey		   : ss->serverCerts[kea_def->exchKeyType].serverKey;    if (ss->ssl3->hs.usedStepDownKey#ifdef DEBUG	 && kea_def->is_limited /* XXX OR cert is signing only */	 && kea_def->exchKeyType == kt_rsa 	 && ss->stepDownKeyPair != NULL#endif	 ) {     	serverKey = ss->stepDownKeyPair->privKey;	ss->sec.keaKeyBits = EXPORT_RSA_KEY_LENGTH * BPB;    } else {	sslServerCerts * sc = ss->serverCerts + kea_def->exchKeyType;	serverKey           = sc->serverKey;	ss->sec.keaKeyBits = sc->serverKeyBits;    }#ifdef NSS_ENABLE_ECC    }#endif /* NSS_ENABLE_ECC */    if (serverKey == NULL) {    	SEND_ALERT	PORT_SetError(SSL_ERROR_NO_SERVER_KEY_FOR_ALG);	return SECFailure;    }    ss->sec.keaType    = kea_def->exchKeyType;    switch (kea_def->exchKeyType) {    case kt_rsa:	rv = ssl3_HandleRSAClientKeyExchange(ss, b, length, serverKey);	if (rv != SECSuccess) {	    SEND_ALERT	    return SECFailure;	/* error code set by ssl3_InitPendingCipherSpec */	}	break;#ifdef NSS_ENABLE_ECC    case kt_ecdh:        /* XXX We really ought to be able to store multiple	 * EC certs (a requirement if we wish to support both	 * ECDH-RSA and ECDH-ECDSA key exchanges concurrently).	 * When we make that change, we'll need an index other	 * than kt_ecdh to pick the right EC certificate.	 */        if (((kea_def->kea == kea_ecdhe_ecdsa) ||	     (kea_def->kea == kea_ecdhe_rsa)) &&	    (ss->ephemeralECDHKeyPair != NULL)) {	    serverPubKey = ss->ephemeralECDHKeyPair->pubKey;	} else {	    serverPubKey = CERT_ExtractPublicKey(			   ss->serverCerts[kt_ecdh].serverCert);        }	if (serverPubKey == NULL) {	    /* XXX Is this the right error code? */	    PORT_SetError(SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE);	    return SECFailure;	}	rv = ssl3_HandleECDHClientKeyExchange(ss, b, length, 					      serverPubKey, serverKey);	if (rv != SECSuccess) {	    return SECFailure;	/* error code set */	}	break;#endif /* NSS_ENABLE_ECC */    default:	(void) ssl3_HandshakeFailure(ss);	PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);	return SECFailure;    }    ss->ssl3->hs.ws = ss->sec.peerCert ? wait_cert_verify : wait_change_cipher;    return SECSuccess;}