use of sun.security.ssl.HandshakeMessage in project jdk8u_jdk by JetBrains.
the class Handshaker method kickstart.
/*
* Used to kickstart the negotiation ... either writing a
* ClientHello or a HelloRequest as appropriate, whichever
* the subclass returns. NOP if handshaking's already started.
*/
void kickstart() throws IOException {
if (state >= 0) {
return;
}
HandshakeMessage m = getKickstartMessage();
if (debug != null && Debug.isOn("handshake")) {
m.print(System.out);
}
m.write(output);
output.flush();
state = m.messageType();
}
use of sun.security.ssl.HandshakeMessage in project jdk8u_jdk by JetBrains.
the class ClientHandshaker method serverHelloDone.
/*
* The server's "Hello Done" message is the client's sign that
* it's time to do all the hard work.
*/
private void serverHelloDone(ServerHelloDone mesg) throws IOException {
if (debug != null && Debug.isOn("handshake")) {
mesg.print(System.out);
}
/*
* Always make sure the input has been digested before we
* start emitting data, to ensure the hashes are correctly
* computed for the Finished and CertificateVerify messages
* which we send (here).
*/
input.digestNow();
/*
* FIRST ... if requested, send an appropriate Certificate chain
* to authenticate the client, and remember the associated private
* key to sign the CertificateVerify message.
*/
PrivateKey signingKey = null;
if (certRequest != null) {
X509ExtendedKeyManager km = sslContext.getX509KeyManager();
ArrayList<String> keytypesTmp = new ArrayList<>(4);
for (int i = 0; i < certRequest.types.length; i++) {
String typeName;
switch(certRequest.types[i]) {
case CertificateRequest.cct_rsa_sign:
typeName = "RSA";
break;
case CertificateRequest.cct_dss_sign:
typeName = "DSA";
break;
case CertificateRequest.cct_ecdsa_sign:
// ignore if we do not have EC crypto available
typeName = JsseJce.isEcAvailable() ? "EC" : null;
break;
// case CertificateRequest.cct_dss_ephemeral_dh:
default:
typeName = null;
break;
}
if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
keytypesTmp.add(typeName);
}
}
String alias = null;
int keytypesTmpSize = keytypesTmp.size();
if (keytypesTmpSize != 0) {
String[] keytypes = keytypesTmp.toArray(new String[keytypesTmpSize]);
if (conn != null) {
alias = km.chooseClientAlias(keytypes, certRequest.getAuthorities(), conn);
} else {
alias = km.chooseEngineClientAlias(keytypes, certRequest.getAuthorities(), engine);
}
}
CertificateMsg m1 = null;
if (alias != null) {
X509Certificate[] certs = km.getCertificateChain(alias);
if ((certs != null) && (certs.length != 0)) {
PublicKey publicKey = certs[0].getPublicKey();
if (publicKey != null) {
m1 = new CertificateMsg(certs);
signingKey = km.getPrivateKey(alias);
session.setLocalPrivateKey(signingKey);
session.setLocalCertificates(certs);
}
}
}
if (m1 == null) {
//
if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
m1 = new CertificateMsg(new X509Certificate[0]);
} else {
warningSE(Alerts.alert_no_certificate);
}
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Warning: no suitable certificate found - " + "continuing without client authentication");
}
}
//
if (m1 != null) {
if (debug != null && Debug.isOn("handshake")) {
m1.print(System.out);
}
m1.write(output);
}
}
/*
* SECOND ... send the client key exchange message. The
* procedure used is a function of the cipher suite selected;
* one is always needed.
*/
HandshakeMessage m2;
switch(keyExchange) {
case K_RSA:
case K_RSA_EXPORT:
if (serverKey == null) {
throw new SSLProtocolException("Server did not send certificate message");
}
if (!(serverKey instanceof RSAPublicKey)) {
throw new SSLProtocolException("Server certificate does not include an RSA key");
}
/*
* For RSA key exchange, we randomly generate a new
* pre-master secret and encrypt it with the server's
* public key. Then we save that pre-master secret
* so that we can calculate the keying data later;
* it's a performance speedup not to do that until
* the client's waiting for the server response, but
* more of a speedup for the D-H case.
*
* If the RSA_EXPORT scheme is active, when the public
* key in the server certificate is less than or equal
* to 512 bits in length, use the cert's public key,
* otherwise, the ephemeral one.
*/
PublicKey key;
if (keyExchange == K_RSA) {
key = serverKey;
} else {
// K_RSA_EXPORT
if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
// extraneous ephemeralServerKey check done
// above in processMessage()
key = serverKey;
} else {
if (ephemeralServerKey == null) {
throw new SSLProtocolException("Server did not send" + " a RSA_EXPORT Server Key Exchange message");
}
key = ephemeralServerKey;
}
}
m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion, sslContext.getSecureRandom(), key);
break;
case K_DH_RSA:
case K_DH_DSS:
/*
* For DH Key exchange, we only need to make sure the server
* knows our public key, so we calculate the same pre-master
* secret.
*
* For certs that had DH keys in them, we send an empty
* handshake message (no key) ... we flag this case by
* passing a null "dhPublic" value.
*
* Otherwise we send ephemeral DH keys, unsigned.
*/
// if (useDH_RSA || useDH_DSS)
m2 = new DHClientKeyExchange();
break;
case K_DHE_RSA:
case K_DHE_DSS:
case K_DH_ANON:
if (dh == null) {
throw new SSLProtocolException("Server did not send a DH Server Key Exchange message");
}
m2 = new DHClientKeyExchange(dh.getPublicKey());
break;
case K_ECDHE_RSA:
case K_ECDHE_ECDSA:
case K_ECDH_ANON:
if (ecdh == null) {
throw new SSLProtocolException("Server did not send a ECDH Server Key Exchange message");
}
m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
break;
case K_ECDH_RSA:
case K_ECDH_ECDSA:
if (serverKey == null) {
throw new SSLProtocolException("Server did not send certificate message");
}
if (serverKey instanceof ECPublicKey == false) {
throw new SSLProtocolException("Server certificate does not include an EC key");
}
ECParameterSpec params = ((ECPublicKey) serverKey).getParams();
ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
break;
case K_KRB5:
case K_KRB5_EXPORT:
String sniHostname = null;
for (SNIServerName serverName : requestedServerNames) {
if (serverName instanceof SNIHostName) {
sniHostname = ((SNIHostName) serverName).getAsciiName();
break;
}
}
KerberosClientKeyExchange kerberosMsg = null;
if (sniHostname != null) {
// use first requested SNI hostname
try {
kerberosMsg = new KerberosClientKeyExchange(sniHostname, getAccSE(), protocolVersion, sslContext.getSecureRandom());
} catch (IOException e) {
if (serverNamesAccepted) {
// so it must be used
throw e;
}
// fallback to using hostname
if (debug != null && Debug.isOn("handshake")) {
System.out.println("Warning, cannot use Server Name Indication: " + e.getMessage());
}
}
}
if (kerberosMsg == null) {
String hostname = getHostSE();
if (hostname == null) {
throw new IOException("Hostname is required" + " to use Kerberos cipher suites");
}
kerberosMsg = new KerberosClientKeyExchange(hostname, getAccSE(), protocolVersion, sslContext.getSecureRandom());
}
// Record the principals involved in exchange
session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
m2 = kerberosMsg;
break;
default:
// somethings very wrong
throw new RuntimeException("Unsupported key exchange: " + keyExchange);
}
if (debug != null && Debug.isOn("handshake")) {
m2.print(System.out);
}
m2.write(output);
/*
* THIRD, send a "change_cipher_spec" record followed by the
* "Finished" message. We flush the messages we've queued up, to
* get concurrency between client and server. The concurrency is
* useful as we calculate the master secret, which is needed both
* to compute the "Finished" message, and to compute the keys used
* to protect all records following the change_cipher_spec.
*/
output.doHashes();
output.flush();
/*
* We deferred calculating the master secret and this connection's
* keying data; we do it now. Deferring this calculation is good
* from a performance point of view, since it lets us do it during
* some time that network delays and the server's own calculations
* would otherwise cause to be "dead" in the critical path.
*/
SecretKey preMasterSecret;
switch(keyExchange) {
case K_RSA:
case K_RSA_EXPORT:
preMasterSecret = ((RSAClientKeyExchange) m2).preMaster;
break;
case K_KRB5:
case K_KRB5_EXPORT:
byte[] secretBytes = ((KerberosClientKeyExchange) m2).getUnencryptedPreMasterSecret();
preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret");
break;
case K_DHE_RSA:
case K_DHE_DSS:
case K_DH_ANON:
preMasterSecret = dh.getAgreedSecret(serverDH, true);
break;
case K_ECDHE_RSA:
case K_ECDHE_ECDSA:
case K_ECDH_ANON:
preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey);
break;
case K_ECDH_RSA:
case K_ECDH_ECDSA:
preMasterSecret = ecdh.getAgreedSecret(serverKey);
break;
default:
throw new IOException("Internal error: unknown key exchange " + keyExchange);
}
calculateKeys(preMasterSecret, null);
/*
* FOURTH, if we sent a Certificate, we need to send a signed
* CertificateVerify (unless the key in the client's certificate
* was a Diffie-Hellman key).).
*
* This uses a hash of the previous handshake messages ... either
* a nonfinal one (if the particular implementation supports it)
* or else using the third element in the arrays of hashes being
* computed.
*/
if (signingKey != null) {
CertificateVerify m3;
try {
SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(getPeerSupportedSignAlgs(), signingKey.getAlgorithm(), signingKey);
if (preferableSignatureAlgorithm == null) {
throw new SSLHandshakeException("No supported signature algorithm");
}
String hashAlg = SignatureAndHashAlgorithm.getHashAlgorithmName(preferableSignatureAlgorithm);
if (hashAlg == null || hashAlg.length() == 0) {
throw new SSLHandshakeException("No supported hash algorithm");
}
}
m3 = new CertificateVerify(protocolVersion, handshakeHash, signingKey, session.getMasterSecret(), sslContext.getSecureRandom(), preferableSignatureAlgorithm);
} catch (GeneralSecurityException e) {
fatalSE(Alerts.alert_handshake_failure, "Error signing certificate verify", e);
// NOTREACHED, make compiler happy
m3 = null;
}
if (debug != null && Debug.isOn("handshake")) {
m3.print(System.out);
}
m3.write(output);
output.doHashes();
}
/*
* OK, that's that!
*/
sendChangeCipherAndFinish(false);
}
Aggregations