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.security.Key;
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.PublicKey;
28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException;
29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate;
30adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.Arrays;
31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.Cipher;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.KeyAgreement;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHKey;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.interfaces.DHPublicKey;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHParameterSpec;
36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.crypto.spec.DHPublicKeySpec;
37b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstromimport javax.crypto.spec.SecretKeySpec;
38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.X509ExtendedKeyManager;
39b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstromimport javax.net.ssl.X509KeyManager;
406d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condraimport javax.net.ssl.X509TrustManager;
41b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstromimport javax.security.auth.x500.X500Principal;
42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Client side handshake protocol implementation.
45adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Handshake protocol operates on top of the Record Protocol.
46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * It is responsible for session negotiating.
47f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
48f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson * The implementation processes inbound server handshake messages,
49f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes * creates and sends respond messages. Outbound messages are supplied
50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * to Record Protocol. Detected errors are reported to the Alert protocol.
51f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see <a href="http://www.ietf.org/rfc/rfc2246.txt">TLS 1.0 spec., 7. The
53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * TLS Handshake Protocol</a>
54f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes *
55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
56f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughespublic class ClientHandshakeImpl extends HandshakeProtocol {
57f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates Client Handshake Implementation
60f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     *
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param owner
62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    ClientHandshakeImpl(Object owner) {
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(owner);
65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
66f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts handshake
69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
70f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     */
71f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void start() {
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session == null) { // initial handshake
74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session = findSessionToResume();
75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else { // start session renegotiation
76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (clientHello != null && this.status != FINISHED) {
77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // current negotiation has not completed
78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return; // ignore
79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!session.isValid()) {
81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session = null;
82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session != null) {
85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isResuming = true;
86f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        } else if (parameters.getEnableSessionCreation()){
87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isResuming = false;
88adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session = new SSLSessionImpl(parameters.getSecureRandom());
897329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (engineOwner != null) {
907329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort());
917329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } else {
926d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra                session.setPeer(socketOwner.getPeerHostName(), socketOwner.getPeerPort());
937329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
944ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols());
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recordProtocol.setVersion(session.protocol.version);
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "SSL Session may not be created ");
98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        startSession();
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
101f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts renegotiation on a new session
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void renegotiateNewSession() {
107f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        if (parameters.getEnableSessionCreation()){
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            isResuming = false;
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session = new SSLSessionImpl(parameters.getSecureRandom());
1107329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            if (engineOwner != null) {
1117329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom                session.setPeer(engineOwner.getPeerHost(), engineOwner.getPeerPort());
1127329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            } else {
1136d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra                session.setPeer(socketOwner.getPeerHostName(), socketOwner.getPeerPort());
1147329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom            }
1154ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom            session.protocol = ProtocolVersion.getLatestVersion(parameters.getEnabledProtocols());
116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            recordProtocol.setVersion(session.protocol.version);
117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            startSession();
118adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = NOT_HANDSHAKING;
120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            sendWarningAlert(AlertProtocol.NO_RENEGOTIATION);
121f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        }
122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts/resumes session
126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void startSession() {
128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        CipherSuite[] cipher_suites;
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cipher_suites = new CipherSuite[] { session.cipherSuite };
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            cipher_suites = parameters.getEnabledCipherSuitesMember();
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        clientHello = new ClientHello(parameters.getSecureRandom(),
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                session.protocol.version, session.id, cipher_suites);
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        session.clientRandom = clientHello.random;
137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        send(clientHello);
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        status = NEED_UNWRAP;
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
142f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson     * Processes inbound handshake messages
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bytes
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
145f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unwrap(byte[] bytes) {
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (this.delegatedTaskErr != null) {
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Exception e = this.delegatedTaskErr;
149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.delegatedTaskErr = null;
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            this.fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Error in delegated task", e);
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int handshakeType;
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        io_stream.append(bytes);
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        while (io_stream.available() > 0) {
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            io_stream.mark();
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            int length;
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeType = io_stream.read();
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                length = io_stream.readUint24();
160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (io_stream.available() < length) {
161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    io_stream.reset();
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                switch (handshakeType) {
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 0: // HELLO_REQUEST
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // we don't need to take this message into account
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // during FINISH message verification, so remove it
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    io_stream.removeFromMarkedPosition();
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (clientHello != null
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            && (clientFinished == null || serverFinished == null)) {
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        //currently negotiating - ignore
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        break;
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // renegotiate
175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (session.isValid()) {
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session = (SSLSessionImpl) session.clone();
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        isResuming = true;
178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        startSession();
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // if SSLSession is invalidated (e.g. timeout limit is
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        // exceeded) connection can't resume the session.
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        renegotiateNewSession();
183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 2: // SERVER_HELLO
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (clientHello == null || serverHello != null) {
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverHello = new ServerHello(io_stream, length);
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    //check protocol version
1934ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    ProtocolVersion servProt = ProtocolVersion.getByVersion(serverHello.server_version);
194f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    String[] enabled = parameters.getEnabledProtocols();
195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    find: {
196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        for (int i = 0; i < enabled.length; i++) {
1974ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                            if (servProt.equals(ProtocolVersion.getByName(enabled[i]))) {
198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                break find;
199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
2024ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                   "Bad server hello protocol version");
203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
204f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // check compression method
206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (serverHello.compression_method != 0) {
207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
2084ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                   "Bad server hello compression method");
209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
210f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
211adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    //check cipher_suite
212adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    CipherSuite[] enabledSuites = parameters.getEnabledCipherSuitesMember();
213adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    find: {
214adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        for (int i = 0; i < enabledSuites.length; i++) {
2154ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                            if (serverHello.cipher_suite.equals(enabledSuites[i])) {
216adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                break find;
217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            }
218adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
2204ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                   "Bad server hello cipher suite");
221f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes                    }
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (isResuming) {
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (serverHello.session_id.length == 0) {
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // server is not willing to establish the new connection
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // using specified session
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            isResuming = false;
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } else if (!Arrays.equals(serverHello.session_id, clientHello.session_id)) {
229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            isResuming = false;
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } else if (!session.protocol.equals(servProt)) {
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
2324ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                       "Bad server hello protocol version");
2334ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                        } else if (!session.cipherSuite.equals(serverHello.cipher_suite)) {
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
2354ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                                       "Bad server hello cipher suite");
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (serverHello.server_version[1] == 1) {
238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            computerReferenceVerifyDataTLS("server finished");
239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        } else {
240adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            computerReferenceVerifyDataSSLv3(SSLv3Constants.server);
241adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
242adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
243adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.protocol = servProt;
244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    recordProtocol.setVersion(session.protocol.version);
245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.cipherSuite = serverHello.cipher_suite;
246f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson                    session.id = serverHello.session_id.clone();
247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.serverRandom = serverHello.random;
248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 11: // CERTIFICATE
250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (serverHello == null || serverKeyExchange != null
251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || serverCert != null || isResuming) {
252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverCert = new CertificateMessage(io_stream, length);
256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 12: // SERVER_KEY_EXCHANGE
258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (serverHello == null || serverKeyExchange != null
259adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || isResuming) {
260adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
261adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
262adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
263adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverKeyExchange = new ServerKeyExchange(io_stream,
264adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            length, session.cipherSuite.keyExchange);
265adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
266adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 13: // CERTIFICATE_REQUEST
267adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (serverCert == null || certificateRequest != null
268adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            || session.cipherSuite.isAnonymous() || isResuming) {
269adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
270adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
2724ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    certificateRequest = new CertificateRequest(io_stream, length);
273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 14: // SERVER_HELLO_DONE
2754ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                    if (serverHello == null || serverHelloDone != null || isResuming) {
276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverHelloDone = new ServerHelloDone(io_stream, length);
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (this.nonBlocking) {
28190b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                        delegatedTasks.add(new DelegatedTask(new Runnable() {
28290b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                            public void run() {
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                processServerHelloDone();
284f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson                            }
28590b140190f219fd63ede200a63da40bf9e6ca98dElliott Hughes                        }, this));
286adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    processServerHelloDone();
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                case 20: // FINISHED
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (!changeCipherSpecReceived) {
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        unexpectedMessage();
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        return;
294adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverFinished = new Finished(io_stream, length);
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    verifyFinished(serverFinished.getData());
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.lastAccessedTime = System.currentTimeMillis();
298adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    session.context = parameters.getClientSessionContext();
299adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    parameters.getClientSessionContext().putSession(session);
300adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (isResuming) {
301adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        sendChangeCipherSpec();
302adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
303adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        session.lastAccessedTime = System.currentTimeMillis();
304adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        status = FINISHED;
305adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
306adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // XXX there is no cleanup work
307adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    break;
308adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                default:
309adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    unexpectedMessage();
310adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    return;
311adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
312adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (IOException e) {
313adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                // io stream dosn't contain complete handshake message
314adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                io_stream.reset();
315adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
316adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
317adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
318adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
319adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
320adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
322f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * Processes SSLv2 Hello message.
323f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes     * SSLv2 client hello message message is an unexpected message
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for client side of handshake protocol.
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @ see TLS 1.0 spec., E.1. Version 2 client hello
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param bytes
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
328f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
329adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void unwrapSSLv2(byte[] bytes) {
330adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        unexpectedMessage();
331adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
332adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
333adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
334adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Creates and sends Finished message
335adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
336f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
337adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void makeFinished() {
338adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        byte[] verify_data;
339adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serverHello.server_version[1] == 1) {
340adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verify_data = new byte[12];
341adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computerVerifyDataTLS("client finished", verify_data);
342adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
343adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verify_data = new byte[36];
344adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            computerVerifyDataSSLv3(SSLv3Constants.client, verify_data);
345adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
346adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        clientFinished = new Finished(verify_data);
347adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        send(clientFinished);
348adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
349adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session.lastAccessedTime = System.currentTimeMillis();
350adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = FINISHED;
351adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
352adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (serverHello.server_version[1] == 1) {
353adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                computerReferenceVerifyDataTLS("server finished");
354adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
355adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                computerReferenceVerifyDataSSLv3(SSLv3Constants.server);
356adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
357adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            status = NEED_UNWRAP;
358adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
359adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
360adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
361adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
362adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Processes ServerHelloDone: makes verification of the server messages; sends
363adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * client messages, computers masterSecret, sends ChangeCipherSpec
364adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
365adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    void processServerHelloDone() {
366adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        PrivateKey clientKey = null;
367adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
368adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (serverCert != null) {
369b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            if (session.cipherSuite.isAnonymous()) {
370adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unexpectedMessage();
371adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
372adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
373adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            verifyServerCert();
374adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
375b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            if (!session.cipherSuite.isAnonymous()) {
376adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unexpectedMessage();
377adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
378adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
379adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
380adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
381adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Client certificate
382adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (certificateRequest != null) {
383adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            X509Certificate[] certs = null;
384b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            // obtain certificates from key manager
385b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            String alias = null;
386b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            String[] certTypes = certificateRequest.getTypesAsString();
387b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            X500Principal[] issuers = certificateRequest.certificate_authorities;
388b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            X509KeyManager km = parameters.getKeyManager();
389b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            if (km instanceof X509ExtendedKeyManager) {
390b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                X509ExtendedKeyManager ekm = (X509ExtendedKeyManager)km;
391b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                if (this.socketOwner != null) {
392b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    alias = ekm.chooseClientAlias(certTypes, issuers, this.socketOwner);
393b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                } else {
394b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    alias = ekm.chooseEngineClientAlias(certTypes, issuers, this.engineOwner);
395b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                }
396b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                if (alias != null) {
397b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    certs = ekm.getCertificateChain(alias);
398b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                }
399b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            } else {
400b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                alias = km.chooseClientAlias(certTypes, issuers, this.socketOwner);
401b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                if (alias != null) {
402b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                    certs = km.getCertificateChain(alias);
403b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom                }
404adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
405b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom
406adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session.localCertificates = certs;
407adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            clientCert = new CertificateMessage(certs);
408b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            clientKey = km.getPrivateKey(alias);
409adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(clientCert);
410adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
411adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // Client key exchange
412aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom        if (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA
413aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_RSA_EXPORT) {
414adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // RSA encrypted premaster secret message
415adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            Cipher c;
416adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
417adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
418adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (serverKeyExchange != null) {
419b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                    c.init(Cipher.WRAP_MODE, serverKeyExchange
420adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            .getRSAPublicKey());
421adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
422b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                    c.init(Cipher.WRAP_MODE, serverCert.certs[0]);
423adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
424adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (Exception e) {
425adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.INTERNAL_ERROR,
426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        "Unexpected exception", e);
427adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
429adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            preMasterSecret = new byte[48];
430adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            parameters.getSecureRandom().nextBytes(preMasterSecret);
4316882e31b7ce2d04ebbc91c7a55d7840e8fdce8a5Brian Carlstrom            System.arraycopy(clientHello.client_version, 0, preMasterSecret, 0, 2);
432adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
433adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                clientKeyExchange = new ClientKeyExchange(c
434b9f9831a0800adbb6b67ab5bdc62292aa034992bBrian Carlstrom                        .wrap(new SecretKeySpec(preMasterSecret, "preMasterSecret")),
435adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        serverHello.server_version[1] == 1);
436adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (Exception e) {
437adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.INTERNAL_ERROR,
438adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        "Unexpected exception", e);
439adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
441adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            try {
4434ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                KeyFactory kf = KeyFactory.getInstance("DH");
4444ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                KeyAgreement agreement = KeyAgreement.getInstance("DH");
4454ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
4464ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                PublicKey serverPublic;
4474ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom                DHParameterSpec spec;
448adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (serverKeyExchange != null) {
449adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverPublic = kf.generatePublic(new DHPublicKeySpec(
450adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            serverKeyExchange.par3, serverKeyExchange.par1,
451adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            serverKeyExchange.par2));
452adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    spec = new DHParameterSpec(serverKeyExchange.par1,
453adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            serverKeyExchange.par2);
454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
455adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    serverPublic = serverCert.certs[0].getPublicKey();
456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    spec = ((DHPublicKey) serverPublic).getParams();
457adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                kpg.initialize(spec);
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
460adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                KeyPair kp = kpg.generateKeyPair();
461adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                Key key = kp.getPublic();
462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                if (clientCert != null
463adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        && serverCert != null
464aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                        && (session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_RSA
465aacf6f9741dea0f12fbff5e7696e53f251177280Brian Carlstrom                                || session.cipherSuite.keyExchange == CipherSuite.KEY_EXCHANGE_DHE_DSS)) {
466adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    PublicKey client_pk = clientCert.certs[0].getPublicKey();
467adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    PublicKey server_pk = serverCert.certs[0].getPublicKey();
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (client_pk instanceof DHKey
469adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            && server_pk instanceof DHKey) {
470adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (((DHKey) client_pk).getParams().getG().equals(
471adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                ((DHKey) server_pk).getParams().getG())
472adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                && ((DHKey) client_pk).getParams().getP()
473adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                                    .equals(((DHKey) server_pk).getParams().getG())) {
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // client cert message DH public key parameters
475adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            // matched those specified by the
476adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            //   server in its certificate,
477adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            clientKeyExchange = new ClientKeyExchange(); // empty
478adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
479adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
480adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                } else {
481adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    clientKeyExchange = new ClientKeyExchange(
482adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            ((DHPublicKey) key).getY());
483adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
484adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                key = kp.getPrivate();
485adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                agreement.init(key);
486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                agreement.doPhase(serverPublic, true);
487adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                preMasterSecret = agreement.generateSecret();
488adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } catch (Exception e) {
489adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                fatalAlert(AlertProtocol.INTERNAL_ERROR,
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        "Unexpected exception", e);
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
493adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
494adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (clientKeyExchange != null) {
495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(clientKeyExchange);
496adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
497adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
498adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        computerMasterSecret();
499adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
500adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // send certificate verify for all certificates except those containing
501adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // fixed DH parameters
5027c935d4e4ca990334200cf5eb4fbcfac718c6b45gcollins        if (clientCert != null && clientCert.certs.length > 0 && !clientKeyExchange.isEmpty()) {
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // Certificate verify
504b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            String authType = clientKey.getAlgorithm();
505b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            DigitalSignature ds = new DigitalSignature(authType);
506adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            ds.init(clientKey);
507adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
508b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            if ("RSA".equals(authType)) {
509adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ds.setMD5(io_stream.getDigestMD5());
510adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ds.setSHA(io_stream.getDigestSHA());
511b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            } else if ("DSA".equals(authType)) {
512adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                ds.setSHA(io_stream.getDigestSHA());
513b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            // The Signature should be empty in case of anonymous signature algorithm:
514b7eec62f6db198a76b67d7915b03e59189c6df4fBrian Carlstrom            // } else if ("DH".equals(authType)) {
515adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
516adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            certificateVerify = new CertificateVerify(ds.sign());
517adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            send(certificateVerify);
518adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
519adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
520adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sendChangeCipherSpec();
521adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
522f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /*
524adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Verifies certificate path
525adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
526adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private void verifyServerCert() {
5274ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom        String authType = session.cipherSuite.getAuthType(serverKeyExchange != null);
5284ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom        if (authType == null) {
529adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
530adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
5316d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        String hostname = null;
5326d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        if (engineOwner != null) {
5336d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            hostname = engineOwner.getPeerHost();
5346d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        } else {
5356d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            // we don't want to do an inet address lookup here in case we're talking to a proxy
5366d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            hostname = socketOwner.getWrappedHostName();
5376d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra        }
538adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
5396d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            X509TrustManager x509tm = parameters.getTrustManager();
5406d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            if (x509tm instanceof TrustManagerImpl) {
5416d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra                TrustManagerImpl tm = (TrustManagerImpl) x509tm;
5426d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra                tm.checkServerTrusted(serverCert.certs, authType, hostname);
5436d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            } else {
5446d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra                x509tm.checkServerTrusted(serverCert.certs, authType);
5456d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            }
546adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (CertificateException e) {
547adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            fatalAlert(AlertProtocol.BAD_CERTIFICATE, "Not trusted server certificate", e);
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return;
549adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        session.peerCertificates = serverCert.certs;
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
553adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
554f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson     * Processes ChangeCipherSpec message
555adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
556f921579f87fa63204b4a4bef39ed27e7835aec45Jesse Wilson    @Override
557adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void receiveChangeCipherSpec() {
558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (isResuming) {
559adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (serverHello == null) {
560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                unexpectedMessage();
561adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
562adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else if (clientFinished == null) {
563adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            unexpectedMessage();
564f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes        }
565adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        changeCipherSpecReceived = true;
566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    // Find session to resume in client session context
569adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLSessionImpl findSessionToResume() {
570adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        String host = null;
571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        int port = -1;
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (engineOwner != null) {
573adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            host = engineOwner.getPeerHost();
574adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            port = engineOwner.getPeerPort();
5757329fa972d9c20777444e5e1b13169d700de6567Brian Carlstrom        } else {
5766d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            host = socketOwner.getPeerHostName();
5776d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra            port = socketOwner.getPeerPort();
578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
579adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (host == null || port == -1) {
580adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null; // starts new session
581adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
582f33eae7e84eb6d3b0f4e86b59605bb3de73009f3Elliott Hughes
583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        ClientSessionContext context = parameters.getClientSessionContext();
584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLSessionImpl session
585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                = (SSLSessionImpl) context.getSession(host, port);
586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (session != null) {
587adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            session = (SSLSessionImpl) session.clone();
588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
589adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return session;
590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
591adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
593