提交 86087f9c 编写于 作者: P pkoppula

8074462: Handshake messages can be strictly ordered

Reviewed-by: xuelei
Contributed-by: prasadarao.koppula@oracle.com, sean.coffey@oracle.com
上级 2502b033
......@@ -191,19 +191,24 @@ final class ClientHandshaker extends Handshaker {
*/
@Override
void processMessage(byte type, int messageLen) throws IOException {
if (state >= type
&& (type != HandshakeMessage.ht_hello_request)) {
throw new SSLProtocolException(
"Handshake message sequence violation, " + type);
}
// check the handshake state
List<Byte> ignoredOptStates = handshakeState.check(type);
switch (type) {
case HandshakeMessage.ht_hello_request:
this.serverHelloRequest(new HelloRequest(input));
HelloRequest helloRequest = new HelloRequest(input);
handshakeState.update(helloRequest, resumingSession);
this.serverHelloRequest(helloRequest);
break;
case HandshakeMessage.ht_server_hello:
this.serverHello(new ServerHello(input, messageLen));
ServerHello serverHello = new ServerHello(input, messageLen);
this.serverHello(serverHello);
// This handshake state update needs the resumingSession value
// set by serverHello().
handshakeState.update(serverHello, resumingSession);
break;
case HandshakeMessage.ht_certificate:
......@@ -213,7 +218,9 @@ final class ClientHandshaker extends Handshaker {
"unexpected server cert chain");
// NOTREACHED
}
this.serverCertificate(new CertificateMsg(input));
CertificateMsg certificateMsg = new CertificateMsg(input);
handshakeState.update(certificateMsg, resumingSession);
this.serverCertificate(certificateMsg);
serverKey =
session.getPeerCertificates()[0].getPublicKey();
break;
......@@ -249,15 +256,20 @@ final class ClientHandshaker extends Handshaker {
}
try {
this.serverKeyExchange(new RSA_ServerKeyExchange(input));
RSA_ServerKeyExchange rsaSrvKeyExchange =
new RSA_ServerKeyExchange(input);
handshakeState.update(rsaSrvKeyExchange, resumingSession);
this.serverKeyExchange(rsaSrvKeyExchange);
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
break;
case K_DH_ANON:
try {
this.serverKeyExchange(new DH_ServerKeyExchange(
input, protocolVersion));
DH_ServerKeyExchange dhSrvKeyExchange =
new DH_ServerKeyExchange(input, protocolVersion);
handshakeState.update(dhSrvKeyExchange, resumingSession);
this.serverKeyExchange(dhSrvKeyExchange);
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
......@@ -265,11 +277,14 @@ final class ClientHandshaker extends Handshaker {
case K_DHE_DSS:
case K_DHE_RSA:
try {
this.serverKeyExchange(new DH_ServerKeyExchange(
DH_ServerKeyExchange dhSrvKeyExchange =
new DH_ServerKeyExchange(
input, serverKey,
clnt_random.random_bytes, svr_random.random_bytes,
messageLen,
getLocalSupportedSignAlgs(), protocolVersion));
getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(dhSrvKeyExchange, resumingSession);
this.serverKeyExchange(dhSrvKeyExchange);
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
......@@ -278,10 +293,13 @@ final class ClientHandshaker extends Handshaker {
case K_ECDHE_RSA:
case K_ECDH_ANON:
try {
this.serverKeyExchange(new ECDH_ServerKeyExchange
ECDH_ServerKeyExchange ecdhSrvKeyExchange =
new ECDH_ServerKeyExchange
(input, serverKey, clnt_random.random_bytes,
svr_random.random_bytes,
getLocalSupportedSignAlgs(), protocolVersion));
getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(ecdhSrvKeyExchange, resumingSession);
this.serverKeyExchange(ecdhSrvKeyExchange);
} catch (GeneralSecurityException e) {
throwSSLException("Server key", e);
}
......@@ -320,6 +338,7 @@ final class ClientHandshaker extends Handshaker {
if (debug != null && Debug.isOn("handshake")) {
certRequest.print(System.out);
}
handshakeState.update(certRequest, resumingSession);
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
Collection<SignatureAndHashAlgorithm> peerSignAlgs =
......@@ -345,33 +364,23 @@ final class ClientHandshaker extends Handshaker {
break;
case HandshakeMessage.ht_server_hello_done:
this.serverHelloDone(new ServerHelloDone(input));
ServerHelloDone serverHelloDone = new ServerHelloDone(input);
handshakeState.update(serverHelloDone, resumingSession);
this.serverHelloDone(serverHelloDone);
break;
case HandshakeMessage.ht_finished:
// A ChangeCipherSpec record must have been received prior to
// reception of the Finished message (RFC 5246, 7.4.9).
if (!receivedChangeCipherSpec()) {
fatalSE(Alerts.alert_handshake_failure,
"Received Finished message before ChangeCipherSpec");
}
Finished serverFinished =
new Finished(protocolVersion, input, cipherSuite);
handshakeState.update(serverFinished, resumingSession);
this.serverFinished(serverFinished);
this.serverFinished(
new Finished(protocolVersion, input, cipherSuite));
break;
default:
throw new SSLProtocolException(
"Illegal client handshake msg, " + type);
}
//
// Move state machine forward if the message handling
// code didn't already do so
//
if (state < type) {
state = type;
}
}
/*
......@@ -389,7 +398,7 @@ final class ClientHandshaker extends Handshaker {
// Could be (e.g. at connection setup) that we already
// sent the "client hello" but the server's not seen it.
//
if (state < HandshakeMessage.ht_client_hello) {
if (!clientHelloDelivered) {
if (!secureRenegotiation && !allowUnsafeRenegotiation) {
// renegotiation is not allowed.
if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
......@@ -613,7 +622,6 @@ final class ClientHandshaker extends Handshaker {
// looks fine; resume it, and update the state machine.
resumingSession = true;
state = HandshakeMessage.ht_finished - 1;
calculateConnectionKeys(session.getMasterSecret());
if (debug != null && Debug.isOn("session")) {
System.out.println("%% Server resumed " + session);
......@@ -904,6 +912,7 @@ final class ClientHandshaker extends Handshaker {
m1.print(System.out);
}
m1.write(output);
handshakeState.update(m1, resumingSession);
}
}
......@@ -1068,6 +1077,7 @@ final class ClientHandshaker extends Handshaker {
}
m2.write(output);
handshakeState.update(m2, resumingSession);
/*
* THIRD, send a "change_cipher_spec" record followed by the
......@@ -1170,6 +1180,7 @@ final class ClientHandshaker extends Handshaker {
m3.print(System.out);
}
m3.write(output);
handshakeState.update(m3, resumingSession);
output.doHashes();
}
......@@ -1227,6 +1238,8 @@ final class ClientHandshaker extends Handshaker {
if (resumingSession) {
input.digestNow();
sendChangeCipherAndFinish(true);
} else {
handshakeFinished = true;
}
session.setLastAccessedTime(System.currentTimeMillis());
......@@ -1272,13 +1285,6 @@ final class ClientHandshaker extends Handshaker {
if (secureRenegotiation) {
clientVerifyData = mesg.getVerifyData();
}
/*
* Update state machine so server MUST send 'finished' next.
* (In "long" handshake case; in short case, we're responding
* to its message.)
*/
state = HandshakeMessage.ht_finished - 1;
}
......
......@@ -89,6 +89,8 @@ public abstract class HandshakeMessage {
static final byte ht_finished = 20;
static final byte ht_not_applicable = -1; // N/A
/* Class and subclass dynamic debugging support */
public static final Debug debug = Debug.getInstance("ssl");
......
......@@ -118,10 +118,14 @@ abstract class Handshaker {
HandshakeHash handshakeHash;
HandshakeInStream input;
HandshakeOutStream output;
int state;
SSLContextImpl sslContext;
RandomCookie clnt_random, svr_random;
SSLSessionImpl session;
HandshakeStateManager handshakeState;
boolean clientHelloDelivered;
boolean serverHelloRequested;
boolean handshakeActivated;
boolean handshakeFinished;
// current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL
CipherSuite cipherSuite;
......@@ -135,10 +139,6 @@ abstract class Handshaker {
// True if it's OK to start a new SSL session
boolean enableNewSession;
// True if session keys have been calculated and the caller may receive
// and process a ChangeCipherSpec message
private boolean sessKeysCalculated;
// Whether local cipher suites preference should be honored during
// handshaking?
//
......@@ -277,9 +277,13 @@ abstract class Handshaker {
this.secureRenegotiation = secureRenegotiation;
this.clientVerifyData = clientVerifyData;
this.serverVerifyData = serverVerifyData;
enableNewSession = true;
invalidated = false;
sessKeysCalculated = false;
this.enableNewSession = true;
this.invalidated = false;
this.handshakeState = new HandshakeStateManager();
this.clientHelloDelivered = false;
this.serverHelloRequested = false;
this.handshakeActivated = false;
this.handshakeFinished = false;
setCipherSuite(CipherSuite.C_NULL);
setEnabledProtocols(enabledProtocols);
......@@ -289,22 +293,6 @@ abstract class Handshaker {
} else { // engine != null
algorithmConstraints = new SSLAlgorithmConstraints(engine, true);
}
//
// In addition to the connection state machine, controlling
// how the connection deals with the different sorts of records
// that get sent (notably handshake transitions!), there's
// also a handshaking state machine that controls message
// sequencing.
//
// It's a convenient artifact of the protocol that this can,
// with only a couple of minor exceptions, be driven by the
// type constant for the last message seen: except for the
// client's cert verify, those constants are in a convenient
// order to drastically simplify state machine checking.
//
state = -2; // initialized but not activated
}
/*
......@@ -386,14 +374,6 @@ abstract class Handshaker {
}
}
final boolean receivedChangeCipherSpec() {
if (conn != null) {
return conn.receivedChangeCipherSpec();
} else {
return engine.receivedChangeCipherSpec();
}
}
String getEndpointIdentificationAlgorithmSE() {
SSLParameters paras;
if (conn != null) {
......@@ -573,8 +553,7 @@ abstract class Handshaker {
engine.outputRecord.setHelloVersion(helloVersion);
}
// move state to activated
state = -1;
handshakeActivated = true;
}
/**
......@@ -919,10 +898,9 @@ abstract class Handshaker {
* this freshly created session can become the current one.
*/
boolean isDone() {
return state == HandshakeMessage.ht_finished;
return started() && handshakeState.isEmpty() && handshakeFinished;
}
/*
* Returns the session which was created through this
* handshake sequence ... should be called after isDone()
......@@ -1028,6 +1006,13 @@ abstract class Handshaker {
return;
}
// Set the flags in the message receiving side.
if (messageType == HandshakeMessage.ht_client_hello) {
clientHelloDelivered = true;
} else if (messageType == HandshakeMessage.ht_hello_request) {
serverHelloRequested = true;
}
/*
* Process the message. We require
* that processMessage() consumes the entire message. In
......@@ -1062,15 +1047,14 @@ abstract class Handshaker {
* In activated state, the handshaker may not send any messages out.
*/
boolean activated() {
return state >= -1;
return handshakeActivated;
}
/**
* Returns true iff the handshaker has sent any messages.
*/
boolean started() {
return state >= 0; // 0: HandshakeMessage.ht_hello_request
// 1: HandshakeMessage.ht_client_hello
return (serverHelloRequested || clientHelloDelivered);
}
......@@ -1080,11 +1064,13 @@ abstract class Handshaker {
* the subclass returns. NOP if handshaking's already started.
*/
void kickstart() throws IOException {
if (state >= 0) {
if ((isClient && clientHelloDelivered) ||
(!isClient && serverHelloRequested)) {
return;
}
HandshakeMessage m = getKickstartMessage();
handshakeState.update(m, resumingSession);
if (debug != null && Debug.isOn("handshake")) {
m.print(System.out);
......@@ -1092,7 +1078,14 @@ abstract class Handshaker {
m.write(output);
output.flush();
state = m.messageType();
// Set the flags in the message delivering side.
int handshakeType = m.messageType();
if (handshakeType == HandshakeMessage.ht_hello_request) {
serverHelloRequested = true;
} else { // HandshakeMessage.ht_client_hello
clientHelloDelivered = true;
}
}
/**
......@@ -1124,16 +1117,6 @@ abstract class Handshaker {
output.flush(); // i.e. handshake data
/*
* The write cipher state is protected by the connection write lock
* so we must grab it while making the change. We also
* make sure no writes occur between sending the ChangeCipherSpec
* message, installing the new cipher state, and sending the
* Finished message.
*
* We already hold SSLEngine/SSLSocket "this" by virtue
* of this being called from the readRecord code.
*/
OutputRecord r;
if (conn != null) {
r = new OutputRecord(Record.ct_change_cipher_spec);
......@@ -1144,14 +1127,27 @@ abstract class Handshaker {
r.setVersion(protocolVersion);
r.write(1); // single byte of data
/*
* The write cipher state is protected by the connection write lock
* so we must grab it while making the change. We also
* make sure no writes occur between sending the ChangeCipherSpec
* message, installing the new cipher state, and sending the
* Finished message.
*
* We already hold SSLEngine/SSLSocket "this" by virtue
* of this being called from the readRecord code.
*/
if (conn != null) {
conn.writeLock.lock();
try {
handshakeState.changeCipherSpec(false, isClient);
conn.writeRecord(r);
conn.changeWriteCiphers();
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
handshakeState.update(mesg, resumingSession);
mesg.write(output);
output.flush();
} finally {
......@@ -1159,19 +1155,28 @@ abstract class Handshaker {
}
} else {
synchronized (engine.writeLock) {
handshakeState.changeCipherSpec(false, isClient);
engine.writeRecord((EngineOutputRecord)r);
engine.changeWriteCiphers();
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
mesg.write(output);
handshakeState.update(mesg, resumingSession);
mesg.write(output);
if (lastMessage) {
output.setFinishedMsg();
}
output.flush();
}
}
if (lastMessage) {
handshakeFinished = true;
}
}
void receiveChangeCipherSpec() throws IOException {
handshakeState.changeCipherSpec(true, isClient);
}
/*
......@@ -1353,10 +1358,6 @@ abstract class Handshaker {
throw new ProviderException(e);
}
// Mark a flag that allows outside entities (like SSLSocket/SSLEngine)
// determine if a ChangeCipherSpec message could be processed.
sessKeysCalculated = true;
//
// Dump the connection keys as they're generated.
//
......@@ -1411,15 +1412,6 @@ abstract class Handshaker {
}
}
/**
* Return whether or not the Handshaker has derived session keys for
* this handshake. This is used for determining readiness to process
* an incoming ChangeCipherSpec message.
*/
boolean sessionKeysCalculated() {
return sessKeysCalculated;
}
private static void printHex(HexDumpEncoder dump, byte[] bytes) {
if (bytes == null) {
System.out.println("(key bytes not available)");
......
......@@ -211,11 +211,6 @@ final public class SSLEngineImpl extends SSLEngine {
static final byte clauth_requested = 1;
static final byte clauth_required = 2;
/*
* Flag indicating that the engine has received a ChangeCipherSpec message.
*/
private boolean receivedCCS;
/*
* Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that
......@@ -377,7 +372,6 @@ final public class SSLEngineImpl extends SSLEngine {
*/
roleIsServer = true;
connectionState = cs_START;
receivedCCS = false;
// default server name indication
serverNames =
......@@ -525,7 +519,6 @@ final public class SSLEngineImpl extends SSLEngine {
return HandshakeStatus.NEED_UNWRAP;
} // else not handshaking
}
return HandshakeStatus.NOT_HANDSHAKING;
}
}
......@@ -587,14 +580,6 @@ final public class SSLEngineImpl extends SSLEngine {
* Synchronized on "this" from readRecord.
*/
private void changeReadCiphers() throws SSLException {
if (connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE) {
throw new SSLProtocolException(
"State error, change cipher specs");
}
// ... create decompressor
CipherBox oldCipher = readCipher;
try {
......@@ -780,6 +765,10 @@ final public class SSLEngineImpl extends SSLEngine {
synchronized (unwrapLock) {
return readNetRecord(ea);
}
} catch (SSLProtocolException spe) {
// may be an unexpected handshake message
fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
return null; // make compiler happy
} catch (Exception e) {
/*
* Don't reset position so it looks like we didn't
......@@ -1004,6 +993,7 @@ final public class SSLEngineImpl extends SSLEngine {
* session (new keys exchanged) with just this connection
* in it.
*/
initHandshaker();
if (!handshaker.activated()) {
// prior to handshaking, activate the handshake
......@@ -1027,7 +1017,6 @@ final public class SSLEngineImpl extends SSLEngine {
if (handshaker.invalidated) {
handshaker = null;
receivedCCS = false;
// if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA;
......@@ -1046,8 +1035,6 @@ final public class SSLEngineImpl extends SSLEngine {
}
handshaker = null;
connectionState = cs_DATA;
receivedCCS = false;
// No handshakeListeners here. That's a
// SSLSocket thing.
} else if (handshaker.taskOutstanding()) {
......@@ -1085,14 +1072,11 @@ final public class SSLEngineImpl extends SSLEngine {
case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE)
|| !handshaker.sessionKeysCalculated()
|| receivedCCS) {
&& connectionState != cs_RENEGOTIATE)) {
// For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message,
"illegal change cipher spec msg, conn state = "
+ connectionState + ", handshake state = "
+ handshaker.state);
+ connectionState);
} else if (inputRecord.available() != 1
|| inputRecord.read() != 1) {
// For structural/content issues with the CCS
......@@ -1100,11 +1084,6 @@ final public class SSLEngineImpl extends SSLEngine {
"Malformed change cipher spec msg");
}
// Once we've received CCS, update the flag.
// If the remote endpoint sends it again in this handshake
// we won't process it.
receivedCCS = true;
//
// The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record,
......@@ -1112,6 +1091,7 @@ final public class SSLEngineImpl extends SSLEngine {
// to be checked by a minor tweak to the state
// machine.
//
handshaker.receiveChangeCipherSpec();
changeReadCiphers();
// next message MUST be a finished message
expectingFinished = true;
......@@ -1151,7 +1131,6 @@ final public class SSLEngineImpl extends SSLEngine {
}
} // synchronized (this)
}
return hsStatus;
}
......@@ -1185,6 +1164,10 @@ final public class SSLEngineImpl extends SSLEngine {
synchronized (wrapLock) {
return writeAppRecord(ea);
}
} catch (SSLProtocolException spe) {
// may be an unexpected handshake message
fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
return null; // make compiler happy
} catch (Exception e) {
ea.resetPos();
......@@ -1212,7 +1195,6 @@ final public class SSLEngineImpl extends SSLEngine {
* See if the handshaker needs to report back some SSLException.
*/
checkTaskThrown();
/*
* short circuit if we're closed/closing.
*/
......@@ -1234,7 +1216,6 @@ final public class SSLEngineImpl extends SSLEngine {
* without trying to wrap anything.
*/
hsStatus = getHSStatus(null);
if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
}
......@@ -2140,14 +2121,6 @@ final public class SSLEngineImpl extends SSLEngine {
}
}
/*
* Returns a boolean indicating whether the ChangeCipherSpec message
* has been received for this handshake.
*/
boolean receivedChangeCipherSpec() {
return receivedCCS;
}
/**
* Returns a printable representation of this end of the connection.
*/
......
......@@ -174,12 +174,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
private volatile int connectionState;
/*
* Flag indicating that the engine's handshaker has done the necessary
* steps so the engine may process a ChangeCipherSpec message.
*/
private boolean receivedCCS;
/*
* Flag indicating if the next record we receive MUST be a Finished
* message. Temporarily set during the handshake to ensure that
......@@ -610,7 +604,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
*/
roleIsServer = isServer;
connectionState = cs_START;
receivedCCS = false;
/*
* default read and write side cipher and MAC support
......@@ -940,7 +933,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
readRecord(r, true);
}
/*
* Clear the pipeline of records from the peer, optionally returning
* application data. Caller is responsible for knowing that it's
......@@ -1074,7 +1066,8 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
if (handshaker.invalidated) {
handshaker = null;
receivedCCS = false;
inrec.setHandshakeHash(null);
// if state is cs_RENEGOTIATE, revert it to cs_DATA
if (connectionState == cs_RENEGOTIATE) {
connectionState = cs_DATA;
......@@ -1090,7 +1083,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
handshakeSession = null;
handshaker = null;
connectionState = cs_DATA;
receivedCCS = false;
//
// Tell folk about handshake completion, but do
......@@ -1137,25 +1129,17 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
case Record.ct_change_cipher_spec:
if ((connectionState != cs_HANDSHAKE
&& connectionState != cs_RENEGOTIATE)
|| !handshaker.sessionKeysCalculated()
|| receivedCCS) {
&& connectionState != cs_RENEGOTIATE)) {
// For the CCS message arriving in the wrong state
fatal(Alerts.alert_unexpected_message,
"illegal change cipher spec msg, conn state = "
+ connectionState + ", handshake state = "
+ handshaker.state);
+ connectionState);
} else if (r.available() != 1 || r.read() != 1) {
// For structural/content issues with the CCS
fatal(Alerts.alert_unexpected_message,
"Malformed change cipher spec msg");
}
// Once we've received CCS, update the flag.
// If the remote endpoint sends it again in this handshake
// we won't process it.
receivedCCS = true;
//
// The first message after a change_cipher_spec
// record MUST be a "Finished" handshake record,
......@@ -1163,6 +1147,7 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
// to be checked by a minor tweak to the state
// machine.
//
handshaker.receiveChangeCipherSpec();
changeReadCiphers();
// next message MUST be a finished message
expectingFinished = true;
......@@ -1361,13 +1346,10 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
kickstartHandshake();
/*
* All initial handshaking goes through this
* InputRecord until we have a valid SSL connection.
* Once initial handshaking is finished, AppInputStream's
* InputRecord can handle any future renegotiation.
* All initial handshaking goes through this operation
* until we have a valid SSL connection.
*
* Keep this local so that it goes out of scope and is
* eventually GC'd.
* Handle handshake messages only, need no application data.
*/
if (inrec == null) {
inrec = new InputRecord();
......@@ -2666,14 +2648,6 @@ final public class SSLSocketImpl extends BaseSSLSocketImpl {
}
}
/*
* Returns a boolean indicating whether the ChangeCipherSpec message
* has been received for this handshake.
*/
boolean receivedChangeCipherSpec() {
return receivedCCS;
}
//
// We allocate a separate thread to deliver handshake completion
// events. This ensures that the notifications don't block the
......
......@@ -207,21 +207,14 @@ final class ServerHandshaker extends Handshaker {
@Override
void processMessage(byte type, int message_len)
throws IOException {
//
// In SSLv3 and TLS, messages follow strictly increasing
// numerical order _except_ for one annoying special case.
//
if ((state >= type)
&& (state != HandshakeMessage.ht_client_key_exchange
&& type != HandshakeMessage.ht_certificate_verify)) {
throw new SSLProtocolException(
"Handshake message sequence violation, state = " + state
+ ", type = " + type);
}
// check the handshake state
handshakeState.check(type);
switch (type) {
case HandshakeMessage.ht_client_hello:
ClientHello ch = new ClientHello(input, message_len);
handshakeState.update(ch, resumingSession);
/*
* send it off for processing.
*/
......@@ -234,7 +227,9 @@ final class ServerHandshaker extends Handshaker {
"client sent unsolicited cert chain");
// NOTREACHED
}
this.clientCertificate(new CertificateMsg(input));
CertificateMsg certificateMsg = new CertificateMsg(input);
handshakeState.update(certificateMsg, resumingSession);
this.clientCertificate(certificateMsg);
break;
case HandshakeMessage.ht_client_key_exchange:
......@@ -252,17 +247,20 @@ final class ServerHandshaker extends Handshaker {
protocolVersion, clientRequestedVersion,
sslContext.getSecureRandom(), input,
message_len, privateKey);
handshakeState.update(pms, resumingSession);
preMasterSecret = this.clientKeyExchange(pms);
break;
case K_KRB5:
case K_KRB5_EXPORT:
preMasterSecret = this.clientKeyExchange(
KerberosClientKeyExchange kke =
new KerberosClientKeyExchange(protocolVersion,
clientRequestedVersion,
sslContext.getSecureRandom(),
input,
this.getAccSE(),
serviceCreds));
serviceCreds);
handshakeState.update(kke, resumingSession);
preMasterSecret = this.clientKeyExchange(kke);
break;
case K_DHE_RSA:
case K_DHE_DSS:
......@@ -273,16 +271,19 @@ final class ServerHandshaker extends Handshaker {
* protocol difference in these five flavors is in how
* the ServerKeyExchange message was constructed!
*/
preMasterSecret = this.clientKeyExchange(
new DHClientKeyExchange(input));
DHClientKeyExchange dhcke = new DHClientKeyExchange(input);
handshakeState.update(dhcke, resumingSession);
preMasterSecret = this.clientKeyExchange(dhcke);
break;
case K_ECDH_RSA:
case K_ECDH_ECDSA:
case K_ECDHE_RSA:
case K_ECDHE_ECDSA:
case K_ECDH_ANON:
preMasterSecret = this.clientKeyExchange
(new ECDHClientKeyExchange(input));
ECDHClientKeyExchange ecdhcke =
new ECDHClientKeyExchange(input);
handshakeState.update(ecdhcke, resumingSession);
preMasterSecret = this.clientKeyExchange(ecdhcke);
break;
default:
throw new SSLProtocolException
......@@ -302,38 +303,24 @@ final class ServerHandshaker extends Handshaker {
break;
case HandshakeMessage.ht_certificate_verify:
this.clientCertificateVerify(new CertificateVerify(input,
getLocalSupportedSignAlgs(), protocolVersion));
CertificateVerify cvm =
new CertificateVerify(input,
getLocalSupportedSignAlgs(), protocolVersion);
handshakeState.update(cvm, resumingSession);
this.clientCertificateVerify(cvm);
break;
case HandshakeMessage.ht_finished:
// A ChangeCipherSpec record must have been received prior to
// reception of the Finished message (RFC 5246, 7.4.9).
if (!receivedChangeCipherSpec()) {
fatalSE(Alerts.alert_handshake_failure,
"Received Finished message before ChangeCipherSpec");
}
this.clientFinished(
new Finished(protocolVersion, input, cipherSuite));
Finished cfm =
new Finished(protocolVersion, input, cipherSuite);
handshakeState.update(cfm, resumingSession);
this.clientFinished(cfm);
break;
default:
throw new SSLProtocolException(
"Illegal server handshake msg, " + type);
}
//
// Move state machine forward if the message handling
// code didn't already do so
//
if (state < type) {
if(type == HandshakeMessage.ht_certificate_verify) {
state = type + 2; // an annoying special case
} else {
state = type;
}
}
}
......@@ -364,7 +351,7 @@ final class ServerHandshaker extends Handshaker {
//
// This will not have any impact on server initiated renegotiation.
if (rejectClientInitiatedRenego && !isInitialHandshake &&
state != HandshakeMessage.ht_hello_request) {
!serverHelloRequested) {
fatalSE(Alerts.alert_handshake_failure,
"Client initiated renegotiation is not allowed");
}
......@@ -876,6 +863,7 @@ final class ServerHandshaker extends Handshaker {
System.out.println("Cipher suite: " + session.getSuite());
}
m1.write(output);
handshakeState.update(m1, resumingSession);
//
// If we are resuming a session, we finish writing handshake
......@@ -915,6 +903,7 @@ final class ServerHandshaker extends Handshaker {
m2.print(System.out);
}
m2.write(output);
handshakeState.update(m2, resumingSession);
// XXX has some side effects with OS TCP buffering,
// leave it out for now
......@@ -1010,6 +999,7 @@ final class ServerHandshaker extends Handshaker {
m3.print(System.out);
}
m3.write(output);
handshakeState.update(m3, resumingSession);
}
//
......@@ -1059,6 +1049,7 @@ final class ServerHandshaker extends Handshaker {
m4.print(System.out);
}
m4.write(output);
handshakeState.update(m4, resumingSession);
}
/*
......@@ -1070,6 +1061,7 @@ final class ServerHandshaker extends Handshaker {
m5.print(System.out);
}
m5.write(output);
handshakeState.update(m5, resumingSession);
/*
* Flush any buffered messages so the client will see them.
......@@ -1817,6 +1809,8 @@ final class ServerHandshaker extends Handshaker {
if (!resumingSession) {
input.digestNow();
sendChangeCipherAndFinish(true);
} else {
handshakeFinished = true;
}
/*
......@@ -1864,16 +1858,6 @@ final class ServerHandshaker extends Handshaker {
if (secureRenegotiation) {
serverVerifyData = mesg.getVerifyData();
}
/*
* Update state machine so client MUST send 'finished' next
* The update should only take place if it is not in the fast
* handshake mode since the server has to wait for a finished
* message from the client.
*/
if (finishedTag) {
state = HandshakeMessage.ht_finished;
}
}
......
......@@ -23,7 +23,7 @@
/*
* @test
* @bug 8044860
* @bug 8044860 8074462
* @summary Vectors and fixed length fields should be verified
* for allowed sizes.
* @run main/othervm LengthCheckTest
......@@ -231,7 +231,7 @@ public class LengthCheckTest {
// sent back to the server.
if (gotException == false ||
!isTlsMessage(cTOs, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
TLS_ALERT_INTERNAL_ERROR)) {
TLS_ALERT_UNEXPECTED_MSG)) {
throw new SSLException(
"Client failed to throw Alert:fatal:internal_error");
}
......@@ -283,7 +283,7 @@ public class LengthCheckTest {
// sent back to the client.
if (gotException == false ||
!isTlsMessage(sTOc, TLS_RECTYPE_ALERT, TLS_ALERT_LVL_FATAL,
TLS_ALERT_INTERNAL_ERROR)) {
TLS_ALERT_UNEXPECTED_MSG)) {
throw new SSLException(
"Server failed to throw Alert:fatal:internal_error");
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册