Search in sources :

Example 1 with KeyExchange

use of sun.security.ssl.CipherSuite.KeyExchange in project jdk8u_jdk by JetBrains.

the class ServerHandshaker method trySetCipherSuite.

/**
     * 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) {
                // 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;
                // sent the value {sha1,dsa}.
                case K_DHE_DSS:
                case K_DH_DSS:
                    algorithm = SignatureAndHashAlgorithm.valueOf(HashAlgorithm.SHA1.value, SignatureAlgorithm.DSA.value, 0);
                    break;
                // 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:
            }
            if (algorithm == null) {
                supportedSignAlgs = Collections.<SignatureAndHashAlgorithm>emptySet();
            } else {
                supportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(1);
                supportedSignAlgs.add(algorithm);
                supportedSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms(algorithmConstraints, supportedSignAlgs);
            // May be no default activated signature algorithm, but
            // let the following process make the final decision.
            }
            // Sets the peer supported signature algorithm to use in KM
            // temporarily.
            session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
        }
    }
    switch(keyExchange) {
        case K_RSA:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            break;
        case K_RSA_EXPORT:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            try {
                if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
                    if (!setupEphemeralRSAKeys(suite.exportable)) {
                        return false;
                    }
                }
            } catch (RuntimeException e) {
                // could not determine keylength, ignore key
                return false;
            }
            break;
        case K_DHE_RSA:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "RSA", privateKey);
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            setupEphemeralDHKeys(suite.exportable, privateKey);
            break;
        case K_ECDHE_RSA:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "RSA", privateKey);
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            if (setupEphemeralECDHKeys() == false) {
                return false;
            }
            break;
        case K_DHE_DSS:
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "DSA");
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            // need DSS certs for authentication
            if (setupPrivateKeyAndChain("DSA") == false) {
                return false;
            }
            setupEphemeralDHKeys(suite.exportable, privateKey);
            break;
        case K_ECDHE_ECDSA:
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "ECDSA");
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            if (setupEphemeralECDHKeys() == false) {
                return false;
            }
            break;
        case K_ECDH_RSA:
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            setupStaticECDHKeys();
            break;
        case K_ECDH_ECDSA:
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            setupStaticECDHKeys();
            break;
        case K_KRB5:
        case K_KRB5_EXPORT:
            // need Kerberos Key
            if (!setupKerberosKeys()) {
                return false;
            }
            break;
        case K_DH_ANON:
            // no certs needed for anonymous
            setupEphemeralDHKeys(suite.exportable, null);
            break;
        case K_ECDH_ANON:
            // no certs needed for anonymous
            if (setupEphemeralECDHKeys() == false) {
                return false;
            }
            break;
        default:
            // internal error, unknown key exchange
            throw new RuntimeException("Unrecognized cipherSuite: " + suite);
    }
    setCipherSuite(suite);
    // set the peer implicit supported signature algorithms
    if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
        if (peerSupportedSignAlgs == null) {
            setPeerSupportedSignAlgs(supportedSignAlgs);
        // we had alreay update the session
        }
    }
    return true;
}
Also used : KeyExchange(sun.security.ssl.CipherSuite.KeyExchange) SignatureAndHashAlgorithm(sun.security.ssl.SignatureAndHashAlgorithm)

Example 2 with KeyExchange

use of sun.security.ssl.CipherSuite.KeyExchange in project Bytecoder by mirkosertic.

the class ServerHandshaker method trySetCipherSuite.

/**
 * 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.obsoletes(suite)) {
        return false;
    }
    // must not negotiate unsupported cipher suites.
    if (!protocolVersion.supports(suite)) {
        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.useTLS12PlusSpec()) {
        if (peerSupportedSignAlgs != null) {
            supportedSignAlgs = peerSupportedSignAlgs;
        } else {
            SignatureAndHashAlgorithm algorithm = null;
            // we may optimize the performance
            switch(keyExchange) {
                // 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;
                // sent the value {sha1,dsa}.
                case K_DHE_DSS:
                case K_DH_DSS:
                    algorithm = SignatureAndHashAlgorithm.valueOf(HashAlgorithm.SHA1.value, SignatureAlgorithm.DSA.value, 0);
                    break;
                // 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:
            }
            if (algorithm == null) {
                supportedSignAlgs = Collections.<SignatureAndHashAlgorithm>emptySet();
            } else {
                supportedSignAlgs = new ArrayList<SignatureAndHashAlgorithm>(1);
                supportedSignAlgs.add(algorithm);
                supportedSignAlgs = SignatureAndHashAlgorithm.getSupportedAlgorithms(algorithmConstraints, supportedSignAlgs);
            // May be no default activated signature algorithm, but
            // let the following process make the final decision.
            }
            // Sets the peer supported signature algorithm to use in KM
            // temporarily.
            session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
        }
    }
    // The named group used for ECDHE and FFDHE.
    NamedGroup namedGroup = null;
    switch(keyExchange) {
        case K_RSA:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            break;
        case K_RSA_EXPORT:
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            try {
                if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
                    if (!setupEphemeralRSAKeys(suite.exportable)) {
                        return false;
                    }
                }
            } catch (RuntimeException e) {
                // could not determine keylength, ignore key
                return false;
            }
            break;
        case K_DHE_RSA:
            // FFDHE extension will not be used.
            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) && (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
                namedGroup = requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
                if (namedGroup == null) {
                    // no match found, cannot use this cipher suite.
                    return false;
                }
            }
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.useTLS12PlusSpec()) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "RSA", privateKey);
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
            break;
        case K_ECDHE_RSA:
            // Is ECDHE cipher suite usable for the connection?
            namedGroup = (requestedGroups != null) ? requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) : SupportedGroupsExtension.getPreferredECGroup(algorithmConstraints);
            if (namedGroup == null) {
                // no match found, cannot use this ciphersuite
                return false;
            }
            // need RSA certs for authentication
            if (setupPrivateKeyAndChain("RSA") == false) {
                return false;
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.useTLS12PlusSpec()) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "RSA", privateKey);
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            setupEphemeralECDHKeys(namedGroup);
            break;
        case K_DHE_DSS:
            // See comment in K_DHE_RSA case.
            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) && (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
                namedGroup = requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
                if (namedGroup == null) {
                    // no match found, cannot use this cipher suite.
                    return false;
                }
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.useTLS12PlusSpec()) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "DSA");
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            // need DSS certs for authentication
            if (setupPrivateKeyAndChain("DSA") == false) {
                return false;
            }
            setupEphemeralDHKeys(namedGroup, suite.exportable, privateKey);
            break;
        case K_ECDHE_ECDSA:
            // Is ECDHE cipher suite usable for the connection?
            namedGroup = (requestedGroups != null) ? requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) : SupportedGroupsExtension.getPreferredECGroup(algorithmConstraints);
            if (namedGroup == null) {
                // no match found, cannot use this ciphersuite
                return false;
            }
            // get preferable peer signature algorithm for server key exchange
            if (protocolVersion.useTLS12PlusSpec()) {
                preferableSignatureAlgorithm = SignatureAndHashAlgorithm.getPreferableAlgorithm(supportedSignAlgs, "ECDSA");
                if (preferableSignatureAlgorithm == null) {
                    if ((debug != null) && Debug.isOn("handshake")) {
                        System.out.println("No signature and hash algorithm for cipher " + suite);
                    }
                    return false;
                }
            }
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            setupEphemeralECDHKeys(namedGroup);
            break;
        case K_ECDH_RSA:
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            setupStaticECDHKeys();
            break;
        case K_ECDH_ECDSA:
            // need EC cert
            if (setupPrivateKeyAndChain("EC") == false) {
                return false;
            }
            setupStaticECDHKeys();
            break;
        case K_DH_ANON:
            // See comment in K_DHE_RSA case.
            if ((!useLegacyEphemeralDHKeys) && (!suite.exportable) && (requestedGroups != null) && requestedGroups.hasFFDHEGroup()) {
                namedGroup = requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_FFDHE);
                if (namedGroup == null) {
                    // no match found, cannot use this cipher suite.
                    return false;
                }
            }
            // no certs needed for anonymous
            setupEphemeralDHKeys(namedGroup, suite.exportable, null);
            break;
        case K_ECDH_ANON:
            // Is ECDHE cipher suite usable for the connection?
            namedGroup = (requestedGroups != null) ? requestedGroups.getPreferredGroup(algorithmConstraints, NamedGroupType.NAMED_GROUP_ECDHE) : SupportedGroupsExtension.getPreferredECGroup(algorithmConstraints);
            if (namedGroup == null) {
                // no match found, cannot use this ciphersuite
                return false;
            }
            // no certs needed for anonymous
            setupEphemeralECDHKeys(namedGroup);
            break;
        default:
            ClientKeyExchangeService p = ClientKeyExchangeService.find(keyExchange.name);
            if (p == null) {
                // internal error, unknown key exchange
                throw new RuntimeException("Unrecognized cipherSuite: " + suite);
            }
            // need service creds
            if (serviceCreds == null) {
                AccessControlContext acc = getAccSE();
                serviceCreds = p.getServiceCreds(acc);
                if (serviceCreds != null) {
                    if (debug != null && Debug.isOn("handshake")) {
                        System.out.println("Using serviceCreds");
                    }
                }
                if (serviceCreds == null) {
                    return false;
                }
            }
            break;
    }
    setCipherSuite(suite);
    // set the peer implicit supported signature algorithms
    if (protocolVersion.useTLS12PlusSpec()) {
        if (peerSupportedSignAlgs == null) {
            setPeerSupportedSignAlgs(supportedSignAlgs);
        // we had alreay update the session
        }
    }
    return true;
}
Also used : KeyExchange(sun.security.ssl.CipherSuite.KeyExchange) SignatureAndHashAlgorithm(sun.security.ssl.SignatureAndHashAlgorithm)

Example 3 with KeyExchange

use of sun.security.ssl.CipherSuite.KeyExchange in project Bytecoder by mirkosertic.

the class HandshakeStateManager method update.

void update(HandshakeMessage handshakeMessage, boolean isAbbreviated) throws SSLProtocolException {
    byte handshakeType = (byte) handshakeMessage.messageType();
    String exceptionMsg = "Handshake message sequence violation, " + handshakeType;
    if (debugIsOn) {
        System.out.println("update handshake state: " + toString(handshakeType));
    }
    boolean hasPresentState = false;
    switch(handshakeType) {
        case HandshakeMessage.ht_hello_request:
            // Add the upcoming states.
            if (!upcomingStates.isEmpty()) {
                // A ClientHello message should be followed.
                upcomingStates.add(HS_CLIENT_HELLO);
            }
            break;
        case HandshakeMessage.ht_client_hello:
            // Check and update the present state.
            if (!upcomingStates.isEmpty()) {
                // The current state should be HS_CLIENT_HELLO.
                HandshakeState handshakeState = upcomingStates.pop();
                if (handshakeState != HS_CLIENT_HELLO) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            }
            // Add the upcoming states.
            ClientHello clientHello = (ClientHello) handshakeMessage;
            if (isDTLS) {
                // Is it an initial ClientHello message?
                if (clientHello.cookie == null || clientHello.cookie.length == 0) {
                    // Is it an abbreviated handshake?
                    if (clientHello.sessionId.length() != 0) {
                        // A HelloVerifyRequest message or a ServerHello
                        // message may follow the abbreviated session
                        // resuming handshake request.
                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
                        alternatives.add(HS_SERVER_HELLO);
                    } else {
                        // A HelloVerifyRequest message should follow
                        // the initial ClientHello message.
                        upcomingStates.add(HS_HELLO_VERIFY_REQUEST);
                    }
                } else {
                    // A HelloVerifyRequest may be followed if the cookie
                    // cannot be verified.
                    upcomingStates.add(HS_SERVER_HELLO);
                    alternatives.add(HS_HELLO_VERIFY_REQUEST);
                }
            } else {
                upcomingStates.add(HS_SERVER_HELLO);
            }
            break;
        case HandshakeMessage.ht_hello_verify_request:
            // Check and update the present state.
            if (!upcomingStates.isEmpty()) {
                // The current state should be HS_HELLO_VERIFY_REQUEST.
                HandshakeState handshakeState = upcomingStates.pop();
                HandshakeState alternative = null;
                if (!alternatives.isEmpty()) {
                    alternative = alternatives.pop();
                }
                if ((handshakeState != HS_HELLO_VERIFY_REQUEST) && (alternative != HS_HELLO_VERIFY_REQUEST)) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            } else {
                // No present state.
                throw new SSLProtocolException(exceptionMsg);
            }
            // Add the upcoming states.
            upcomingStates.add(HS_CLIENT_HELLO);
            break;
        case HandshakeMessage.ht_server_hello:
            // Check and update the present state.
            if (!upcomingStates.isEmpty()) {
                // The current state should be HS_SERVER_HELLO
                HandshakeState handshakeState = upcomingStates.pop();
                HandshakeState alternative = null;
                if (!alternatives.isEmpty()) {
                    alternative = alternatives.pop();
                }
                if ((handshakeState != HS_SERVER_HELLO) && (alternative != HS_SERVER_HELLO)) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            } else {
                // No present state.
                throw new SSLProtocolException(exceptionMsg);
            }
            // Add the upcoming states.
            ServerHello serverHello = (ServerHello) handshakeMessage;
            HelloExtensions hes = serverHello.extensions;
            if (isAbbreviated) {
                // Not support SessionTicket extension yet.
                // 
                // // Mandatory NewSessionTicket message
                // if (hasSessionTicketExt) {
                // upcomingStates.add(HS_NEW_SESSION_TICKET);
                // }
                // Mandatory server ChangeCipherSpec and Finished messages
                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
                upcomingStates.add(HS_SERVER_FINISHED);
                // Mandatory client ChangeCipherSpec and Finished messages
                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
                upcomingStates.add(HS_CLEINT_FINISHED);
            } else {
                // Not support SupplementalData extension yet.
                // 
                // boolean hasSupplementalDataExt =
                // (hes.get(HandshakeMessage.ht_supplemental_data) != null);
                // Not support CertificateURL extension yet.
                // 
                // boolean hasCertificateUrlExt =
                // (hes.get(ExtensionType EXT_CLIENT_CERTIFICATE_URL)
                // != null);
                // Not support SupplementalData extension yet.
                // 
                // // Optional SupplementalData message
                // if (hasSupplementalDataExt) {
                // upcomingStates.add(HS_SERVER_SUPPLEMENTAL_DATA);
                // }
                // Need server Certificate message or not?
                KeyExchange keyExchange = serverHello.cipherSuite.keyExchange;
                if ((keyExchange != K_KRB5) && (keyExchange != K_KRB5_EXPORT) && (keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
                    // Mandatory Certificate message
                    upcomingStates.add(HS_SERVER_CERTIFICATE);
                }
                // Optional CertificateStatus message
                if (hes.get(ExtensionType.EXT_STATUS_REQUEST) != null || hes.get(ExtensionType.EXT_STATUS_REQUEST_V2) != null) {
                    upcomingStates.add(HS_CERTIFICATE_STATUS);
                }
                // Need ServerKeyExchange message or not?
                if ((keyExchange == K_RSA_EXPORT) || (keyExchange == K_DHE_RSA) || (keyExchange == K_DHE_DSS) || (keyExchange == K_DH_ANON) || (keyExchange == K_ECDHE_RSA) || (keyExchange == K_ECDHE_ECDSA) || (keyExchange == K_ECDH_ANON)) {
                    // Optional ServerKeyExchange message
                    upcomingStates.add(HS_SERVER_KEY_EXCHANGE);
                }
                // Optional CertificateRequest message
                upcomingStates.add(HS_CERTIFICATE_REQUEST);
                // Mandatory ServerHelloDone message
                upcomingStates.add(HS_SERVER_HELLO_DONE);
                // Not support SupplementalData extension yet.
                // 
                // // Optional SupplementalData message
                // if (hasSupplementalDataExt) {
                // upcomingStates.add(HS_CLIENT_SUPPLEMENTAL_DATA);
                // }
                // Optional client Certificate message
                upcomingStates.add(HS_CLIENT_CERTIFICATE);
                // Not support CertificateURL extension yet.
                // 
                // // Alternative CertificateURL message, optional too.
                // //
                // // Please put CertificateURL rather than Certificate
                // // message in the alternatives list.  So that we can
                // // simplify the process of this alternative pair later.
                // if (hasCertificateUrlExt) {
                // alternatives.add(HS_CERTIFICATE_URL);
                // }
                // Mandatory ClientKeyExchange message
                upcomingStates.add(HS_CLIENT_KEY_EXCHANGE);
                // Optional CertificateVerify message
                upcomingStates.add(HS_CERTIFICATE_VERIFY);
                // Mandatory client ChangeCipherSpec and Finished messages
                upcomingStates.add(HS_CLIENT_CHANGE_CIPHER_SPEC);
                upcomingStates.add(HS_CLEINT_FINISHED);
                // Not support SessionTicket extension yet.
                // 
                // // Mandatory NewSessionTicket message
                // if (hasSessionTicketExt) {
                // upcomingStates.add(HS_NEW_SESSION_TICKET);
                // }
                // Mandatory server ChangeCipherSpec and Finished messages
                upcomingStates.add(HS_SERVER_CHANGE_CIPHER_SPEC);
                upcomingStates.add(HS_SERVER_FINISHED);
            }
            break;
        case HandshakeMessage.ht_certificate:
            // Check and update the present state.
            while (!upcomingStates.isEmpty()) {
                HandshakeState handshakeState = upcomingStates.pop();
                if (handshakeState.handshakeType == handshakeType) {
                    hasPresentState = true;
                    // the alternative list.
                    if ((handshakeState != HS_CLIENT_CERTIFICATE) && (handshakeState != HS_SERVER_CERTIFICATE)) {
                        throw new SSLProtocolException(exceptionMsg);
                    }
                    // Is it an expected client Certificate message?
                    boolean isClientMessage = false;
                    if (!upcomingStates.isEmpty()) {
                        // If the next expected message is ClientKeyExchange,
                        // this one should be an expected client Certificate
                        // message.
                        HandshakeState nextState = upcomingStates.getFirst();
                        if (nextState == HS_CLIENT_KEY_EXCHANGE) {
                            isClientMessage = true;
                        }
                    }
                    if (isClientMessage) {
                        if (handshakeState != HS_CLIENT_CERTIFICATE) {
                            throw new SSLProtocolException(exceptionMsg);
                        }
                    // Not support CertificateURL extension yet.
                    /**
                     *****************************************
                     *                        // clear up the alternatives list
                     *                        if (!alternatives.isEmpty()) {
                     *                            HandshakeState alternative = alternatives.pop();
                     *
                     *                            if (alternative != HS_CERTIFICATE_URL) {
                     *                                throw new SSLProtocolException(exceptionMsg);
                     *                            }
                     *                        }
                     *******************************************
                     */
                    } else {
                        if ((handshakeState != HS_SERVER_CERTIFICATE)) {
                            throw new SSLProtocolException(exceptionMsg);
                        }
                    }
                    break;
                } else if (!handshakeState.isOptional) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            // Otherwise, looking for next state track.
            }
            // No present state.
            if (!hasPresentState) {
                throw new SSLProtocolException(exceptionMsg);
            }
            break;
        /**
         **********************************************
         */
        case HandshakeMessage.ht_certificate_url:
            // Check and update the present state.
            while (!upcomingStates.isEmpty()) {
                // The current state should be HS_CLIENT_CERTIFICATE.
                // 
                // Note that we won't put HS_CLIENT_CERTIFICATE into
                // the alternative list.
                HandshakeState handshakeState = upcomingStates.pop();
                if (handshakeState.handshakeType == HS_CLIENT_CERTIFICATE.handshakeType) {
                    hasPresentState = true;
                    // Look for HS_CERTIFICATE_URL state track.
                    if (!alternatives.isEmpty()) {
                        HandshakeState alternative = alternatives.pop();
                        if (alternative != HS_CERTIFICATE_URL) {
                            throw new SSLProtocolException(exceptionMsg);
                        }
                    } else {
                        // No alternative CertificateUR state track.
                        throw new SSLProtocolException(exceptionMsg);
                    }
                    if ((handshakeState != HS_CLIENT_CERTIFICATE)) {
                        throw new SSLProtocolException(exceptionMsg);
                    }
                    break;
                } else if (!handshakeState.isOptional) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            // Otherwise, looking for next state track.
            }
            // No present state.
            if (!hasPresentState) {
                // No present state.
                throw new SSLProtocolException(exceptionMsg);
            }
            break;
        default:
            // Check and update the present state.
            while (!upcomingStates.isEmpty()) {
                HandshakeState handshakeState = upcomingStates.pop();
                if (handshakeState.handshakeType == handshakeType) {
                    hasPresentState = true;
                    break;
                } else if (!handshakeState.isOptional) {
                    throw new SSLProtocolException(exceptionMsg);
                }
            // Otherwise, looking for next state track.
            }
            // No present state.
            if (!hasPresentState) {
                throw new SSLProtocolException(exceptionMsg);
            }
    }
    if (debugIsOn) {
        for (HandshakeState handshakeState : upcomingStates) {
            System.out.println("upcoming handshake states: " + handshakeState);
        }
        for (HandshakeState handshakeState : alternatives) {
            System.out.println("upcoming handshake alternative state: " + handshakeState);
        }
    }
}
Also used : HandshakeState(sun.security.ssl.HandshakeStateManager.HandshakeState) SSLProtocolException(javax.net.ssl.SSLProtocolException) KeyExchange(sun.security.ssl.CipherSuite.KeyExchange)

Aggregations

KeyExchange (sun.security.ssl.CipherSuite.KeyExchange)3 SignatureAndHashAlgorithm (sun.security.ssl.SignatureAndHashAlgorithm)2 SSLProtocolException (javax.net.ssl.SSLProtocolException)1 HandshakeState (sun.security.ssl.HandshakeStateManager.HandshakeState)1