} catch (PrivilegedActionException e) { subject = null; if (debug != null && Debug.isOn("session")) { System.out.println("Attempt to obtain" + " subject failed!"); } } if (subject != null) { // Eliminate dependency on KerberosPrincipal Set<Principal> principals = subject.getPrincipals(Principal.class); if (!principals.contains(localPrincipal)) { resumingSession = false; if (debug != null && Debug.isOn("session")) { System.out.println("Subject identity" + " is not the same"); } } else { if (debug != null && Debug.isOn("session")) System.out.println("Subject identity" + " is same"); } } else { resumingSession = false; if (debug != null && Debug.isOn("session")) System.out.println("Kerberos credentials are" + " not present in the current Subject;" + " check if " + " javax.security.auth.useSubjectAsCreds" + " system property has been set to false"); } } } if (resumingSession) { CipherSuite suite = previous.getSuite(); // verify that the ciphersuite from the cached session // is in the list of client requested ciphersuites and // we have it enabled if ((isNegotiable(suite) == false) || (mesg.getCipherSuites().contains(suite) == false)) { resumingSession = false; } else { // everything looks ok, set the ciphersuite // this should be done last when we are sure we // will resume setCipherSuite(suite); } } if (resumingSession) { session = previous; if (debug != null && (Debug.isOn("handshake") || Debug.isOn("session"))) { System.out.println("%% Resuming " + session); } } } } // else client did not try to resume // // If client hasn't specified a session we can resume, start a // new one and choose its cipher suite and compression options. // Unless new session creation is disabled for this connection! // if (session == null) { if (!enableNewSession) { throw new SSLException("Client did not resume a session"); } supportedCurves = (SupportedEllipticCurvesExtension) mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES); // We only need to handle the "signature_algorithm" extension // for full handshakes and TLS 1.2 or later. if (protocolVersion.v >= ProtocolVersion.TLS12.v) { SignatureAlgorithmsExtension signAlgs = (SignatureAlgorithmsExtension)mesg.extensions.get( ExtensionType.EXT_SIGNATURE_ALGORITHMS); if (signAlgs != null) { Collection<SignatureAndHashAlgorithm> peerSignAlgs = signAlgs.getSignAlgorithms(); if (peerSignAlgs == null || peerSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No peer supported signature algorithms"); } Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms( peerSignAlgs); if (supportedPeerSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature and hash algorithm " + "in common"); } setPeerSupportedSignAlgs(supportedPeerSignAlgs); } // else, need to use peer implicit supported signature algs } session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL, getLocalSupportedSignAlgs(), sslContext.getSecureRandom(), getHostAddressSE(), getPortSE()); if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) { session.setPeerSupportedSignatureAlgorithms( peerSupportedSignAlgs); } // else, we will set the implicit peer supported signature // algorithms in chooseCipherSuite() } // set the handshake session setHandshakeSessionSE(session); // choose cipher suite and corresponding private key chooseCipherSuite(mesg); session.setSuite(cipherSuite); session.setLocalPrivateKey(privateKey); // chooseCompression(mesg); } else { // set the handshake session setHandshakeSessionSE(session); } if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (resumingSession) { handshakeHash.setCertificateVerifyAlg(null); } handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg()); } m1.cipherSuite = cipherSuite; m1.sessionId = session.getSessionId(); m1.compression_method = session.getCompression(); if (secureRenegotiation) { // For ServerHellos that are initial handshakes, then the // "renegotiated_connection" field in "renegotiation_info" // extension is of zero length. // // For ServerHellos that are renegotiating, this field contains // the concatenation of client_verify_data and server_verify_data. // // Note that for initial handshakes, both the clientVerifyData // variable and serverVerifyData variable are of zero length. HelloExtension serverHelloRI = new RenegotiationInfoExtension( clientVerifyData, serverVerifyData); m1.extensions.add(serverHelloRI); } if (debug != null && Debug.isOn("handshake")) { m1.print(System.out); System.out.println("Cipher suite: " + session.getSuite()); } m1.write(output); // // If we are resuming a session, we finish writing handshake // messages right now and then finish. // if (resumingSession) { calculateConnectionKeys(session.getMasterSecret()); sendChangeCipherAndFinish(false); return; } /* * SECOND, write the server Certificate(s) if we need to. * * NOTE: while an "anonymous RSA" mode is explicitly allowed by * the protocol, we can't support it since all of the SSL flavors * defined in the protocol spec are explicitly stated to require * using RSA certificates. */ if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) { // Server certificates are omitted for Kerberos ciphers } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) { if (certs == null) { throw new RuntimeException("no certificates"); } CertificateMsg m2 = new CertificateMsg(certs); /* * Set local certs in the SSLSession, output * debug info, and then actually write to the client. */ session.setLocalCertificates(certs); if (debug != null && Debug.isOn("handshake")) { m2.print(System.out); } m2.write(output); // XXX has some side effects with OS TCP buffering, // leave it out for now // let client verify chain in the meantime... // output.flush(); } else { if (certs != null) { throw new RuntimeException("anonymous keyexchange with certs"); } } /* * THIRD, the ServerKeyExchange message ... iff it's needed. * * It's usually needed unless there's an encryption-capable * RSA cert, or a D-H cert. The notable exception is that * exportable ciphers used with big RSA keys need to downgrade * to use short RSA keys, even when the key/cert encrypts OK. */ ServerKeyExchange m3; switch (keyExchange) { case K_RSA: case K_KRB5: case K_KRB5_EXPORT: // no server key exchange for RSA or KRB5 ciphersuites m3 = null; break; case K_RSA_EXPORT: if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) { try { m3 = new RSA_ServerKeyExchange( tempPublicKey, privateKey, clnt_random, svr_random, sslContext.getSecureRandom()); privateKey = tempPrivateKey; } catch (GeneralSecurityException e) { throwSSLException ("Error generating RSA server key exchange", e); m3 = null; // make compiler happy } } else { // RSA_EXPORT with short key, don't need ServerKeyExchange m3 = null; } break; case K_DHE_RSA: case K_DHE_DSS: try { m3 = new DH_ServerKeyExchange(dh, privateKey, clnt_random.random_bytes, svr_random.random_bytes, sslContext.getSecureRandom(), preferableSignatureAlgorithm, protocolVersion); } catch (GeneralSecurityException e) { throwSSLException("Error generating DH server key exchange", e); m3 = null; // make compiler happy } break; case K_DH_ANON: m3 = new DH_ServerKeyExchange(dh, protocolVersion); break; case K_ECDHE_RSA: case K_ECDHE_ECDSA: case K_ECDH_ANON: try { m3 = new ECDH_ServerKeyExchange(ecdh, privateKey, clnt_random.random_bytes, svr_random.random_bytes, sslContext.getSecureRandom(), preferableSignatureAlgorithm, protocolVersion); } catch (GeneralSecurityException e) { throwSSLException( "Error generating ECDH server key exchange", e); m3 = null; // make compiler happy } break; case K_ECDH_RSA: case K_ECDH_ECDSA: // ServerKeyExchange not used for fixed ECDH m3 = null; break; default: throw new RuntimeException("internal error: " + keyExchange); } if (m3 != null) { if (debug != null && Debug.isOn("handshake")) { m3.print(System.out); } m3.write(output); } // // FOURTH, the CertificateRequest message. The details of // the message can be affected by the key exchange algorithm // in use. For example, certs with fixed Diffie-Hellman keys // are only useful with the DH_DSS and DH_RSA key exchange // algorithms. // // Needed only if server requires client to authenticate self. // Illegal for anonymous flavors, so we need to check that. // // CertificateRequest is omitted for Kerberos ciphers if (doClientAuth != SSLEngineImpl.clauth_none && keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON && keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) { CertificateRequest m4; X509Certificate caCerts[]; Collection<SignatureAndHashAlgorithm> localSignAlgs = null; if (protocolVersion.v >= ProtocolVersion.TLS12.v) { // We currently use all local upported signature and hash // algorithms. However, to minimize the computation cost // of requested hash algorithms, we may use a restricted // set of signature algorithms in the future. localSignAlgs = getLocalSupportedSignAlgs(); if (localSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature algorithm"); } Set<String> localHashAlgs = SignatureAndHashAlgorithm.getHashAlgorithmNames( localSignAlgs); if (localHashAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature algorithm"); } handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs); } caCerts = sslContext.getX509TrustManager().getAcceptedIssuers(); m4 = new CertificateRequest(caCerts, keyExchange, localSignAlgs, protocolVersion); if (debug != null && Debug.isOn("handshake")) { m4.print(System.out); } m4.write(output); } else { if (protocolVersion.v >= ProtocolVersion.TLS12.v) { handshakeHash.setCertificateVerifyAlg(null); } } /* * FIFTH, say ServerHelloDone. */ ServerHelloDone m5 = new ServerHelloDone(); if (debug != null && Debug.isOn("handshake")) { m5.print(System.out); } m5.write(output); /* * Flush any buffered messages so the client will see them. * Ideally, all the messages above go in a single network level * message to the client. Without big Certificate chains, it's * going to be the common case. */ output.flush(); } /* * Choose cipher suite from among those supported by client. Sets * the cipherSuite and keyExchange variables. */ private void chooseCipherSuite(ClientHello mesg) throws IOException { for (CipherSuite suite : mesg.getCipherSuites().collection()) { if (isNegotiable(suite) == false) { continue; } if (doClientAuth == SSLEngineImpl.clauth_required) { if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) { continue; } } if (trySetCipherSuite(suite) == false) { continue; } return; } fatalSE(Alerts.alert_handshake_failure, "no cipher suites in common"); } /** * Set the given CipherSuite, if possible. Return the result. * The call succeeds if the CipherSuite is available and we have * the necessary certificates to complete the handshake. We don't * check if the CipherSuite is actually enabled. * * If successful, this method also generates ephemeral keys if * required for this ciphersuite. This may take some time, so this * method should only be called if you really want to use the * CipherSuite. * * This method is called from chooseCipherSuite() in this class. */ boolean trySetCipherSuite(CipherSuite suite) { /* * If we're resuming a session we know we can * support this key exchange algorithm and in fact * have already cached the result of it in * the session state. */ if (resumingSession) { return true; } if (suite.isNegotiable() == false) { return false; } // must not negotiate the obsoleted weak cipher suites. if (protocolVersion.v >= suite.obsoleted) { return false; } // must not negotiate unsupported cipher suites. if (protocolVersion.v < suite.supported) { return false; } KeyExchange keyExchange = suite.keyExchange; // null out any existing references privateKey = null; certs = null; dh = null; tempPrivateKey = null; tempPublicKey = null; Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null; if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) { supportedSignAlgs = peerSupportedSignAlgs; } else { SignatureAndHashAlgorithm algorithm = null; // we may optimize the performance switch (keyExchange) { // If the negotiated key exchange algorithm is one of // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), // behave as if client had sent the value {sha1,rsa}. case K_RSA: case K_DHE_RSA: case K_DH_RSA: // case K_RSA_PSK: case K_ECDH_RSA: case K_ECDHE_RSA: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.RSA.value, 0); break; // If the negotiated key exchange algorithm is one of // (DHE_DSS, DH_DSS), behave as if the client had // sent the value {sha1,dsa}. case K_DHE_DSS: case K_DH_DSS: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.DSA.value, 0); break; // If the negotiated key exchange algorithm is one of // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client // had sent value {sha1,ecdsa}. case K_ECDH_ECDSA: case K_ECDHE_ECDSA: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.ECDSA.value, 0); break; default: // no peer supported signature algorithms } if (algorithm == null) { supportedSignAlgs = Collections.<SignatureAndHashAlgorithm>emptySet(); } else { supportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(1); supportedSignAlgs.add(algorithm); } // Sets the peer supported signature algorithm to use in KM // temporarily. session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs); } }Lines 501–1000 of 1678. Previous lines Load more
} catch (PrivilegedActionException e) { subject = null; if (debug != null && Debug.isOn("session")) { System.out.println("Attempt to obtain" + " subject failed!"); } } if (subject != null) { // Eliminate dependency on KerberosPrincipal Set<Principal> principals = subject.getPrincipals(Principal.class); if (!principals.contains(localPrincipal)) { resumingSession = false; if (debug != null && Debug.isOn("session")) { System.out.println("Subject identity" + " is not the same"); } } else { if (debug != null && Debug.isOn("session")) System.out.println("Subject identity" + " is same"); } } else { resumingSession = false; if (debug != null && Debug.isOn("session")) System.out.println("Kerberos credentials are" + " not present in the current Subject;" + " check if " + " javax.security.auth.useSubjectAsCreds" + " system property has been set to false"); } } } if (resumingSession) { CipherSuite suite = previous.getSuite(); // verify that the ciphersuite from the cached session // is in the list of client requested ciphersuites and // we have it enabled if ((isNegotiable(suite) == false) || (mesg.getCipherSuites().contains(suite) == false)) { resumingSession = false; } else { // everything looks ok, set the ciphersuite // this should be done last when we are sure we // will resume setCipherSuite(suite); } } if (resumingSession) { session = previous; if (debug != null && (Debug.isOn("handshake") || Debug.isOn("session"))) { System.out.println("%% Resuming " + session); } } } } // else client did not try to resume // // If client hasn't specified a session we can resume, start a // new one and choose its cipher suite and compression options. // Unless new session creation is disabled for this connection! // if (session == null) { if (!enableNewSession) { throw new SSLException("Client did not resume a session"); } supportedCurves = (SupportedEllipticCurvesExtension) mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES); // We only need to handle the "signature_algorithm" extension // for full handshakes and TLS 1.2 or later. if (protocolVersion.v >= ProtocolVersion.TLS12.v) { SignatureAlgorithmsExtension signAlgs = (SignatureAlgorithmsExtension)mesg.extensions.get( ExtensionType.EXT_SIGNATURE_ALGORITHMS); if (signAlgs != null) { Collection<SignatureAndHashAlgorithm> peerSignAlgs = signAlgs.getSignAlgorithms(); if (peerSignAlgs == null || peerSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No peer supported signature algorithms"); } Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms( peerSignAlgs); if (supportedPeerSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature and hash algorithm " + "in common"); } setPeerSupportedSignAlgs(supportedPeerSignAlgs); } // else, need to use peer implicit supported signature algs } session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL, getLocalSupportedSignAlgs(), sslContext.getSecureRandom(), getHostAddressSE(), getPortSE()); if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) { session.setPeerSupportedSignatureAlgorithms( peerSupportedSignAlgs); } // else, we will set the implicit peer supported signature // algorithms in chooseCipherSuite() } // set the handshake session setHandshakeSessionSE(session); // choose cipher suite and corresponding private key chooseCipherSuite(mesg); session.setSuite(cipherSuite); session.setLocalPrivateKey(privateKey); // chooseCompression(mesg); } else { // set the handshake session setHandshakeSessionSE(session); } if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (resumingSession) { handshakeHash.setCertificateVerifyAlg(null); } handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg()); } m1.cipherSuite = cipherSuite; m1.sessionId = session.getSessionId(); m1.compression_method = session.getCompression(); if (secureRenegotiation) { // For ServerHellos that are initial handshakes, then the // "renegotiated_connection" field in "renegotiation_info" // extension is of zero length. // // For ServerHellos that are renegotiating, this field contains // the concatenation of client_verify_data and server_verify_data. // // Note that for initial handshakes, both the clientVerifyData // variable and serverVerifyData variable are of zero length. HelloExtension serverHelloRI = new RenegotiationInfoExtension( clientVerifyData, serverVerifyData); m1.extensions.add(serverHelloRI); } if (debug != null && Debug.isOn("handshake")) { m1.print(System.out); System.out.println("Cipher suite: " + session.getSuite()); } m1.write(output); // // If we are resuming a session, we finish writing handshake // messages right now and then finish. // if (resumingSession) { calculateConnectionKeys(session.getMasterSecret()); sendChangeCipherAndFinish(false); return; } /* * SECOND, write the server Certificate(s) if we need to. * * NOTE: while an "anonymous RSA" mode is explicitly allowed by * the protocol, we can't support it since all of the SSL flavors * defined in the protocol spec are explicitly stated to require * using RSA certificates. */ if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) { // Server certificates are omitted for Kerberos ciphers } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) { if (certs == null) { throw new RuntimeException("no certificates"); } CertificateMsg m2 = new CertificateMsg(certs); /* * Set local certs in the SSLSession, output * debug info, and then actually write to the client. */ session.setLocalCertificates(certs); if (debug != null && Debug.isOn("handshake")) { m2.print(System.out); } m2.write(output); // XXX has some side effects with OS TCP buffering, // leave it out for now // let client verify chain in the meantime... // output.flush(); } else { if (certs != null) { throw new RuntimeException("anonymous keyexchange with certs"); } } /* * THIRD, the ServerKeyExchange message ... iff it's needed. * * It's usually needed unless there's an encryption-capable * RSA cert, or a D-H cert. The notable exception is that * exportable ciphers used with big RSA keys need to downgrade * to use short RSA keys, even when the key/cert encrypts OK. */ ServerKeyExchange m3; switch (keyExchange) { case K_RSA: case K_KRB5: case K_KRB5_EXPORT: // no server key exchange for RSA or KRB5 ciphersuites m3 = null; break; case K_RSA_EXPORT: if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) { try { m3 = new RSA_ServerKeyExchange( tempPublicKey, privateKey, clnt_random, svr_random, sslContext.getSecureRandom()); privateKey = tempPrivateKey; } catch (GeneralSecurityException e) { throwSSLException ("Error generating RSA server key exchange", e); m3 = null; // make compiler happy } } else { // RSA_EXPORT with short key, don't need ServerKeyExchange m3 = null; } break; case K_DHE_RSA: case K_DHE_DSS: try { m3 = new DH_ServerKeyExchange(dh, privateKey, clnt_random.random_bytes, svr_random.random_bytes, sslContext.getSecureRandom(), preferableSignatureAlgorithm, protocolVersion); } catch (GeneralSecurityException e) { throwSSLException("Error generating DH server key exchange", e); m3 = null; // make compiler happy } break; case K_DH_ANON: m3 = new DH_ServerKeyExchange(dh, protocolVersion); break; case K_ECDHE_RSA: case K_ECDHE_ECDSA: case K_ECDH_ANON: try { m3 = new ECDH_ServerKeyExchange(ecdh, privateKey, clnt_random.random_bytes, svr_random.random_bytes, sslContext.getSecureRandom(), preferableSignatureAlgorithm, protocolVersion); } catch (GeneralSecurityException e) { throwSSLException( "Error generating ECDH server key exchange", e); m3 = null; // make compiler happy } break; case K_ECDH_RSA: case K_ECDH_ECDSA: // ServerKeyExchange not used for fixed ECDH m3 = null; break; default: throw new RuntimeException("internal error: " + keyExchange); } if (m3 != null) { if (debug != null && Debug.isOn("handshake")) { m3.print(System.out); } m3.write(output); } // // FOURTH, the CertificateRequest message. The details of // the message can be affected by the key exchange algorithm // in use. For example, certs with fixed Diffie-Hellman keys // are only useful with the DH_DSS and DH_RSA key exchange // algorithms. // // Needed only if server requires client to authenticate self. // Illegal for anonymous flavors, so we need to check that. // // CertificateRequest is omitted for Kerberos ciphers if (doClientAuth != SSLEngineImpl.clauth_none && keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON && keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) { CertificateRequest m4; X509Certificate caCerts[]; Collection<SignatureAndHashAlgorithm> localSignAlgs = null; if (protocolVersion.v >= ProtocolVersion.TLS12.v) { // We currently use all local upported signature and hash // algorithms. However, to minimize the computation cost // of requested hash algorithms, we may use a restricted // set of signature algorithms in the future. localSignAlgs = getLocalSupportedSignAlgs(); if (localSignAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature algorithm"); } Set<String> localHashAlgs = SignatureAndHashAlgorithm.getHashAlgorithmNames( localSignAlgs); if (localHashAlgs.isEmpty()) { throw new SSLHandshakeException( "No supported signature algorithm"); } handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs); } caCerts = sslContext.getX509TrustManager().getAcceptedIssuers(); m4 = new CertificateRequest(caCerts, keyExchange, localSignAlgs, protocolVersion); if (debug != null && Debug.isOn("handshake")) { m4.print(System.out); } m4.write(output); } else { if (protocolVersion.v >= ProtocolVersion.TLS12.v) { handshakeHash.setCertificateVerifyAlg(null); } } /* * FIFTH, say ServerHelloDone. */ ServerHelloDone m5 = new ServerHelloDone(); if (debug != null && Debug.isOn("handshake")) { m5.print(System.out); } m5.write(output); /* * Flush any buffered messages so the client will see them. * Ideally, all the messages above go in a single network level * message to the client. Without big Certificate chains, it's * going to be the common case. */ output.flush(); } /* * Choose cipher suite from among those supported by client. Sets * the cipherSuite and keyExchange variables. */ private void chooseCipherSuite(ClientHello mesg) throws IOException { for (CipherSuite suite : mesg.getCipherSuites().collection()) { if (isNegotiable(suite) == false) { continue; } if (doClientAuth == SSLEngineImpl.clauth_required) { if ((suite.keyExchange == K_DH_ANON) || (suite.keyExchange == K_ECDH_ANON)) { continue; } } if (trySetCipherSuite(suite) == false) { continue; } return; } fatalSE(Alerts.alert_handshake_failure, "no cipher suites in common"); } /** * Set the given CipherSuite, if possible. Return the result. * The call succeeds if the CipherSuite is available and we have * the necessary certificates to complete the handshake. We don't * check if the CipherSuite is actually enabled. * * If successful, this method also generates ephemeral keys if * required for this ciphersuite. This may take some time, so this * method should only be called if you really want to use the * CipherSuite. * * This method is called from chooseCipherSuite() in this class. */ boolean trySetCipherSuite(CipherSuite suite) { /* * If we're resuming a session we know we can * support this key exchange algorithm and in fact * have already cached the result of it in * the session state. */ if (resumingSession) { return true; } if (suite.isNegotiable() == false) { return false; } // must not negotiate the obsoleted weak cipher suites. if (protocolVersion.v >= suite.obsoleted) { return false; } // must not negotiate unsupported cipher suites. if (protocolVersion.v < suite.supported) { return false; } KeyExchange keyExchange = suite.keyExchange; // null out any existing references privateKey = null; certs = null; dh = null; tempPrivateKey = null; tempPublicKey = null; Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null; if (protocolVersion.v >= ProtocolVersion.TLS12.v) { if (peerSupportedSignAlgs != null) { supportedSignAlgs = peerSupportedSignAlgs; } else { SignatureAndHashAlgorithm algorithm = null; // we may optimize the performance switch (keyExchange) { // If the negotiated key exchange algorithm is one of // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA), // behave as if client had sent the value {sha1,rsa}. case K_RSA: case K_DHE_RSA: case K_DH_RSA: // case K_RSA_PSK: case K_ECDH_RSA: case K_ECDHE_RSA: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.RSA.value, 0); break; // If the negotiated key exchange algorithm is one of // (DHE_DSS, DH_DSS), behave as if the client had // sent the value {sha1,dsa}. case K_DHE_DSS: case K_DH_DSS: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.DSA.value, 0); break; // If the negotiated key exchange algorithm is one of // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client // had sent value {sha1,ecdsa}. case K_ECDH_ECDSA: case K_ECDHE_ECDSA: algorithm = SignatureAndHashAlgorithm.valueOf( HashAlgorithm.SHA1.value, SignatureAlgorithm.ECDSA.value, 0); break; default: // no peer supported signature algorithms } if (algorithm == null) { supportedSignAlgs = Collections.<SignatureAndHashAlgorithm>emptySet(); } else { supportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(1); supportedSignAlgs.add(algorithm); } // Sets the peer supported signature algorithm to use in KM // temporarily. session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs); } }