/** * Get the active cipher suites. * * <p>In TLS 1.1, many weak or vulnerable cipher suites were obsoleted, such as * TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT negotiate these cipher suites in * TLS 1.1 or later mode. * * <p>Therefore, when the active protocols only include TLS 1.1 or later, the client cannot * request to negotiate those obsoleted cipher suites. That is, the obsoleted suites should not be * included in the client hello. So we need to create a subset of the enabled cipher suites, the * active cipher suites, which does not contain obsoleted cipher suites of the minimum active * protocol. * * <p>Return empty list instead of null if no active cipher suites. */ CipherSuiteList getActiveCipherSuites() { if (activeCipherSuites == null) { if (activeProtocols == null) { activeProtocols = getActiveProtocols(); } ArrayList<CipherSuite> suites = new ArrayList<>(); if (!(activeProtocols.collection().isEmpty()) && activeProtocols.min.v != ProtocolVersion.NONE.v) { for (CipherSuite suite : enabledCipherSuites.collection()) { if (suite.obsoleted > activeProtocols.min.v && suite.supported <= activeProtocols.max.v) { if (algorithmConstraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { suites.add(suite); } } else if (debug != null && Debug.isOn("verbose")) { if (suite.obsoleted <= activeProtocols.min.v) { System.out.println("Ignoring obsoleted cipher suite: " + suite); } else { System.out.println("Ignoring unsupported cipher suite: " + suite); } } } } activeCipherSuites = new CipherSuiteList(suites); } return activeCipherSuites; }
/* * Get the active protocol versions. * * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted, * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT * negotiate these cipher suites in TLS 1.1 or later mode. * * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the * only enabled cipher suite, the client cannot request TLS 1.1 or * later, even though TLS 1.1 or later is enabled. We need to create a * subset of the enabled protocols, called the active protocols, which * contains protocols appropriate to the list of enabled Ciphersuites. * * Return empty list instead of null if no active protocol versions. */ ProtocolList getActiveProtocols() { if (activeProtocols == null) { ArrayList<ProtocolVersion> protocols = new ArrayList<>(4); for (ProtocolVersion protocol : enabledProtocols.collection()) { boolean found = false; for (CipherSuite suite : enabledCipherSuites.collection()) { if (suite.isAvailable() && suite.obsoleted > protocol.v && suite.supported <= protocol.v) { if (algorithmConstraints.permits( EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { protocols.add(protocol); found = true; break; } else if (debug != null && Debug.isOn("verbose")) { System.out.println("Ignoring disabled cipher suite: " + suite + " for " + protocol); } } else if (debug != null && Debug.isOn("verbose")) { System.out.println("Ignoring unsupported cipher suite: " + suite + " for " + protocol); } } if (!found && (debug != null) && Debug.isOn("handshake")) { System.out.println("No available cipher suite for " + protocol); } } activeProtocols = new ProtocolList(protocols); } return activeProtocols; }
/** * 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; }