/* * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.ssl; import java.io.*;import java.util.*;import java.security.*;import java.security.NoSuchAlgorithmException;import java.security.AccessController;import java.security.AlgorithmConstraints;import java.security.AccessControlContext;import java.security.PrivilegedExceptionAction;import java.security.PrivilegedActionException; import javax.crypto.*;import javax.crypto.spec.*; import javax.net.ssl.*;import sun.misc.HexDumpEncoder; import sun.security.internal.spec.*;import sun.security.internal.interfaces.TlsMasterSecret; import sun.security.ssl.HandshakeMessage.*;import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; /** * Handshaker ... processes handshake records from an SSL V3.0 * data stream, handling all the details of the handshake protocol. * * Note that the real protocol work is done in two subclasses, the base * class just provides the control flow and key generation framework. * * @author David Brownell */abstract class Handshaker { // protocol version being established using this Handshaker ProtocolVersion protocolVersion; // the currently active protocol version during a renegotiation ProtocolVersion activeProtocolVersion; // security parameters for secure renegotiation. boolean secureRenegotiation; byte[] clientVerifyData; byte[] serverVerifyData; // Is it an initial negotiation or a renegotiation? boolean isInitialHandshake; // List of enabled protocols private ProtocolList enabledProtocols; // List of enabled CipherSuites private CipherSuiteList enabledCipherSuites; // The endpoint identification protocol String identificationProtocol; // The cryptographic algorithm constraints private AlgorithmConstraints algorithmConstraints = null; // Local supported signature and algorithms Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs; // Peer supported signature and algorithms Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs; /* /* * List of active protocols * * Active protocols is a subset of enabled protocols, and will * contain only those protocols that have vaild cipher suites * enabled. */ private ProtocolList activeProtocols; /* * List of active cipher suites * * Active cipher suites is a subset of enabled cipher suites, and will * contain only those cipher suites available for the active protocols. */ private CipherSuiteList activeCipherSuites; private boolean isClient; private boolean needCertVerify; SSLSocketImpl conn = null; SSLEngineImpl engine = null; HandshakeHash handshakeHash; HandshakeInStream input; HandshakeOutStream output; int state; SSLContextImpl sslContext; RandomCookie clnt_random, svr_random; SSLSessionImpl session; // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL CipherSuite cipherSuite; // current key exchange. Never null, initially K_NULL KeyExchange keyExchange; /* True if this session is being resumed (fast handshake) */ boolean resumingSession; /* True if it's OK to start a new SSL session */ boolean enableNewSession; // Temporary storage for the individual keys. Set by // calculateConnectionKeys() and cleared once the ciphers are // activated. private SecretKey clntWriteKey, svrWriteKey; private IvParameterSpec clntWriteIV, svrWriteIV; private SecretKey clntMacSecret, svrMacSecret; /* * Delegated task subsystem data structures. * * If thrown is set, we need to propagate this back immediately * on entry into processMessage(). * * Data is protected by the SSLEngine.this lock. */ private volatile boolean taskDelegated = false; private volatile DelegatedTask delegatedTask = null; private volatile Exception thrown = null; // Could probably use a java.util.concurrent.atomic.AtomicReference // here instead of using this lock. Consider changing. private Object thrownLock = new Object(); /* Class and subclass dynamic debugging support */ static final Debug debug = Debug.getInstance("ssl"); // By default, disable the unsafe legacy session renegotiation static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty( "sun.security.ssl.allowUnsafeRenegotiation", false); // For maximum interoperability and backward compatibility, RFC 5746 // allows server (or client) to accept ClientHello (or ServerHello) // message without the secure renegotiation_info extension or SCSV. // // For maximum security, RFC 5746 also allows server (or client) to // reject such message with a fatal "handshake_failure" alert. // // By default, allow such legacy hello messages. static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty( "sun.security.ssl.allowLegacyHelloMessages", true); // need to dispose the object when it is invalidated boolean invalidated; Handshaker(SSLSocketImpl c, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { this.conn = c; init(context, enabledProtocols, needCertVerify, isClient, activeProtocolVersion, isInitialHandshake, secureRenegotiation, clientVerifyData, serverVerifyData); } Handshaker(SSLEngineImpl engine, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { this.engine = engine; init(context, enabledProtocols, needCertVerify, isClient, activeProtocolVersion, isInitialHandshake, secureRenegotiation, clientVerifyData, serverVerifyData); } private void init(SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { if (debug != null && Debug.isOn("handshake")) { System.out.println( "Allow unsafe renegotiation: " + allowUnsafeRenegotiation + "\nAllow legacy hello messages: " + allowLegacyHelloMessages + "\nIs initial handshake: " + isInitialHandshake + "\nIs secure renegotiation: " + secureRenegotiation); } this.sslContext = context; this.isClient = isClient; this.needCertVerify = needCertVerify; this.activeProtocolVersion = activeProtocolVersion; this.isInitialHandshake = isInitialHandshake; this.secureRenegotiation = secureRenegotiation; this.clientVerifyData = clientVerifyData; this.serverVerifyData = serverVerifyData; enableNewSession = true; invalidated = false; setCipherSuite(CipherSuite.C_NULL); setEnabledProtocols(enabledProtocols); if (conn != null) { algorithmConstraints = new SSLAlgorithmConstraints(conn, true); } 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 } /* * Reroutes calls to the SSLSocket or SSLEngine (*SE). * * We could have also done it by extra classes * and letting them override, but this seemed much * less involved. */ void fatalSE(byte b, String diagnostic) throws IOException { fatalSE(b, diagnostic, null); } void fatalSE(byte b, Throwable cause) throws IOException { fatalSE(b, null, cause); } void fatalSE(byte b, String diagnostic, Throwable cause) throws IOException { if (conn != null) { conn.fatal(b, diagnostic, cause); } else { engine.fatal(b, diagnostic, cause); } } void warningSE(byte b) { if (conn != null) { conn.warning(b); } else { engine.warning(b); } } String getRawHostnameSE() { if (conn != null) { return conn.getRawHostname(); } else { return engine.getPeerHost(); } } String getHostSE() { if (conn != null) { return conn.getHost(); } else { return engine.getPeerHost(); } } String getHostAddressSE() { if (conn != null) { return conn.getInetAddress().getHostAddress(); } else { /* * This is for caching only, doesn't matter that's is really * a hostname. The main thing is that it doesn't do * a reverse DNS lookup, potentially slowing things down. */ return engine.getPeerHost(); } } boolean isLoopbackSE() { if (conn != null) { return conn.getInetAddress().isLoopbackAddress(); } else { return false; } } int getPortSE() { if (conn != null) { return conn.getPort(); } else { return engine.getPeerPort(); } } int getLocalPortSE() { if (conn != null) { return conn.getLocalPort(); } else { return -1; } } AccessControlContext getAccSE() { if (conn != null) { return conn.getAcc(); } else { return engine.getAcc(); } } private void setVersionSE(ProtocolVersion protocolVersion) { if (conn != null) { conn.setVersion(protocolVersion); } else { engine.setVersion(protocolVersion); } } /** * Set the active protocol version and propagate it to the SSLSocket * and our handshake streams. Called from ClientHandshaker * and ServerHandshaker with the negotiated protocol version. */ void setVersion(ProtocolVersion protocolVersion) { this.protocolVersion = protocolVersion; setVersionSE(protocolVersion); output.r.setVersion(protocolVersion); } /** * Set the enabled protocols. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the * handshake is not yet in progress). */ void setEnabledProtocols(ProtocolList enabledProtocols) { activeCipherSuites = null; activeProtocols = null; this.enabledProtocols = enabledProtocols; } /** * Set the enabled cipher suites. Called from * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the * handshake is not yet in progress). */ void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) { activeCipherSuites = null; activeProtocols = null; this.enabledCipherSuites = enabledCipherSuites; } /** * Set the algorithm constraints. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the * handshake is not yet in progress). */ void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) { activeCipherSuites = null; activeProtocols = null; this.algorithmConstraints = new SSLAlgorithmConstraints(algorithmConstraints); this.localSupportedSignAlgs = null; } Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() { if (localSupportedSignAlgs == null) { localSupportedSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms( algorithmConstraints); } return localSupportedSignAlgs; } void setPeerSupportedSignAlgs( Collection<SignatureAndHashAlgorithm> algorithms) { peerSupportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(algorithms); } Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() { return peerSupportedSignAlgs; } /** * Set the identification protocol. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the * handshake is not yet in progress). */ void setIdentificationProtocol(String protocol) { this.identificationProtocol = protocol; } /** * Prior to handshaking, activate the handshake and initialize the version, * input stream and output stream. */ void activate(ProtocolVersion helloVersion) throws IOException { if (activeProtocols == null) { activeProtocols = getActiveProtocols(); } if (activeProtocols.collection().isEmpty() || activeProtocols.max.v == ProtocolVersion.NONE.v) { throw new SSLHandshakeException("No appropriate protocol"); } if (activeCipherSuites == null) { activeCipherSuites = getActiveCipherSuites(); } if (activeCipherSuites.collection().isEmpty()) { throw new SSLHandshakeException("No appropriate cipher suite"); } // temporary protocol version until the actual protocol version // is negotiated in the Hello exchange. This affects the record // version we sent with the ClientHello. if (!isInitialHandshake) { protocolVersion = activeProtocolVersion; } else { protocolVersion = activeProtocols.max; } if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) { helloVersion = activeProtocols.helloVersion; } // We accumulate digests of the handshake messages so that // we can read/write CertificateVerify and Finished messages, // getting assurance against some particular active attacks. Set<String> localSupportedHashAlgorithms = SignatureAndHashAlgorithm.getHashAlgorithmNames( getLocalSupportedSignAlgs()); handshakeHash = new HandshakeHash(!isClient, needCertVerify, localSupportedHashAlgorithms); // Generate handshake input/output stream. input = new HandshakeInStream(handshakeHash); if (conn != null) { output = new HandshakeOutStream(protocolVersion, helloVersion, handshakeHash, conn); conn.getAppInputStream().r.setHandshakeHash(handshakeHash); conn.getAppInputStream().r.setHelloVersion(helloVersion); conn.getAppOutputStream().r.setHelloVersion(helloVersion); } else { output = new HandshakeOutStream(protocolVersion, helloVersion, handshakeHash, engine); engine.inputRecord.setHandshakeHash(handshakeHash); engine.inputRecord.setHelloVersion(helloVersion); engine.outputRecord.setHelloVersion(helloVersion); } // move state to activated state = -1; }Lines 1–500 of 1386. Load more
/* * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.ssl; import java.io.*; import java.util.*; import java.security.*; import java.security.NoSuchAlgorithmException; import java.security.AccessController; import java.security.AlgorithmConstraints; import java.security.AccessControlContext; import java.security.PrivilegedExceptionAction; import java.security.PrivilegedActionException; import javax.crypto.*; import javax.crypto.spec.*; import javax.net.ssl.*; import sun.misc.HexDumpEncoder; import sun.security.internal.spec.*; import sun.security.internal.interfaces.TlsMasterSecret; import sun.security.ssl.HandshakeMessage.*; import sun.security.ssl.CipherSuite.*; import static sun.security.ssl.CipherSuite.PRF.*; /** * Handshaker ... processes handshake records from an SSL V3.0 * data stream, handling all the details of the handshake protocol. * * Note that the real protocol work is done in two subclasses, the base * class just provides the control flow and key generation framework. * * @author David Brownell */ abstract class Handshaker { // protocol version being established using this Handshaker ProtocolVersion protocolVersion; // the currently active protocol version during a renegotiation ProtocolVersion activeProtocolVersion; // security parameters for secure renegotiation. boolean secureRenegotiation; byte[] clientVerifyData; byte[] serverVerifyData; // Is it an initial negotiation or a renegotiation? boolean isInitialHandshake; // List of enabled protocols private ProtocolList enabledProtocols; // List of enabled CipherSuites private CipherSuiteList enabledCipherSuites; // The endpoint identification protocol String identificationProtocol; // The cryptographic algorithm constraints private AlgorithmConstraints algorithmConstraints = null; // Local supported signature and algorithms Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs; // Peer supported signature and algorithms Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs; /* /* * List of active protocols * * Active protocols is a subset of enabled protocols, and will * contain only those protocols that have vaild cipher suites * enabled. */ private ProtocolList activeProtocols; /* * List of active cipher suites * * Active cipher suites is a subset of enabled cipher suites, and will * contain only those cipher suites available for the active protocols. */ private CipherSuiteList activeCipherSuites; private boolean isClient; private boolean needCertVerify; SSLSocketImpl conn = null; SSLEngineImpl engine = null; HandshakeHash handshakeHash; HandshakeInStream input; HandshakeOutStream output; int state; SSLContextImpl sslContext; RandomCookie clnt_random, svr_random; SSLSessionImpl session; // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL CipherSuite cipherSuite; // current key exchange. Never null, initially K_NULL KeyExchange keyExchange; /* True if this session is being resumed (fast handshake) */ boolean resumingSession; /* True if it's OK to start a new SSL session */ boolean enableNewSession; // Temporary storage for the individual keys. Set by // calculateConnectionKeys() and cleared once the ciphers are // activated. private SecretKey clntWriteKey, svrWriteKey; private IvParameterSpec clntWriteIV, svrWriteIV; private SecretKey clntMacSecret, svrMacSecret; /* * Delegated task subsystem data structures. * * If thrown is set, we need to propagate this back immediately * on entry into processMessage(). * * Data is protected by the SSLEngine.this lock. */ private volatile boolean taskDelegated = false; private volatile DelegatedTask delegatedTask = null; private volatile Exception thrown = null; // Could probably use a java.util.concurrent.atomic.AtomicReference // here instead of using this lock. Consider changing. private Object thrownLock = new Object(); /* Class and subclass dynamic debugging support */ static final Debug debug = Debug.getInstance("ssl"); // By default, disable the unsafe legacy session renegotiation static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty( "sun.security.ssl.allowUnsafeRenegotiation", false); // For maximum interoperability and backward compatibility, RFC 5746 // allows server (or client) to accept ClientHello (or ServerHello) // message without the secure renegotiation_info extension or SCSV. // // For maximum security, RFC 5746 also allows server (or client) to // reject such message with a fatal "handshake_failure" alert. // // By default, allow such legacy hello messages. static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty( "sun.security.ssl.allowLegacyHelloMessages", true); // need to dispose the object when it is invalidated boolean invalidated; Handshaker(SSLSocketImpl c, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { this.conn = c; init(context, enabledProtocols, needCertVerify, isClient, activeProtocolVersion, isInitialHandshake, secureRenegotiation, clientVerifyData, serverVerifyData); } Handshaker(SSLEngineImpl engine, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { this.engine = engine; init(context, enabledProtocols, needCertVerify, isClient, activeProtocolVersion, isInitialHandshake, secureRenegotiation, clientVerifyData, serverVerifyData); } private void init(SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData) { if (debug != null && Debug.isOn("handshake")) { System.out.println( "Allow unsafe renegotiation: " + allowUnsafeRenegotiation + "\nAllow legacy hello messages: " + allowLegacyHelloMessages + "\nIs initial handshake: " + isInitialHandshake + "\nIs secure renegotiation: " + secureRenegotiation); } this.sslContext = context; this.isClient = isClient; this.needCertVerify = needCertVerify; this.activeProtocolVersion = activeProtocolVersion; this.isInitialHandshake = isInitialHandshake; this.secureRenegotiation = secureRenegotiation; this.clientVerifyData = clientVerifyData; this.serverVerifyData = serverVerifyData; enableNewSession = true; invalidated = false; setCipherSuite(CipherSuite.C_NULL); setEnabledProtocols(enabledProtocols); if (conn != null) { algorithmConstraints = new SSLAlgorithmConstraints(conn, true); } 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 } /* * Reroutes calls to the SSLSocket or SSLEngine (*SE). * * We could have also done it by extra classes * and letting them override, but this seemed much * less involved. */ void fatalSE(byte b, String diagnostic) throws IOException { fatalSE(b, diagnostic, null); } void fatalSE(byte b, Throwable cause) throws IOException { fatalSE(b, null, cause); } void fatalSE(byte b, String diagnostic, Throwable cause) throws IOException { if (conn != null) { conn.fatal(b, diagnostic, cause); } else { engine.fatal(b, diagnostic, cause); } } void warningSE(byte b) { if (conn != null) { conn.warning(b); } else { engine.warning(b); } } String getRawHostnameSE() { if (conn != null) { return conn.getRawHostname(); } else { return engine.getPeerHost(); } } String getHostSE() { if (conn != null) { return conn.getHost(); } else { return engine.getPeerHost(); } } String getHostAddressSE() { if (conn != null) { return conn.getInetAddress().getHostAddress(); } else { /* * This is for caching only, doesn't matter that's is really * a hostname. The main thing is that it doesn't do * a reverse DNS lookup, potentially slowing things down. */ return engine.getPeerHost(); } } boolean isLoopbackSE() { if (conn != null) { return conn.getInetAddress().isLoopbackAddress(); } else { return false; } } int getPortSE() { if (conn != null) { return conn.getPort(); } else { return engine.getPeerPort(); } } int getLocalPortSE() { if (conn != null) { return conn.getLocalPort(); } else { return -1; } } AccessControlContext getAccSE() { if (conn != null) { return conn.getAcc(); } else { return engine.getAcc(); } } private void setVersionSE(ProtocolVersion protocolVersion) { if (conn != null) { conn.setVersion(protocolVersion); } else { engine.setVersion(protocolVersion); } } /** * Set the active protocol version and propagate it to the SSLSocket * and our handshake streams. Called from ClientHandshaker * and ServerHandshaker with the negotiated protocol version. */ void setVersion(ProtocolVersion protocolVersion) { this.protocolVersion = protocolVersion; setVersionSE(protocolVersion); output.r.setVersion(protocolVersion); } /** * Set the enabled protocols. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the * handshake is not yet in progress). */ void setEnabledProtocols(ProtocolList enabledProtocols) { activeCipherSuites = null; activeProtocols = null; this.enabledProtocols = enabledProtocols; } /** * Set the enabled cipher suites. Called from * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the * handshake is not yet in progress). */ void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) { activeCipherSuites = null; activeProtocols = null; this.enabledCipherSuites = enabledCipherSuites; } /** * Set the algorithm constraints. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the * handshake is not yet in progress). */ void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) { activeCipherSuites = null; activeProtocols = null; this.algorithmConstraints = new SSLAlgorithmConstraints(algorithmConstraints); this.localSupportedSignAlgs = null; } Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() { if (localSupportedSignAlgs == null) { localSupportedSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms( algorithmConstraints); } return localSupportedSignAlgs; } void setPeerSupportedSignAlgs( Collection<SignatureAndHashAlgorithm> algorithms) { peerSupportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(algorithms); } Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() { return peerSupportedSignAlgs; } /** * Set the identification protocol. Called from the constructor or * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the * handshake is not yet in progress). */ void setIdentificationProtocol(String protocol) { this.identificationProtocol = protocol; } /** * Prior to handshaking, activate the handshake and initialize the version, * input stream and output stream. */ void activate(ProtocolVersion helloVersion) throws IOException { if (activeProtocols == null) { activeProtocols = getActiveProtocols(); } if (activeProtocols.collection().isEmpty() || activeProtocols.max.v == ProtocolVersion.NONE.v) { throw new SSLHandshakeException("No appropriate protocol"); } if (activeCipherSuites == null) { activeCipherSuites = getActiveCipherSuites(); } if (activeCipherSuites.collection().isEmpty()) { throw new SSLHandshakeException("No appropriate cipher suite"); } // temporary protocol version until the actual protocol version // is negotiated in the Hello exchange. This affects the record // version we sent with the ClientHello. if (!isInitialHandshake) { protocolVersion = activeProtocolVersion; } else { protocolVersion = activeProtocols.max; } if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) { helloVersion = activeProtocols.helloVersion; } // We accumulate digests of the handshake messages so that // we can read/write CertificateVerify and Finished messages, // getting assurance against some particular active attacks. Set<String> localSupportedHashAlgorithms = SignatureAndHashAlgorithm.getHashAlgorithmNames( getLocalSupportedSignAlgs()); handshakeHash = new HandshakeHash(!isClient, needCertVerify, localSupportedHashAlgorithms); // Generate handshake input/output stream. input = new HandshakeInStream(handshakeHash); if (conn != null) { output = new HandshakeOutStream(protocolVersion, helloVersion, handshakeHash, conn); conn.getAppInputStream().r.setHandshakeHash(handshakeHash); conn.getAppInputStream().r.setHelloVersion(helloVersion); conn.getAppOutputStream().r.setHelloVersion(helloVersion); } else { output = new HandshakeOutStream(protocolVersion, helloVersion, handshakeHash, engine); engine.inputRecord.setHandshakeHash(handshakeHash); engine.inputRecord.setHelloVersion(helloVersion); engine.outputRecord.setHelloVersion(helloVersion); } // move state to activated state = -1; }