PORT_Assert( ssl_HaveRecvBufLock(ss) ); PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );
PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
ssl3_HandleServerHello(sslSocket *ss, SSL3Opaque *b, PRUint32 length){    sslSessionID *sid		= ss->sec.ci.sid;    PRInt32       temp;		/* allow for consume number failure */    PRBool        suite_found   = PR_FALSE;    int           i;    int           errCode	= SSL_ERROR_RX_MALFORMED_SERVER_HELLO;    SECStatus     rv;    SECItem       sidBytes 	= {siBuffer, NULL, 0};    PRBool        sid_match;    PRBool        isTLS		= PR_FALSE;    SSL3AlertDescription desc   = illegal_parameter;    SSL3ProtocolVersion version;    SSL_TRC(3, ("%d: SSL3[%d]: handle server_hello handshake",    	SSL_GETPID(), ss->fd));    PORT_Assert( ssl_HaveRecvBufLock(ss) );    PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) );    rv = ssl3_InitState(ss);    if (rv != SECSuccess) {	errCode = PORT_GetError(); /* ssl3_InitState has set the error code. */	goto alert_loser;    }    if (ss->ssl3->hs.ws != wait_server_hello) {        errCode = SSL_ERROR_RX_UNEXPECTED_SERVER_HELLO;	desc    = unexpected_message;	goto alert_loser;    }    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);    if (temp < 0) {    	goto loser; 	/* alert has been sent */    }    version = (SSL3ProtocolVersion)temp;    /* this is appropriate since the negotiation is complete, and we only    ** know SSL 3.x.    */    if (MSB(version) != MSB(SSL_LIBRARY_VERSION_3_0)) {    	desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure;	goto alert_loser;    }    rv = ssl3_NegotiateVersion(ss, version);    if (rv != SECSuccess) {    	desc = (version > SSL_LIBRARY_VERSION_3_0) ? protocol_version : handshake_failure;	errCode = SSL_ERROR_NO_CYPHER_OVERLAP;	goto alert_loser;    }    isTLS = (ss->version > SSL_LIBRARY_VERSION_3_0);    rv = ssl3_ConsumeHandshake(	ss, &ss->ssl3->hs.server_random, SSL3_RANDOM_LENGTH, &b, &length);    if (rv != SECSuccess) {    	goto loser; 	/* alert has been sent */    }    rv = ssl3_ConsumeHandshakeVariable(ss, &sidBytes, 1, &b, &length);    if (rv != SECSuccess) {    	goto loser; 	/* alert has been sent */    }    if (sidBytes.len > SSL3_SESSIONID_BYTES) {	if (isTLS)	    desc = decode_error;	goto alert_loser;	/* malformed. */    }    /* find selected cipher suite in our list. */    temp = ssl3_ConsumeHandshakeNumber(ss, 2, &b, &length);    if (temp < 0) {    	goto loser; 	/* alert has been sent */    }    ssl3_config_match_init(ss);    for (i = 0; i < ssl_V3_SUITES_IMPLEMENTED; i++) {	ssl3CipherSuiteCfg *suite = &ss->cipherSuites[i];	if ((temp == suite->cipher_suite) &&	    (config_match(suite, ss->ssl3->policy, PR_TRUE))) {	    suite_found = PR_TRUE;	    break;	/* success */	}    }    if (!suite_found) {    	desc    = handshake_failure;	errCode = SSL_ERROR_NO_CYPHER_OVERLAP;	goto alert_loser;    }    ss->ssl3->hs.cipher_suite = (ssl3CipherSuite)temp;    ss->ssl3->hs.suite_def    = ssl_LookupCipherSuiteDef((ssl3CipherSuite)temp);    PORT_Assert(ss->ssl3->hs.suite_def);    if (!ss->ssl3->hs.suite_def) {    	PORT_SetError(errCode = SEC_ERROR_LIBRARY_FAILURE);	goto loser;	/* we don't send alerts for our screw-ups. */    }    /* find selected compression method in our list. */    temp = ssl3_ConsumeHandshakeNumber(ss, 1, &b, &length);    if (temp < 0) {    	goto loser; 	/* alert has been sent */    }    suite_found = PR_FALSE;    for (i = 0; i < compressionMethodsCount; i++) {	if (temp == compressions[i])  {	    suite_found = PR_TRUE;	    break;	/* success */    	}    }    if (!suite_found) {    	desc    = handshake_failure;	errCode = SSL_ERROR_NO_COMPRESSION_OVERLAP;	goto alert_loser;    }    ss->ssl3->hs.compression = (SSL3CompressionMethod)temp;    if (length != 0) {	/* malformed */	goto alert_loser;    }    /* Any errors after this point are not "malformed" errors. */    desc    = handshake_failure;    /* we need to call ssl3_SetupPendingCipherSpec here so we can check the     * key exchange algorithm. */    rv = ssl3_SetupPendingCipherSpec(ss, ss->ssl3);    if (rv != SECSuccess) {	goto alert_loser;	/* error code is set. */    }    /* We may or may not have sent a session id, we may get one back or     * not and if so it may match the one we sent.     * Attempt to restore the master secret to see if this is so...     * Don't consider failure to find a matching SID an error.     */    sid_match = (PRBool)(sidBytes.len > 0 &&	sidBytes.len == sid->u.ssl3.sessionIDLength &&	!PORT_Memcmp(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len));    if (sid_match &&	sid->version == ss->version &&	sid->u.ssl3.cipherSuite == ss->ssl3->hs.cipher_suite) do {	PK11SlotInfo *slot;	PK11SymKey *  wrapKey;     /* wrapping key */	SECItem       wrappedMS;   /* wrapped master secret. */	CK_FLAGS      keyFlags      = 0;        ss->sec.authAlgorithm = sid->authAlgorithm;	ss->sec.authKeyBits   = sid->authKeyBits;	ss->sec.keaType       = sid->keaType;	ss->sec.keaKeyBits    = sid->keaKeyBits;	slot = SECMOD_LookupSlot(sid->u.ssl3.masterModuleID,	                         sid->u.ssl3.masterSlotID);	if (slot == NULL) {	    break;		/* not considered an error. */	}	if (!PK11_IsPresent(slot)) {	    PK11_FreeSlot(slot);	    break;		/* not considered an error. */	}	wrapKey = PK11_GetWrapKey(slot, sid->u.ssl3.masterWrapIndex,				  sid->u.ssl3.masterWrapMech,				  sid->u.ssl3.masterWrapSeries,				  ss->pkcs11PinArg);	PK11_FreeSlot(slot);	if (wrapKey == NULL) {	    break;		/* not considered an error. */	}	if (ss->version > SSL_LIBRARY_VERSION_3_0) {	/* isTLS */	    keyFlags = CKF_SIGN | CKF_VERIFY;	}        wrappedMS.data = sid->u.ssl3.keys.wrapped_master_secret;	wrappedMS.len  = sid->u.ssl3.keys.wrapped_master_secret_len;	ss->ssl3->pwSpec->master_secret =	    PK11_UnwrapSymKeyWithFlags(wrapKey, sid->u.ssl3.masterWrapMech, 	    		NULL, &wrappedMS, CKM_SSL3_MASTER_KEY_DERIVE,		        CKA_DERIVE, sizeof(SSL3MasterSecret), keyFlags);	errCode = PORT_GetError();	PK11_FreeSymKey(wrapKey);	if (ss->ssl3->pwSpec->master_secret == NULL) {	    break;	/* errorCode set just after call to UnwrapSymKey. */	}	/* Got a Match */	++ssl3stats.hsh_sid_cache_hits;	ss->ssl3->hs.ws         = wait_change_cipher;	ss->ssl3->hs.isResuming = PR_TRUE;	/* copy the peer cert from the SID */	if (sid->peerCert != NULL) {	    ss->sec.peerCert = CERT_DupCertificate(sid->peerCert);	}	/* NULL value for PMS signifies re-use of the old MS */	rv = ssl3_InitPendingCipherSpec(ss,  NULL);	if (rv != SECSuccess) {	    goto alert_loser;	/* err code was set */	}	SECITEM_ZfreeItem(&sidBytes, PR_FALSE);		return SECSuccess;    } while (0);    if (sid_match)	++ssl3stats.hsh_sid_cache_not_ok;    else	++ssl3stats.hsh_sid_cache_misses;    /* throw the old one away */    sid->u.ssl3.resumable = PR_FALSE;    (*ss->sec.uncache)(sid);    ssl_FreeSID(sid);    /* get a new sid */    ss->sec.ci.sid = sid = ssl3_NewSessionID(ss, PR_FALSE);    if (sid == NULL) {	goto alert_loser;	/* memory error is set. */    }    sid->version = ss->version;    sid->u.ssl3.sessionIDLength = sidBytes.len;    PORT_Memcpy(sid->u.ssl3.sessionID, sidBytes.data, sidBytes.len);    SECITEM_ZfreeItem(&sidBytes, PR_FALSE);    ss->ssl3->hs.isResuming = PR_FALSE;    ss->ssl3->hs.ws         = wait_server_cert;    return SECSuccess;alert_loser:    (void)SSL3_SendAlert(ss, alert_fatal, desc);loser:    if (sidBytes.data != NULL)	SECITEM_ZfreeItem(&sidBytes, PR_FALSE);    errCode = ssl_MapLowLevelError(errCode);    return SECFailure;}