1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  this work for additional information regarding copyright ownership.
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  the License.  You may obtain a copy of the License at
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  See the License for the specific language governing permissions and
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *  limitations under the License.
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.math.BigInteger;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyFactory;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyPair;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.KeyPairGenerator;
25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.NoSuchAlgorithmException;
26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivateKey;
27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PrivilegedExceptionAction;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.PublicKey;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.interfaces.RSAPublicKey;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.Cipher;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.KeyAgreement;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHPublicKey;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHParameterSpec;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHPublicKeySpec;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509ExtendedKeyManager;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509KeyManager;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509TrustManager;
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Server side handshake protocol implementation.
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol operates on top of the Record Protocol.
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It responsible for negotiating a session.
46f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
47f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * The implementation processes inbound client handshake messages,
48f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * creates and sends respond messages. Outbound messages are supplied
49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to Record Protocol. Detected errors are reported to the Alert protocol.
50f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7.4.
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol.</a>
53f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class ServerHandshakeImpl extends HandshakeProtocol {
56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // private key used in key exchange
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private PrivateKey privKey;
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates Server Handshake Implementation
62f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param owner
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public ServerHandshakeImpl(Object owner) {
66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(owner);
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        status = NEED_UNWRAP;
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Start session negotiation
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
73f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void start() {
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session == null) { // initial handshake
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = NEED_UNWRAP;
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return; // wait client hello
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (clientHello != null && this.status != FINISHED) {
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // current negotiation has not completed
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return; // ignore
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
83f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // renegotiation
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sendHelloRequest();
86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        status = NEED_UNWRAP;
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
89adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Proceses inbound handshake messages
91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bytes
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
93f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
94adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unwrap(byte[] bytes) {
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        io_stream.append(bytes);
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (io_stream.available() > 0) {
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int handshakeType;
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int length;
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            io_stream.mark();
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeType = io_stream.read();
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                length = io_stream.readUint24();
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (io_stream.available() < length) {
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    io_stream.reset();
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                switch (handshakeType) {
110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 1: // CLIENT_HELLO
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (clientHello != null && this.status != FINISHED) {
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // Client hello has been received during handshake
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            unexpectedMessage();
114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            return;
115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // if protocol planed to send Hello Request message
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // - cancel this demand.
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    needSendHelloRequest = false;
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clientHello = new ClientHello(io_stream, length);
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (nonBlocking) {
12190b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                        delegatedTasks.add(new DelegatedTask(new Runnable() {
12290b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                            public void run() {
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                processClientHello();
124f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson                            }
12590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                        }, this));
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    processClientHello();
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 11: //    CLIENT CERTIFICATE
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (isResuming || certificateRequest == null
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || serverHelloDone == null || clientCert != null) {
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clientCert = new CertificateMessage(io_stream, length);
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (clientCert.certs.length == 0) {
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (parameters.getNeedClientAuth()) {
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
1414ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                       "HANDSHAKE FAILURE: no client certificate received");
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
144b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                        String authType = clientCert.getAuthType();
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        try {
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            parameters.getTrustManager().checkClientTrusted(
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    clientCert.certs, authType);
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } catch (CertificateException e) {
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            fatalAlert(AlertProtocol.BAD_CERTIFICATE,
1504ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                       "Untrusted Client Certificate ", e);
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session.peerCertificates = clientCert.certs;
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 15: // CERTIFICATE_VERIFY
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (isResuming
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || clientKeyExchange == null
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || clientCert == null
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || clientKeyExchange.isEmpty() //client certificate
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                           // contains fixed DH
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                           // parameters
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || certificateVerify != null
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || changeCipherSpecReceived) {
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    certificateVerify = new CertificateVerify(io_stream, length);
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
170b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    String authType = clientCert.getAuthType();
171b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    DigitalSignature ds = new DigitalSignature(authType);
172b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    ds.init(clientCert.certs[0]);
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    byte[] md5_hash = null;
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    byte[] sha_hash = null;
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
176b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    if ("RSA".equals(authType)) {
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        md5_hash = io_stream.getDigestMD5withoutLast();
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        sha_hash = io_stream.getDigestSHAwithoutLast();
179b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    } else if ("DSA".equals(authType)) {
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        sha_hash = io_stream.getDigestSHAwithoutLast();
181b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    // The Signature should be empty in case of anonymous signature algorithm:
182b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    // } else if ("DH".equals(authType)) {
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ds.setMD5(md5_hash);
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ds.setSHA(sha_hash);
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!ds.verifySignature(certificateVerify.signedHash)) {
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        fatalAlert(AlertProtocol.DECRYPT_ERROR,
1884ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                   "DECRYPT ERROR: CERTIFICATE_VERIFY incorrect signature");
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 16: // CLIENT_KEY_EXCHANGE
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (isResuming
193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || serverHelloDone == null
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || clientKeyExchange != null
1954ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                            || (clientCert == null && parameters.getNeedClientAuth())) {
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
199aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    if (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA
200aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                            || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        clientKeyExchange = new ClientKeyExchange(io_stream,
202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                length, serverHello.server_version[1] == 1,
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                true);
204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        Cipher c = null;
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        try {
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
207b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                            c.init(Cipher.UNWRAP_MODE, privKey);
208b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                            preMasterSecret = c.unwrap(clientKeyExchange.exchange_keys,
209b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                                                       "preMasterSecret",
210b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                                                       Cipher.SECRET_KEY).getEncoded();
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // check preMasterSecret:
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            if (preMasterSecret.length != 48
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    || preMasterSecret[0] != clientHello.client_version[0]
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    || preMasterSecret[1] != clientHello.client_version[1]) {
215adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                // incorrect preMasterSecret
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                // prevent an attack (see TLS 1.0 spec., 7.4.7.1.)
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                preMasterSecret = new byte[48];
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                parameters.getSecureRandom().nextBytes(
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                        preMasterSecret);
220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } catch (Exception e) {
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            fatalAlert(AlertProtocol.INTERNAL_ERROR,
2234ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                       "INTERNAL ERROR", e);
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else { // diffie hellman key exchange
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        clientKeyExchange = new ClientKeyExchange(io_stream,
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                length, serverHello.server_version[1] == 1,
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                false);
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (clientKeyExchange.isEmpty()) {
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // TODO check that client cert. DH params
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // matched server cert. DH params
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
233f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                            // client cert. contains fixed DH parameters
2344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                            preMasterSecret = ((DHPublicKey) clientCert.certs[0].getPublicKey()).getY().toByteArray();
235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } else {
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            try {
2374ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                KeyFactory kf = KeyFactory.getInstance("DH");
2384ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                KeyAgreement agreement = KeyAgreement.getInstance("DH");
2394ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                PublicKey clientPublic = kf.generatePublic(new DHPublicKeySpec(
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                new BigInteger(
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                        1,
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                        clientKeyExchange.exchange_keys),
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                serverKeyExchange.par1,
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                                serverKeyExchange.par2));
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                agreement.init(privKey);
246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                agreement.doPhase(clientPublic, true);
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                preMasterSecret = agreement.generateSecret();
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            } catch (Exception e) {
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                fatalAlert(AlertProtocol.INTERNAL_ERROR,
2504ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                           "INTERNAL ERROR", e);
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                return;
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    computerMasterSecret();
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 20: // FINISHED
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!isResuming && !changeCipherSpecReceived) {
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clientFinished = new Finished(io_stream, length);
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    verifyFinished(clientFinished.getData());
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.context = parameters.getServerSessionContext();
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    parameters.getServerSessionContext().putSession(session);
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!isResuming) {
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        sendChangeCipherSpec();
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
272adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session.lastAccessedTime = System.currentTimeMillis();
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        status = FINISHED;
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                default:
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    unexpectedMessage();
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // io stream dosn't contain complete handshake message
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                io_stream.reset();
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes SSLv2 Hello message
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @ see TLS 1.0 spec., E.1. Version 2 client hello
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bytes
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
292f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unwrapSSLv2(byte[] bytes) {
294f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        io_stream.append(bytes);
295f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        io_stream.mark();
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
297f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson            clientHello = new ClientHello(io_stream);
298f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        } catch (IOException e) {
299f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson            io_stream.reset();
300f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson            return;
301f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        }
302f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        if (nonBlocking) {
30390b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes            delegatedTasks.add(new DelegatedTask(new Runnable() {
30490b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                public void run() {
30590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                    processClientHello();
30690b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                }
30790b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes            }, this));
308f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson            return;
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
310f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson        processClientHello();
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
314f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
315f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Processes Client Hello message.
316f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Server responds to client hello message with server hello
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * and (if necessary) server certificate, server key exchange,
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * certificate request, and server hello done messages.
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void processClientHello() {
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        CipherSuite cipher_suite;
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // check that clientHello contains CompressionMethod.null
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        checkCompression: {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            for (int i = 0; i < clientHello.compression_methods.length; i++) {
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (clientHello.compression_methods[i] == 0) {
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break checkCompression;
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
3314ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                       "HANDSHAKE FAILURE. Incorrect client hello message");
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
333f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
3343e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom        byte[] server_version = clientHello.client_version;
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!ProtocolVersion.isSupported(clientHello.client_version)) {
3363e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom            if (clientHello.client_version[0] >= 3) {
3373e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                // Protocol from the future, admit that the newest thing we know is TLSv1
3383e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                server_version = ProtocolVersion.TLSv1.version;
3393e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom            } else {
3403e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                fatalAlert(AlertProtocol.PROTOCOL_VERSION,
3413e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                           "PROTOCOL VERSION. Unsupported client version "
3423e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                           + clientHello.client_version[0]
3433e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                           + clientHello.client_version[1]);
3443e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom            }
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        isResuming = false;
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        FIND: if (clientHello.session_id.length != 0) {
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // client wishes to reuse session
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            SSLSessionImpl sessionToResume;
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean reuseCurrent = false;
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // reuse current session
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (session != null
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    && Arrays.equals(session.id, clientHello.session_id)) {
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (session.isValid()) {
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    isResuming = true;
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break FIND;
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                reuseCurrent = true;
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
363f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // find session in cash
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            sessionToResume = findSessionToResume(clientHello.session_id);
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (sessionToResume == null || !sessionToResume.isValid()) {
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!parameters.getEnableSessionCreation()) {
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (reuseCurrent) {
369adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // we can continue current session
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        sendWarningAlert(AlertProtocol.NO_RENEGOTIATION);
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        status = NOT_HANDSHAKING;
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        clearMessages();
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
375f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson                    // throw AlertException
376f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson                    fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created");
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session = null;
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session = (SSLSessionImpl)sessionToResume.clone();
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                isResuming = true;
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
384adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
385adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
386adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cipher_suite = session.cipherSuite;
387adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // clientHello.cipher_suites must include at least cipher_suite from the session
388adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            checkCipherSuite: {
389adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                for (int i = 0; i < clientHello.cipher_suites.length; i++) {
390adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (cipher_suite.equals(clientHello.cipher_suites[i])) {
391adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break checkCipherSuite;
392adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
393adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
394adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
3954ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                           "HANDSHAKE FAILURE. Incorrect client hello message");
396adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
397adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
398adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cipher_suite = selectSuite(clientHello.cipher_suites);
399adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (cipher_suite == null) {
400adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "HANDSHAKE FAILURE. NO COMMON SUITE");
401adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
402adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!parameters.getEnableSessionCreation()) {
403adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
4044ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                           "SSL Session may not be created");
405adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
40607ced5b685db42cc46a9567600c1f37326ab8f8aElliott Hughes            session = new SSLSessionImpl(cipher_suite, parameters.getSecureRandom());
4077329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (engineOwner != null) {
4087329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort());
4097329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } else {
4107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                session.setPeer(socketOwner.getInetAddress().getHostName(), socketOwner.getPort());
4117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
413adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
4143e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom        recordProtocol.setVersion(server_version);
4153e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom        session.protocol = ProtocolVersion.getByVersion(server_version);
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        session.clientRandom = clientHello.random;
417f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // create server hello message
419f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        serverHello = new ServerHello(parameters.getSecureRandom(),
4203e6dd45baa0d7f9b4fa06f4ade76e088b59cc7bfBrian Carlstrom                server_version,
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session.getId(), cipher_suite, (byte) 0); //CompressionMethod.null
422adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        session.serverRandom = serverHello.random;
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        send(serverHello);
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            sendChangeCipherSpec();
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
428f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        //    create and send server certificate message if needed
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!cipher_suite.isAnonymous()) { // need to send server certificate
431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            X509Certificate[] certs = null;
4324ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            String certType = cipher_suite.getServerKeyType();
4334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            if (certType == null) {
4344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO CERT TYPE FOR " + cipher_suite.getName());
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // obtain certificates from key manager
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            String alias = null;
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            X509KeyManager km = parameters.getKeyManager();
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (km instanceof X509ExtendedKeyManager) {
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                X509ExtendedKeyManager ekm = (X509ExtendedKeyManager)km;
4417329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (this.socketOwner != null) {
4427329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                    alias = ekm.chooseServerAlias(certType, null,
4437329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                            this.socketOwner);
4447329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                } else {
445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    alias = ekm.chooseEngineServerAlias(certType, null,
446adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            this.engineOwner);
4477329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (alias != null) {
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    certs = ekm.getCertificateChain(alias);
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
4527329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                alias = km.chooseServerAlias(certType, null, this.socketOwner);
4537329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                if (alias != null) {
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    certs = km.getCertificateChain(alias);
4557329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                }
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (certs == null) {
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "NO SERVER CERTIFICATE FOUND");
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session.localCertificates = certs;
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            serverCert = new CertificateMessage(certs);
464b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            privKey = km.getPrivateKey(alias);
465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(serverCert);
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // create and send server key exchange message if needed
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        RSAPublicKey rsakey = null;
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        DHPublicKeySpec dhkeySpec = null;
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] hash = null;
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        BigInteger p = null;
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        BigInteger g = null;
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        KeyPairGenerator kpg = null;
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
478aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom            if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
479f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                PublicKey pk = serverCert.certs[0].getPublicKey();
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (getRSAKeyLength(pk) > 512) {
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // key is longer than 512 bits
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    kpg = KeyPairGenerator.getInstance("RSA");
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    kpg.initialize(512);
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
485aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom            } else if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS
486aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS_EXPORT
487aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA
488aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA_EXPORT
489aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon
490aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    || cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_DH_anon_EXPORT) {
4914ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                kpg = KeyPairGenerator.getInstance("DH");
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                p = new BigInteger(1, DHParameters.getPrime());
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                g = new BigInteger("2");
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                DHParameterSpec spec = new DHParameterSpec(p, g);
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                kpg.initialize(spec);
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (Exception e) {
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (kpg != null) {
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // need to send server key exchange message
503b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            DigitalSignature ds = new DigitalSignature(cipher_suite.authType);
504adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            KeyPair kp = null;
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                kp = kpg.genKeyPair();
507aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
508adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    rsakey = (RSAPublicKey) kp.getPublic();
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    DHPublicKey dhkey = (DHPublicKey) kp.getPublic();
5114ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    KeyFactory kf = KeyFactory.getInstance("DH");
5124ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    dhkeySpec = kf.getKeySpec(dhkey, DHPublicKeySpec.class);
513adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
514adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (!cipher_suite.isAnonymous()) { // calculate signed_params
515f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // init by private key which correspond to
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // server certificate
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ds.init(privKey);
519f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // use emphemeral key for key exchange
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    privKey = kp.getPrivate();
522adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ds.update(clientHello.getRandom());
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    ds.update(serverHello.getRandom());
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    byte[] tmp;
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    byte[] tmpLength = new byte[2];
527f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes//FIXME 1_byte==0x00
528aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                    if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
529c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        tmp = ServerKeyExchange.toUnsignedByteArray(rsakey.getModulus());
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
531adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[1] = (byte) (tmp.length & 0xFF);
532adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmpLength);
533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmp);
534c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        tmp = ServerKeyExchange.toUnsignedByteArray(rsakey.getPublicExponent());
535adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
536adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[1] = (byte) (tmp.length & 0xFF);
537c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        ds.update(tmpLength);
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmp);
539adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
540c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getP());
541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[1] = (byte) (tmp.length & 0xFF);
543c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        ds.update(tmpLength);
544adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmp);
545c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getG());
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[1] = (byte) (tmp.length & 0xFF);
548c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        ds.update(tmpLength);
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmp);
550c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        tmp = ServerKeyExchange.toUnsignedByteArray(dhkeySpec.getY());
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[0] = (byte) ((tmp.length & 0xFF00) >>> 8);
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        tmpLength[1] = (byte) (tmp.length & 0xFF);
553c7fd8fd75e74f59e583df1e4fea0d221891e2000Costin Manolache                        ds.update(tmpLength);
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        ds.update(tmp);
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
556adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    hash = ds.sign();
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    privKey = kp.getPrivate(); // use emphemeral key for key exchange
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (Exception e) {
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.INTERNAL_ERROR, "INTERNAL ERROR", e);
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
564aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom            if (cipher_suite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                serverKeyExchange = new ServerKeyExchange(rsakey.getModulus(),
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        rsakey.getPublicExponent(), null, hash);
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                serverKeyExchange = new ServerKeyExchange(p,
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        g, dhkeySpec.getY(), hash);
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(serverKeyExchange);
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // CERTIFICATE_REQUEST
575adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        certRequest: if (parameters.getWantClientAuth()
576adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                || parameters.getNeedClientAuth()) {
577adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            X509Certificate[] accepted;
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                X509TrustManager tm = parameters.getTrustManager();
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                accepted = tm.getAcceptedIssuers();
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (ClassCastException e) {
582adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // don't send certificateRequest
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                break certRequest;
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
5854ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            byte[] requestedClientCertTypes = { CipherSuite.TLS_CT_RSA_SIGN,
5864ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                                CipherSuite.TLS_CT_DSS_SIGN };
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            certificateRequest = new CertificateRequest(
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    requestedClientCertTypes, accepted);
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(certificateRequest);
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // SERVER_HELLO_DONE
593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        serverHelloDone = new ServerHelloDone();
594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        send(serverHelloDone);
595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        status = NEED_UNWRAP;
596adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
597f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates and sends finished message
600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
601f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
602adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void makeFinished() {
603adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] verify_data;
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        boolean isTLS = (serverHello.server_version[1] == 1); // TLS 1.0 protocol
605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isTLS) {
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verify_data = new byte[12];
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computerVerifyDataTLS("server finished", verify_data);
608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else { // SSL 3.0 protocol (http://wp.netscape.com/eng/ssl3)
609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verify_data = new byte[36];
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computerVerifyDataSSLv3(SSLv3Constants.server, verify_data);
611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        serverFinished = new Finished(verify_data);
613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        send(serverFinished);
614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (isTLS) {
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                computerReferenceVerifyDataTLS("client finished");
617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
618f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                computerReferenceVerifyDataSSLv3(SSLv3Constants.client);
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = NEED_UNWRAP;
621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session.lastAccessedTime = System.currentTimeMillis();
623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = FINISHED;
624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // find sesssion in the session hash
628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLSessionImpl findSessionToResume(byte[] session_id) {
629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return (SSLSessionImpl)parameters.getServerSessionContext().getSession(session_id);
630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
631f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // find appropriate cipher_suite in the client suites
6334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom    private CipherSuite selectSuite(CipherSuite[] clientSuites) {
6344ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom        for (CipherSuite clientSuite : clientSuites) {
6354ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            if (!clientSuite.supported) {
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                continue;
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
6384ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            for (CipherSuite enabledCipherSuite : parameters.getEnabledCipherSuitesMember()) {
6394ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                if (clientSuite.equals(enabledCipherSuite)) {
6404ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    return clientSuite;
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return null;
645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
648f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson     * Processes inbound ChangeCipherSpec message
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
650f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
651f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes    public void receiveChangeCipherSpec() {
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (serverFinished == null) {
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unexpectedMessage();
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                changeCipherSpecReceived = true;
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if ((parameters.getNeedClientAuth() && clientCert == null)
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    || clientKeyExchange == null
6617c935d4e4ca990334200cf5eb4fbcfac718c6b45gcollins                    || (clientCert != null && clientCert.certs.length > 0
6626882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                            && !clientKeyExchange.isEmpty()
6636882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom                            && certificateVerify == null)) {
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unexpectedMessage();
665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                changeCipherSpecReceived = true;
667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (serverHello.server_version[1] == 1) {
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                computerReferenceVerifyDataTLS("client finished");
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                computerReferenceVerifyDataSSLv3(SSLv3Constants.client);
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
677