OpenSSLSocketImpl.java revision 5f2e6872311240319509aed64d9f58cd5b64719b
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License.
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException;
20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream;
21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream;
22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress;
23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket;
24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException;
256df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey;
266df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom;
2712cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException;
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.ArrayList;
3130da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybobimport java.util.concurrent.atomic.AtomicInteger;
32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.logging.Logger;
33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException;
36bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException;
37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession;
38059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal;
39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl;
40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/**
424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p>
44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere
45ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document.
464559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p>
474559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include:
484559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul>
494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout
504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>compression methods
514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets
524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication
534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul>
54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
55ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl
56ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        extends javax.net.ssl.SSLSocket
576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        implements NativeCrypto.SSLHandshakeCallbacks {
58ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private int sslNativePointer;
59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private InputStream is;
60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OutputStream os;
61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private final Object handshakeLock = new Object();
62ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object readLock = new Object();
63ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private final Object writeLock = new Object();
64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private SSLParameters sslParameters;
65bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private String[] enabledProtocols;
66bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private String[] enabledCipherSuites;
674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private String[] enabledCompressionMethods;
684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private boolean useSessionTickets;
694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    private String hostname;
70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private OpenSSLSessionImpl sslSession;
71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private Socket socket;
72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean autoClose;
73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private boolean handshakeStarted = false;
74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
75bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
76bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Not set to true until the update from native that tells us the
77bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * full handshake is complete, since SSL_do_handshake can return
78bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * before the handshake is completely done due to
79bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * handshake_cutthrough support.
80bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
81bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private boolean handshakeCompleted = false;
82bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private ArrayList<HandshakeCompletedListener> listeners;
84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private int timeout = 0;
859d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
869d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    private int handshakeTimeout = -1;  // -1 = same as timeout; 0 = infinite
879d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
88a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom    private String wrappedHost;
89a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom    private int wrappedPort;
90adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
9130da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob    private static final AtomicInteger instanceCount = new AtomicInteger(0);
92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public static int getInstanceCount() {
9430da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        return instanceCount.get();
95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private static void updateInstanceCount(int amount) {
9830da60bf992bd5f2ef15ffcd8a3ebb17937d23d0crazybob        instanceCount.addAndGet(amount);
99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 1 parameter
103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param sslParameters Parameters for the SSL
105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            context
106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(SSLParameters sslParameters) throws IOException {
109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
110ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
114bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl
115bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     *
116bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param sslParameters Parameters for the SSL
117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     *            context
118bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @throws IOException if network fails
119bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
120bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    protected OpenSSLSocketImpl(SSLParameters sslParameters,
121bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                String[] enabledProtocols,
1224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                                String[] enabledCipherSuites,
1234559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                                String[] enabledCompressionMethods) throws IOException {
124bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        super();
1254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods);
126bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
127bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
128bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters
130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1340c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    protected OpenSSLSocketImpl(String host, int port, SSLParameters sslParameters)
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port);
137ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 3 parameters: 1st is InetAddress
142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1460c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParameters sslParameters)
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port);
149ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is host
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1590c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom    protected OpenSSLSocketImpl(String host, int port,
1600c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                InetAddress clientAddress, int clientPort,
1610c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                SSLParameters sslParameters)
162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(host, port, clientAddress, clientPort);
164ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Class constructor with 5 parameters: 1st is InetAddress
169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws java.net.UnknownHostException host not defined
172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
1740c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                InetAddress clientAddress, int clientPort,
1750c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom                                SSLParameters sslParameters)
176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throws IOException {
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super(address, port, clientAddress, clientPort);
178ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Constructor with 5 parameters: 1st is socket. Enhances an existing socket
183a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom     * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor.
184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IOException if network fails
186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected OpenSSLSocketImpl(Socket socket, String host, int port,
188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            boolean autoClose, SSLParameters sslParameters) throws IOException {
189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super();
190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.socket = socket;
191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.timeout = socket.getSoTimeout();
192a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom        this.wrappedHost = host;
193a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom        this.wrappedPort = port;
194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.autoClose = autoClose;
195ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        init(sslParameters);
196ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
197ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
198ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
199ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * Initialize the SSL socket and set the certificates for the
200ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * future handshaking.
201ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
202ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private void init(SSLParameters sslParameters) throws IOException {
203bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        init(sslParameters,
204bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom             NativeCrypto.getSupportedProtocols(),
2054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom             NativeCrypto.getDefaultCipherSuites(),
2064559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom             NativeCrypto.getDefaultCompressionMethods());
207ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
208ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
209ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    /**
210bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Initialize the SSL socket and set the certificates for the
211bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * future handshaking.
212ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     */
213bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private void init(SSLParameters sslParameters,
214bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                      String[] enabledProtocols,
2154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                      String[] enabledCipherSuites,
2164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                      String[] enabledCompressionMethods) throws IOException {
217bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.sslParameters = sslParameters;
218bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.enabledProtocols = enabledProtocols;
219bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        this.enabledCipherSuites = enabledCipherSuites;
2204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.enabledCompressionMethods = enabledCompressionMethods;
221adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        updateInstanceCount(1);
222adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
223adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
224adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
225adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Gets the suitable session reference from the session cache container.
226adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
227adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return OpenSSLSessionImpl
228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
229bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) {
230adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (super.getInetAddress() == null ||
231adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostAddress() == null ||
232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName() == null) {
233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return null;
234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
2359acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(
236adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getInetAddress().getHostName(),
237adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                super.getPort());
2389acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (session == null) {
2399acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2409acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2419acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom
2429acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        String protocol = session.getProtocol();
2439acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        boolean protocolFound = false;
2449acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        for (String enabledProtocol : enabledProtocols) {
2459acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            if (protocol.equals(enabledProtocol)) {
2469acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                protocolFound = true;
2479acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                break;
2489acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            }
2499acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2509acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (!protocolFound) {
2519acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2529acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2539acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom
2549acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        String cipherSuite = session.getCipherSuite();
2559acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        boolean cipherSuiteFound = false;
2569acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        for (String enabledCipherSuite : enabledCipherSuites) {
2579acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            if (cipherSuite.equals(enabledCipherSuite)) {
2589acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                cipherSuiteFound = true;
2599acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom                break;
2609acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            }
2619acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2629acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        if (!cipherSuiteFound) {
2639acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            return null;
2649acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        }
2656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
2664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        String compressionMethod = session.getCompressionMethod();
2674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        boolean compressionMethodFound = false;
2684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        for (String enabledCompressionMethod : enabledCompressionMethods) {
2694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            if (compressionMethod.equals(enabledCompressionMethod)) {
2704559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                compressionMethodFound = true;
2714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom                break;
2724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            }
2734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
2744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        if (!compressionMethodFound) {
2754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            return null;
2764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
2774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
2789acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom        return session;
279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
280adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
281adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
282adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Ensures that logger is lazily loaded. The outer class seems to load
283adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * before logging is ready.
284adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
285adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    static class LoggerHolder {
286ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName());
287adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
288adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
289adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
290adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Starts a TLS/SSL handshake on this connection using some native methods
291adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * from the OpenSSL library. It can negotiate new encryption keys, change
292adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * cipher suites, or initiate a new session. The certificate chain is
293adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * verified if the correspondent property in java.Security is set. All
294ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     * listeners are notified at the end of the TLS/SSL handshake.
295adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
296adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if network fails
297adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
2984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
299bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public void startHandshake() throws IOException {
300bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        startHandshake(true);
301bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
302bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
303bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
3045f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     * Checks whether the socket is closed, and throws an exception.
3055f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     *
3065f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     * @throws SocketException
3075f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     *             if the socket is closed.
3085f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom     */
3095f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    private void checkOpen() throws SocketException {
3105f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        if (isClosed()) {
3115f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            throw new SocketException("Socket is closed");
3125f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        }
3135f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    }
3145f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom
3155f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom    /**
316bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * Perform the handshake
317bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param full If true, disable handshake cutthrough for a fully synchronous handshake
318bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
319bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public synchronized void startHandshake(boolean full) throws IOException {
3205f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
321adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
322adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
323adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
324adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
325adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
326adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
327adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
328adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
3296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // note that this modifies the global seed, not something specific to the connection
3306df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
3316df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
3326df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        if (secureRandom == null) {
3336df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
3346df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        } else {
3356df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
3366df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        }
3376df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3386df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final boolean client = sslParameters.getUseClientMode();
3396df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3406df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        final int sslCtxNativePointer = (client) ?
3416df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            sslParameters.getClientSessionContext().sslCtxNativePointer :
3426df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            sslParameters.getServerSessionContext().sslCtxNativePointer;
3436df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3446df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        this.sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
3456df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
3466df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // setup server certificates and private keys.
3476df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // clients will receive a call back to request certificates.
3486df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        if (!client) {
3496df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            for (String keyType : NativeCrypto.KEY_TYPES) {
350ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                try {
351ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType,
352ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                                                                                   null,
353ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                                                                                   this));
354ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                } catch (CertificateEncodingException e) {
355ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    throw new IOException(e);
356ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                }
3576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            }
3586df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        }
3596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
360bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols);
361bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites);
3624559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        if (enabledCompressionMethods.length != 0) {
3634559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            NativeCrypto.setEnabledCompressionMethods(sslNativePointer, enabledCompressionMethods);
3644559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
3654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        if (useSessionTickets) {
3664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET);
3674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
3684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        if (hostname != null) {
3694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom            NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname);
3704559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        }
371bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
372bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        boolean enableSessionCreation = sslParameters.getEnableSessionCreation();
373bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (!enableSessionCreation) {
374bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer,
375bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                                          enableSessionCreation);
376bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
377bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
378bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        AbstractSessionContext sessionContext;
379bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        OpenSSLSessionImpl session;
380bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (client) {
381bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // look for client session to reuse
382bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext();
383bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            sessionContext = clientSessionContext;
384bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            session = getCachedClientSession(clientSessionContext);
385bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (session != null) {
386bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                NativeCrypto.SSL_set_session(sslNativePointer,  session.sslSessionNativePointer);
387bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
388bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } else {
389bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            sessionContext = sslParameters.getServerSessionContext();
390bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            session = null;
391bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
392bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
393bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // setup peer certificate verification
394bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (client) {
3956df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            // TODO support for anonymous cipher would require us to
3966df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            // conditionally use SSL_VERIFY_NONE
397bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } else {
398bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // needing client auth takes priority...
399ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            boolean certRequested = false;
400bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (sslParameters.getNeedClientAuth()) {
401bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                NativeCrypto.SSL_set_verify(sslNativePointer,
402ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                                            NativeCrypto.SSL_VERIFY_PEER
403ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                                            | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
404ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                certRequested = true;
405bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // ... over just wanting it...
406bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            } else if (sslParameters.getWantClientAuth()) {
407bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                NativeCrypto.SSL_set_verify(sslNativePointer,
408e3a187163504f00c98bd75cbd8bcbdde123ae2cdBrian Carlstrom                                            NativeCrypto.SSL_VERIFY_PEER);
409ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                certRequested = true;
410bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // ... and it defaults properly so we don't need call SSL_set_verify in the common case.
411ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            } else {
412ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                certRequested = false;
413ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
414059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
415ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (certRequested) {
416ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                X509Certificate[] issuers = sslParameters.getTrustManager().getAcceptedIssuers();
417ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                if (issuers != null) {
418ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    byte[][] issuersBytes;
419ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    try {
420ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                        issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers);
421ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    } catch (CertificateEncodingException e) {
422ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                        throw new IOException("Problem encoding principals", e);
423ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    }
424ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                    NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes);
425ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                }
426ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
427bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
428bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
429bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (client && full) {
430bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // we want to do a full synchronous handshake, so turn off cutthrough
4316df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            NativeCrypto.SSL_clear_mode(sslNativePointer,
4326df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                                        NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH);
433ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
434ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
435ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // BEGIN android-added
436ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // Temporarily use a different timeout for the handshake process
437ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        int savedTimeout = timeout;
438ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (handshakeTimeout >= 0) {
439ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            setSoTimeout(handshakeTimeout);
440ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
441ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // END android-added
442ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
443bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
444ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        Socket socket = this.socket != null ? this.socket : this;
445bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        int sslSessionNativePointer;
446bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        try {
4476df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            sslSessionNativePointer
4486df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                = NativeCrypto.SSL_do_handshake(sslNativePointer, socket, this, timeout, client);
449bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } catch (CertificateException e) {
450bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            throw new SSLPeerUnverifiedException(e.getMessage());
451bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
452f002bdddce924e2145a4a2b60592b7a40f4112f6Brian Carlstrom        byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer);
453bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId);
454bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (sslSession != null) {
4559acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom            sslSession.lastAccessedTime = System.currentTimeMillis();
456ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            LoggerHolder.logger.fine("Reused cached session for "
457bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                     + getInetAddress() + ".");
458f002bdddce924e2145a4a2b60592b7a40f4112f6Brian Carlstrom            NativeCrypto.SSL_SESSION_free(sslSessionNativePointer);
459adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } else {
460bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (!enableSessionCreation) {
461bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled
462bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                throw new IllegalStateException("SSL Session may not be created");
463bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
464bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            byte[][] localCertificatesBytes = NativeCrypto.SSL_get_certificate(sslNativePointer);
465bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            X509Certificate[] localCertificates;
466bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (localCertificatesBytes == null) {
467bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                localCertificates = null;
468adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            } else {
469bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                localCertificates = new X509Certificate[localCertificatesBytes.length];
470bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                for (int i = 0; i < localCertificatesBytes.length; i++) {
471059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                    localCertificates[i] = new X509CertImpl(localCertificatesBytes[i]);
472bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                }
473ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            }
474adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
475a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom            if (wrappedHost == null) {
476bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates,
477ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    super.getInetAddress().getHostName(),
478ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    super.getPort(), sessionContext);
479ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            } else  {
480bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates,
481a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom                                                    wrappedHost, wrappedPort,
482ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                                                    sessionContext);
483ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            }
4840c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom            // if not, putSession later in handshakeCompleted() callback
485bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (handshakeCompleted) {
486ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                sessionContext.putSession(sslSession);
4879d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor            }
488bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            LoggerHolder.logger.fine("Created new session for "
489bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                                     + getInetAddress().getHostName() + ".");
490adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
491adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
492ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // BEGIN android-added
493ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // Restore the original timeout now that the handshake is complete
494ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (handshakeTimeout >= 0) {
495ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            setSoTimeout(savedTimeout);
496ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
497ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        // END android-added
498ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
4990c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom        // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
500bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (handshakeCompleted) {
501bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            notifyHandshakeCompletedListeners();
502adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
503adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
504bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
505adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
506ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom    private void setCertificate(String alias) throws CertificateEncodingException, SSLException {
5076df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        if (alias == null) {
5086df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            return;
5096df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        }
5106df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5116df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias);
51212cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstrom        byte[] privateKeyBytes = privateKey.getEncoded();
5136df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes);
5146df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5156df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias);
516ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates);
5176df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes);
5186df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5196df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // checks the last installed private key and certificate,
5206df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        // so need to do this once per loop iteration
5216df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom        NativeCrypto.SSL_check_private_key(sslNativePointer);
5226df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    }
5236df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
5246df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    /**
5256df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
5266df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * invoked via JNI from client_cert_cb
5276df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     */
528059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
529ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            throws CertificateEncodingException, SSLException {
530059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
531059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        String[] keyTypes = new String[keyTypeBytes.length];
532059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        for (int i = 0; i < keyTypeBytes.length; i++) {
533059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            keyTypes[i] = NativeCrypto.keyType(keyTypeBytes[i]);
534059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        }
535059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom
536059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        X500Principal[] issuers;
537059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        if (asn1DerEncodedPrincipals == null) {
538059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            issuers = null;
539059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        } else {
540059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            issuers = new X500Principal[asn1DerEncodedPrincipals.length];
541059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) {
542059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom                issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]);
543059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom            }
544059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        }
545059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom        setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this));
5466df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    }
5476df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom
548adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
5496df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
550bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * invoked via JNI from info_callback
551adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
552bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    public void handshakeCompleted() {
553bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        handshakeCompleted = true;
554adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
555bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // If sslSession is null, the handshake was completed during
556bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // the call to NativeCrypto.SSL_do_handshake and not during a
557bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // later read operation. That means we do not need to fixup
558bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // the SSLSession and session cache or notify
559bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // HandshakeCompletedListeners, it will be done in
560bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // startHandshake.
561bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (sslSession == null) {
562bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            return;
563bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
564adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // reset session id from the native pointer and update the
566bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // appropriate cache.
567bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        sslSession.resetId();
568bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        AbstractSessionContext sessionContext =
569bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            (sslParameters.getUseClientMode())
570bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            ? sslParameters.getClientSessionContext()
571bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                : sslParameters.getServerSessionContext();
572adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sessionContext.putSession(sslSession);
573bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
574bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        // let listeners know we are finally done
575bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        notifyHandshakeCompletedListeners();
576bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    }
577bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
578bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
579bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
580bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            // notify the listeners
581bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            HandshakeCompletedEvent event =
582bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
583bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
584bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                try {
585bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                    listener.handshakeCompleted(event);
586bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                } catch (RuntimeException e) {
587e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // The RI runs the handlers in a separate thread,
588e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // which we do not. But we try to preserve their
589e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // behavior of logging a problem and not killing
590e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // the handshaking thread just because a listener
591e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    // has a problem.
592e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    Thread thread = Thread.currentThread();
593e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
594bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                }
595bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            }
596bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        }
597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
6006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom     * Implementation of NativeCrypto.SSLHandshakeCallbacks
601ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
602059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom     * @param bytes An array of ASN.1 DER encoded certficates
603bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @param authMethod auth algorithm name
604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
605bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * @throws CertificateException if the certificate is untrusted
606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @SuppressWarnings("unused")
6086df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom    public void verifyCertificateChain(byte[][] bytes, String authMethod)
6096df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom            throws CertificateException {
610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
611e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            if (bytes == null || bytes.length == 0) {
612e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom                throw new SSLException("Peer sent no certificate");
613e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom            }
614bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length];
615bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            for (int i = 0; i < bytes.length; i++) {
616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                peerCertificateChain[i] =
6176df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                    new X509CertImpl(
6186df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                        javax.security.cert.X509Certificate.getInstance(bytes[i]).getEncoded());
619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
620bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
621bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            if (client) {
6226df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain,
6236df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                                                                   authMethod);
624bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            } else {
6256df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain,
6266df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom                                                                   authMethod);
627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
628bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom
629bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } catch (CertificateException e) {
630bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            throw e;
631bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        } catch (Exception e) {
632bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            throw new RuntimeException(e);
633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an input stream for this SSL socket using native calls to the
638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return: an input stream for reading bytes from this socket.
641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws: <code>IOException</code> if an I/O error occurs when creating
642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          the input stream, the socket is closed, the socket is not
643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *          connected, or the socket input has been shutdown.
644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
6454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public InputStream getInputStream() throws IOException {
6475f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
648ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        synchronized (this) {
649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (is == null) {
650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                is = new SSLInputStream();
651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return is;
654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns an output stream for this SSL socket using native calls to the
659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * OpenSSL library.
660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an output stream for writing bytes to this socket.
662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error occurs when creating
663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             the output stream, or no connection to the socket exists.
664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
6654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public OutputStream getOutputStream() throws IOException {
6675f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom        checkOpen();
668ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom        synchronized (this) {
669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (os == null) {
670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                os = new SSLOutputStream();
671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return os;
674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
677bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
678bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * This method is not supported for this SSLSocket implementation
679bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * because reading from an SSLSocket may involve writing to the
680bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * network.
681bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
6824559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownInput() throws IOException {
684bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        throw new UnsupportedOperationException();
685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
687bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom    /**
688bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * This method is not supported for this SSLSocket implementation
689bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * because writing to an SSLSocket may involve reading from the
690bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     * network.
691bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom     */
6924559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void shutdownOutput() throws IOException {
694bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        throw new UnsupportedOperationException();
695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides input data stream functionality
699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * read data received via SSL protocol.
701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLInputStream extends InputStream {
703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLInputStream() throws IOException {
704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             * SSLInputStream object will be created.
707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
708bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * this operation can block until the data will be
714adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * available.
715adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @return read value.
716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @throws <code>IOException</code>
717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read() throws IOException {
7205f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
721ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (readLock) {
7223e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom                return NativeCrypto.SSL_read_byte(sslNativePointer, timeout);
723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public int read(byte[] b, int off, int len) throws IOException {
7325f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
733ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (b == null) {
734ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new NullPointerException("b == null");
735ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
736ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if ((len | off) < 0 || len > b.length - off) {
737ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new IndexOutOfBoundsException();
738ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
739ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (0 == len) {
740ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                return 0;
741ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
742ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (readLock) {
7433e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom                return NativeCrypto.SSL_read(sslNativePointer, b, off, len, timeout);
744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This inner class provides output data stream functionality
750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * for the OpenSSL native implementation. It is used to
751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * write data according to the encryption parameters given in SSL context.
752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    private class SSLOutputStream extends OutputStream {
754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        SSLOutputStream() throws IOException {
755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /**
756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            /* Note: When startHandshake() throws an exception, no
757ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom             * SSLOutputStream object will be created.
758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project             */
759bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            OpenSSLSocketImpl.this.startHandshake(false);
760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(int)
765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(int b) throws IOException {
7685f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
769ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (writeLock) {
7703e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom                NativeCrypto.SSL_write_byte(sslNativePointer, b);
771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /**
775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * Method acts as described in spec for superclass.
776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
7784559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        @Override
779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        public void write(byte[] b, int start, int len) throws IOException {
7805f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom            checkOpen();
781ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (b == null) {
782ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new NullPointerException("b == null");
783ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
784ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if ((len | start) < 0 || len > b.length - start) {
785ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                throw new IndexOutOfBoundsException();
786ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
787ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            if (len == 0) {
788ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom                return;
789ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            }
790ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom            synchronized (writeLock) {
7913e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom                NativeCrypto.SSL_write(sslNativePointer, b, start, len);
792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
793adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
797adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
798adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The SSL session used by this connection is returned. The SSL session
799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * determines which cipher suite should be used by all connections within
800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * that session and which identities have the session's client and server.
801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method starts the SSL handshake.
802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return the SSLSession.
803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if the handshake fails
804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public SSLSession getSession() {
807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        try {
808bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom            startHandshake(true);
809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        } catch (IOException e) {
810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // return an invalid session with
811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
812adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            return SSLSessionImpl.NULL_SESSION;
813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslSession;
815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
816adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Registers a listener to be notified that a SSL handshake
819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * was successfully completed on this connection.
820adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IllegalArgumentException</code> if listener is null.
821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void addHandshakeCompletedListener(
824adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
828adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
829adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            listeners = new ArrayList();
830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        listeners.add(listener);
832adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
833adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The method removes a registered listener.
836adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if listener is null or not registered
837adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
839adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void removeHandshakeCompletedListener(
840adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            HandshakeCompletedListener listener) {
841adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listener == null) {
842adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
843adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (listeners == null) {
845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
847adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (!listeners.remove(listener)) {
849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
850adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    "Provided listener is not registered");
851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
855adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if new SSL sessions may be established by this socket.
856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the session may be created; false if a session already
858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *         exists and must be resumed.
859adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getEnableSessionCreation() {
862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getEnableSessionCreation();
863adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set a flag for the socket to inhibit or to allow the creation of a new
867adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * SSL sessions. If the flag is set to false, and there are no actual
868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * sessions to resume, then there will be no successful handshaking.
869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param flag true if session may be created; false
871adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            if a session already exists and must be resumed.
872adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnableSessionCreation(boolean flag) {
875adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
879adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites which could be used by the SSL connection
880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * are returned.
881adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8834559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedCipherSuites() {
885ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the cipher suites that are in use in the actual the SSL
890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection are returned.
891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of cipher suite names
893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
8944559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledCipherSuites() {
896bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        return enabledCipherSuites.clone();
897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the cipher suites listed by
901adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedCipherSuites().
902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param suites names of all the cipher suites to
904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            put on use
905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the
906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             ciphers in array suites are not supported, or when the array
907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             is null.
908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setEnabledCipherSuites(String[] suites) {
911bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites);
912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that may be used on this SSL
916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
9194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getSupportedProtocols() {
921ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * The names of the protocols' versions that are in use on this SSL
926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * connection.
927ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return an array of protocols names
929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
931adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public String[] getEnabledProtocols() {
932bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        return enabledProtocols.clone();
933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method enables the protocols' versions listed by
937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * getSupportedProtocols().
938ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
9394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param protocols The names of all the protocols to allow
940ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom     *
941adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException when one or more of the names in the
942adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             array are not supported, or when the array is null.
943adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
944adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    @Override
9454559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setEnabledProtocols(String[] protocols) {
946bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols);
947adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
9504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * The names of the compression methods that may be used on this SSL
9514559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * connection.
9524559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return an array of compression methods
9534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
9544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String[] getSupportedCompressionMethods() {
9554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return NativeCrypto.getSupportedCompressionMethods();
9564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
9574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
9584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
9594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * The names of the compression methods versions that are in use
9604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * on this SSL connection.
9614559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
9624559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return an array of compression methods
9634559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
9644559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String[] getEnabledCompressionMethods() {
9654559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return enabledCompressionMethods.clone();
9664559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
9674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
9684559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
9694559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables the compression method listed by
9704559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * getSupportedCompressionMethods().
9714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
9724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param methods The names of all the compression methods to allow
9734559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
9744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @throws IllegalArgumentException when one or more of the names in the
9754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *             array are not supported, or when the array is null.
9764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
9774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setEnabledCompressionMethods (String[] methods) {
9784559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods);
9794559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
9804559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
9814559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
9824559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables session ticket support.
9834559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
9844559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param useSessionTickets True to enable session tickets
9854559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
9864559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
9874559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.useSessionTickets = useSessionTickets;
9884559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
9894559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
9904559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
9914559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method gives true back if the SSL socket is set to client mode.
9924559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
9934559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return true if the socket should do the handshaking as client.
9944559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
9954559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public boolean getUseSessionTickets() {
9964559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return useSessionTickets;
9974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
9984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
9994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method enables Server Name Indication
10014559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10024559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
10034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10044559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setHostname(String hostname) {
10054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        this.hostname = hostname;
10064559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10074559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10084559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
10094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * This method returns the current SNI hostname
10104559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     *
10114559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     * @return a host name if SNI is enabled, or null otherwise
10124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom     */
10134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public String getHostname() {
10144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom        return hostname;
10154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    }
10164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom
10174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    /**
1018adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method gives true back if the SSL socket is set to client mode.
1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if the socket should do the handshaking as client.
1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getUseClientMode() {
1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getUseClientMode();
1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1025adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1026adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1027adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method set the actual SSL socket to client mode.
1028adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1029adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param mode true if the socket starts in client
1030adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            mode
1031adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws IllegalArgumentException if mode changes during
1032adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             handshake.
1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
10354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setUseClientMode(boolean mode) {
1036adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        if (handshakeStarted) {
1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            throw new IllegalArgumentException(
1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            "Could not change the mode after the initial handshake has begun.");
1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setUseClientMode(mode);
1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1043adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1044adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket requests client's authentication. Relevant
1045adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
1046adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1047adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
1048adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1050adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getWantClientAuth() {
1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getWantClientAuth();
1052adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1053adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1054adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1055adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Returns true if the SSL socket needs client's authentication. Relevant
1056adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * only for server sockets!
1057adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1058adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @return true if client authentication is desired, false if not.
1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1061adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public boolean getNeedClientAuth() {
1062adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        return sslParameters.getNeedClientAuth();
1063adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1064adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1065adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1066adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
1067adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets!
1068adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1069adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param need true if client authentication is
1070adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
1071adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1073adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setNeedClientAuth(boolean need) {
1074adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setNeedClientAuth(need);
1075adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1076adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1078adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Sets the SSL socket to use client's authentication. Relevant only for
1079adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * server sockets! Notice that in contrast to setNeedClientAuth(..) this
1080adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * method will continue the negotiation if the client decide not to send
1081adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * authentication credentials.
1082adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1083adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param want true if client authentication is
1084adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *            desired, false if not.
1085adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10864559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1087adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setWantClientAuth(boolean want) {
1088adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        sslParameters.setWantClientAuth(want);
1089adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1090adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1091adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1092adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
10944559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1095adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void sendUrgentData(int data) throws IOException {
1096adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
1097adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Method sendUrgentData() is not supported.");
1098adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1099adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * This method is not supported for SSLSocket implementation.
1102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void setOOBInline(boolean on) throws SocketException {
1105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        throw new SocketException(
1106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                "Methods sendUrgentData, setOOBInline are not supported.");
1107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Set the read timeout on this socket. The SO_TIMEOUT option, is specified
1111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * in milliseconds. The read operation will block indefinitely for a zero
1112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * value.
1113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @param timeout the read timeout value
1115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws SocketException if an error occurs setting the option
1116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
11184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setSoTimeout(int timeout) throws SocketException {
1119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        super.setSoTimeout(timeout);
1120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        this.timeout = timeout;
1121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11239d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // BEGIN android-added
11249d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    /**
11259d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
11269d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * milliseconds and will be used only during the handshake process.
11279d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     *
11289d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     * @param timeout the handshake timeout value
11299d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor     */
11304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    public void setHandshakeTimeout(int timeout) throws SocketException {
11319d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor        this.handshakeTimeout = timeout;
11329d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    }
11339d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor    // END android-added
11349d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor
1135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    /**
1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * Closes the SSL socket. Once closed, a socket is not available for further
1137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * use anymore under any circumstance. A new socket must be created.
1138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *
1139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     * @throws <code>IOException</code> if an I/O error happens during the
1140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     *             socket's closure.
1141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project     */
11424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    public void close() throws IOException {
1144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // TODO: Close SSL sockets using a background thread so they close
1145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        // gracefully.
1146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (handshakeLock) {
1148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            if (!handshakeStarted) {
1149bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom                // prevent further attemps to start handshake
1150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                handshakeStarted = true;
1151ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
1152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (this) {
1153ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
1154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (socket != null) {
1156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed()) socket.close();
1157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
1158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed()) super.close();
1159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1161ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom
1162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                return;
1163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
11663e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom        NativeCrypto.SSL_interrupt(sslNativePointer);
1167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        synchronized (this) {
1169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            synchronized (writeLock) {
1170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                synchronized (readLock) {
1171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    IOException pendingException = null;
1173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    // Shut down the SSL connection, per se.
1175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    try {
1176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (handshakeStarted) {
11773e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom                            NativeCrypto.SSL_shutdown(sslNativePointer);
1178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        }
1179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } catch (IOException ex) {
1180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        /*
1181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * Note the exception at this point, but try to continue
1182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         * to clean the rest of this all up before rethrowing.
1183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                         */
1184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        pendingException = ex;
1185adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1186adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    /*
1188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * Even if the above call failed, it is still safe to free
1189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * the native structs, and we need to do so lest we leak
1190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     * memory.
1191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                     */
1192ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom                    free();
1193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (socket != null) {
1195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (autoClose && !socket.isClosed())
1196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            socket.close();
1197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    } else {
1198adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        if (!super.isClosed())
1199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                            super.close();
1200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    if (pendingException != null) {
1203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                        throw pendingException;
1204adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                    }
1205adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project                }
1206adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project            }
1207adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        }
1208adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1209adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1210ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    private void free() {
1211ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        if (sslNativePointer == 0) {
1212ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom            return;
1213ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        }
1214ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1215ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom        sslNativePointer = 0;
1216ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom    }
1217adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
12184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom    @Override
1219adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    protected void finalize() throws IOException {
1220adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project        /*
1221bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * Just worry about our own state. Notably we do not try and
1222bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * close anything. The SocketImpl, either our own
1223bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * PlainSocketImpl, or the Socket we are wrapping, will do
1224bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * that. This might mean we do not properly SSL_shutdown, but
1225bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * if you want to do that, properly close the socket yourself.
1226bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         *
1227bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * The reason why we don't try to SSL_shutdown, is that there
1228bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * can be a race between finalizers where the PlainSocketImpl
1229bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * finalizer runs first and closes the socket. However, in the
1230bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * meanwhile, the underlying file descriptor could be reused
1231bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * for another purpose. If we call SSL_shutdown, the
1232bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * underlying socket BIOs still have the old file descriptor
1233bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * and will write the close notify to some unsuspecting
1234bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom         * reader.
1235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project         */
1236bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        updateInstanceCount(-1);
1237bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom        free();
1238adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
1239adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
1240