Search in sources :

Example 1 with HandshakeMessage

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();
}
Also used : HandshakeMessage(sun.security.ssl.HandshakeMessage)

Example 2 with HandshakeMessage

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);
}
Also used : RSAPublicKey(java.security.interfaces.RSAPublicKey) SecretKeySpec(javax.crypto.spec.SecretKeySpec) RSAPublicKey(java.security.interfaces.RSAPublicKey) ECPublicKey(java.security.interfaces.ECPublicKey) X509Certificate(java.security.cert.X509Certificate) SecretKey(javax.crypto.SecretKey) HandshakeMessage(sun.security.ssl.HandshakeMessage) ECPublicKey(java.security.interfaces.ECPublicKey) ECParameterSpec(java.security.spec.ECParameterSpec)

Aggregations

HandshakeMessage (sun.security.ssl.HandshakeMessage)2 X509Certificate (java.security.cert.X509Certificate)1 ECPublicKey (java.security.interfaces.ECPublicKey)1 RSAPublicKey (java.security.interfaces.RSAPublicKey)1 ECParameterSpec (java.security.spec.ECParameterSpec)1 SecretKey (javax.crypto.SecretKey)1 SecretKeySpec (javax.crypto.spec.SecretKeySpec)1