108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/*
208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * you may not use this file except in compliance with the License.
608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * You may obtain a copy of the License at
708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project *
1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * See the License for the specific language governing permissions and
1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * limitations under the License.
1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
199b343fce2ab41569e858cc2503bc6d9411af0a3bKenny Rootimport org.conscrypt.util.ArrayUtils;
209f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietarimport org.conscrypt.ct.CTVerifier;
219f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietarimport org.conscrypt.ct.CTVerificationResult;
22ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard;
23fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard;
240648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkeyimport java.io.FileDescriptor;
2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException;
2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream;
2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream;
2808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress;
2999bb3908434214ff7fb41e053158df69ad3bb963Kenny Rootimport java.net.InetSocketAddress;
3008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket;
3199bb3908434214ff7fb41e053158df69ad3bb963Kenny Rootimport java.net.SocketAddress;
3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException;
331ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Rootimport java.security.InvalidKeyException;
3498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey;
3598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom;
361f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException;
3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException;
387dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubinimport java.security.interfaces.ECKey;
397dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubinimport java.security.spec.ECParameterSpec;
4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList;
4101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubinimport javax.crypto.SecretKey;
4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
4308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
4408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException;
45edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException;
4650dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Rootimport javax.net.ssl.SSLParameters;
478765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException;
4808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession;
498d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubinimport javax.net.ssl.X509KeyManager;
50fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager;
5198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal;
528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/**
540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p>
560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include:
570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul>
580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout
590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets
600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication
610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul>
6208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
63f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl
64f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        extends javax.net.ssl.SSLSocket
6501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser,
6601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        SSLParametersImpl.PSKCallbacks {
6790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom
688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final boolean DBG_STATE = false;
698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
7169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     * Protects handshakeStarted and handshakeCompleted.
7269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private final Object stateLock = new Object();
7469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
7569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * The {@link OpenSSLSocketImpl} object is constructed, but {@link #startHandshake()}
778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * has not yet been called.
7869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_NEW = 0;
8069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
8169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has been called at least once.
8369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_HANDSHAKE_STARTED = 1;
8569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
8669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #handshakeCompleted()} has been called, but {@link #startHandshake()} hasn't
888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * returned yet.
8969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_HANDSHAKE_COMPLETED = 2;
918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    /**
938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has completed but {@link #handshakeCompleted()} hasn't
948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake
958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * returns before the handshake is complete. We can now start writing data to the socket.
968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     */
978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 3;
9869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
9969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has completed and {@link #handshakeCompleted()} has been
1018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * called.
10269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_READY = 4;
10469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
10569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #close()} has been called at least once.
10769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_CLOSED = 5;
1098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
1108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private int state = STATE_NEW;
11269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
11369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as 0, set by
1158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * startHandshake, reset to 0 on close.
11669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private long sslNativePointer;
11969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
12069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as null, set by
1228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * getInputStream.
12369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private SSLInputStream is;
1268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
1278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    /**
1288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as null, set by
1298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * getInputStream.
1308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     */
1318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private SSLOutputStream os;
13369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
13469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final Socket socket;
13569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final boolean autoClose;
136cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root
137cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    /**
13899bb3908434214ff7fb41e053158df69ad3bb963Kenny Root     * The peer's DNS hostname if it was supplied during creation. Note that
13999bb3908434214ff7fb41e053158df69ad3bb963Kenny Root     * this may be a raw IP address, so it should be checked before use with
14099bb3908434214ff7fb41e053158df69ad3bb963Kenny Root     * extensions that don't use it like Server Name Indication (SNI).
141cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root     */
142cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    private String peerHostname;
143cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root
144cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    /**
145cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root     * The peer's port if it was supplied during creation. Should only be set if
146cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root     * {@link #peerHostname} is also set.
147cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root     */
148cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    private final int peerPort;
149cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root
15069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final SSLParametersImpl sslParameters;
151126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root
152126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root    /*
153126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root     * A CloseGuard object on Android. On other platforms, this is nothing.
154126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root     */
155126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root    private final Object guard = Platform.closeGuardGet();
15669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
1573c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    private ArrayList<HandshakeCompletedListener> listeners;
1582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
1592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
1603c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root     * Private key for the TLS Channel ID extension. This field is client-side
1613c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root     * only. Set during startHandshake.
1622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
1633c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    OpenSSLKey channelIdPrivateKey;
16469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
16569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /** Set during startHandshake. */
16669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private OpenSSLSessionImpl sslSession;
1672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
168d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    /** Used during handshake callbacks. */
169d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    private OpenSSLSessionImpl handshakeSession;
170d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
17172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    /**
17272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * Local cache of timeout to avoid getsockopt on every read and
17372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * write for non-wrapped sockets. Note that
17472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * OpenSSLSocketImplWrapper overrides setSoTimeout and
17572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * getSoTimeout to delegate to the wrapped socket.
17672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     */
177fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    private int readTimeoutMilliseconds = 0;
178fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    private int writeTimeoutMilliseconds = 0;
17972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
18072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    private int handshakeTimeoutMilliseconds = -1;  // -1 = same as timeout; 0 = infinite
18108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
182cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException {
18390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
184cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = null;
185cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = -1;
18669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
18769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
190076138ff29d805ec5a32d6ad96a18ef08c7f1b11Kenny Root    protected OpenSSLSocketImpl(String hostname, int port, SSLParametersImpl sslParameters)
19190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom            throws IOException {
192076138ff29d805ec5a32d6ad96a18ef08c7f1b11Kenny Root        super(hostname, port);
19390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
194cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = hostname;
195cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = port;
19669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
19769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
19908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
200cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters)
20190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom            throws IOException {
20208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port);
20390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
204cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = null;
205cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = -1;
20669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
20769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
20808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
20908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
21008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
211076138ff29d805ec5a32d6ad96a18ef08c7f1b11Kenny Root    protected OpenSSLSocketImpl(String hostname, int port,
212c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
2135006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson                                SSLParametersImpl sslParameters) throws IOException {
214076138ff29d805ec5a32d6ad96a18ef08c7f1b11Kenny Root        super(hostname, port, clientAddress, clientPort);
21590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
216cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = hostname;
217cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = port;
21869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
21969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
22008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
22108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
22208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
223c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
2245006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson                                SSLParametersImpl sslParameters) throws IOException {
22508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port, clientAddress, clientPort);
22690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
227cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = null;
228cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = -1;
22969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
23069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
23108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
2345006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson     * Create an SSL socket that wraps another socket. Invoked by
2355006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson     * OpenSSLSocketImplWrapper constructor.
23608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
237076138ff29d805ec5a32d6ad96a18ef08c7f1b11Kenny Root    protected OpenSSLSocketImpl(Socket socket, String hostname, int port,
238cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom            boolean autoClose, SSLParametersImpl sslParameters) throws IOException {
23908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.socket = socket;
240cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerHostname = hostname;
241cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        this.peerPort = port;
24208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.autoClose = autoClose;
24369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
24472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
24572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // this.timeout is not set intentionally.
24672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout
24772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // to wrapped socket
248f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
249f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
25099bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    @Override
25199bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    public void connect(SocketAddress endpoint) throws IOException {
25299bb3908434214ff7fb41e053158df69ad3bb963Kenny Root        connect(endpoint, 0);
25399bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    }
25499bb3908434214ff7fb41e053158df69ad3bb963Kenny Root
25599bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    /**
25699bb3908434214ff7fb41e053158df69ad3bb963Kenny Root     * Try to extract the peer's hostname if it's available from the endpoint address.
25799bb3908434214ff7fb41e053158df69ad3bb963Kenny Root     */
25899bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    @Override
25999bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    public void connect(SocketAddress endpoint, int timeout) throws IOException {
26099bb3908434214ff7fb41e053158df69ad3bb963Kenny Root        if (peerHostname == null && endpoint instanceof InetSocketAddress) {
26199bb3908434214ff7fb41e053158df69ad3bb963Kenny Root            peerHostname = Platform.getHostStringFromInetSocketAddress(
26299bb3908434214ff7fb41e053158df69ad3bb963Kenny Root                    (InetSocketAddress) endpoint);
26399bb3908434214ff7fb41e053158df69ad3bb963Kenny Root        }
26499bb3908434214ff7fb41e053158df69ad3bb963Kenny Root
26599bb3908434214ff7fb41e053158df69ad3bb963Kenny Root        super.connect(endpoint, timeout);
26699bb3908434214ff7fb41e053158df69ad3bb963Kenny Root    }
26799bb3908434214ff7fb41e053158df69ad3bb963Kenny Root
268a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    private void checkOpen() throws SocketException {
269a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        if (isClosed()) {
270a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            throw new SocketException("Socket is closed");
271a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        }
272a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    }
273a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom
274a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    /**
275d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * Starts a TLS/SSL handshake on this connection using some native methods
276d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * from the OpenSSL library. It can negotiate new encryption keys, change
277d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * cipher suites, or initiate a new session. The certificate chain is
278d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * verified if the correspondent property in java.Security is set. All
279d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * listeners are notified at the end of the TLS/SSL handshake.
2802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
281f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
282f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void startHandshake() throws IOException {
2838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        checkOpen();
2848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
2858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_NEW) {
2868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                state = STATE_HANDSHAKE_STARTED;
28708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            } else {
2888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We've either started the handshake already or have been closed.
2898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Do nothing in both cases.
29008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
29108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
29208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
29308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
294da4730440c53c99759d89259b320290a6444342fKenny Root        // For BoringSSL, RAND_seed and RAND_load_file are no-ops since the RNG
295da4730440c53c99759d89259b320290a6444342fKenny Root        // reads directly from the random device node.
296da4730440c53c99759d89259b320290a6444342fKenny Root        if (!NativeCrypto.isBoringSSL) {
297da4730440c53c99759d89259b320290a6444342fKenny Root            // note that this modifies the global seed, not something specific
298da4730440c53c99759d89259b320290a6444342fKenny Root            // to the connection
299da4730440c53c99759d89259b320290a6444342fKenny Root            final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
300da4730440c53c99759d89259b320290a6444342fKenny Root            final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
301da4730440c53c99759d89259b320290a6444342fKenny Root            if (secureRandom == null) {
302da4730440c53c99759d89259b320290a6444342fKenny Root                NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
303da4730440c53c99759d89259b320290a6444342fKenny Root            } else {
304da4730440c53c99759d89259b320290a6444342fKenny Root                NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
305da4730440c53c99759d89259b320290a6444342fKenny Root            }
30698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
30798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
30898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final boolean client = sslParameters.getUseClientMode();
30998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
3108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        sslNativePointer = 0;
3118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        boolean releaseResources = true;
312fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom        try {
3133c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final AbstractSessionContext sessionContext = sslParameters.getSessionContext();
3143c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final long sslCtxNativePointer = sessionContext.sslCtxNativePointer;
315fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
316126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root            Platform.closeGuardOpen(guard, "close");
31798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
3183c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            boolean enableSessionCreation = getEnableSessionCreation();
319fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (!enableSessionCreation) {
320fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer,
3213c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                        enableSessionCreation);
3222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
3232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
324ed628f94df430278a203da28055b309346b0bce2Adam Langley            // Allow servers to trigger renegotiation. Some inadvisable server
325ed628f94df430278a203da28055b309346b0bce2Adam Langley            // configurations cause them to attempt to renegotiate during
326ed628f94df430278a203da28055b309346b0bce2Adam Langley            // certain protocols.
327ed628f94df430278a203da28055b309346b0bce2Adam Langley            NativeCrypto.SSL_set_reject_peer_renegotiations(sslNativePointer, false);
328ed628f94df430278a203da28055b309346b0bce2Adam Langley
3299f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar            if (client && sslParameters.isCTVerificationEnabled(getHostname())) {
3309f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                NativeCrypto.SSL_enable_signed_cert_timestamps(sslNativePointer);
3319f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                NativeCrypto.SSL_enable_ocsp_stapling(sslNativePointer);
3329f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar            }
3339f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar
3343c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final OpenSSLSessionImpl sessionToReuse = sslParameters.getSessionToReuse(
335ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root                    sslNativePointer, getHostnameOrIP(), getPort());
33601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this,
33750dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root                    getHostname());
3383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.setCertificateValidation(sslNativePointer);
3393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey);
340f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
341fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // Temporarily use a different timeout for the handshake process
342fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom            int savedReadTimeoutMilliseconds = getSoTimeout();
343fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom            int savedWriteTimeoutMilliseconds = getSoWriteTimeout();
344fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
345fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                setSoTimeout(handshakeTimeoutMilliseconds);
346fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoWriteTimeout(handshakeTimeoutMilliseconds);
347fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
3482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
3498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
3508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_CLOSED) {
3518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    return;
3528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
3548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3557dd8d0b433cf8212538aaaf8726f5222abf035ddMatteo Franchin            long sslSessionNativePointer;
356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            try {
357a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes                sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer,
3583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                        Platform.getFileDescriptor(socket), this, getSoTimeout(), client,
3593c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                        sslParameters.npnProtocols, client ? null : sslParameters.alpnProtocols);
360fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            } catch (CertificateException e) {
361d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage());
362d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                wrapper.initCause(e);
363d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                throw wrapper;
3648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } catch (SSLException e) {
3658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Swallow this exception if it's thrown as the result of an interruption.
3668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                //
3678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake
3688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ
3698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // (or WANT_WRITE). Catching that exception here doesn't seem much worse than
3708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // changing the native code to return a "special" native pointer value when that
3718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // happens.
3728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
3738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
3748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        return;
3758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
3768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3782e1be9d876e8c5554f91afee914641f323eebd4crich cannings                // Write CCS errors to EventLog
3792e1be9d876e8c5554f91afee914641f323eebd4crich cannings                String message = e.getMessage();
3802e1be9d876e8c5554f91afee914641f323eebd4crich cannings                // Must match error string of SSL_R_UNEXPECTED_CCS
3812e1be9d876e8c5554f91afee914641f323eebd4crich cannings                if (message.contains("unexpected CCS")) {
3822e1be9d876e8c5554f91afee914641f323eebd4crich cannings                    String logMessage = String.format("ssl_unexpected_ccs: host=%s",
383ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root                            getHostnameOrIP());
3842e1be9d876e8c5554f91afee914641f323eebd4crich cannings                    Platform.logEvent(logMessage);
3852e1be9d876e8c5554f91afee914641f323eebd4crich cannings                }
3862e1be9d876e8c5554f91afee914641f323eebd4crich cannings
3878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw e;
3882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
3898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            boolean handshakeCompleted = false;
3918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
3928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_HANDSHAKE_COMPLETED) {
3938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    handshakeCompleted = true;
3948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } else if (state == STATE_CLOSED) {
3958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    return;
3968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
3988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3990dd7db8b85dfd8ad5d16d239432b9852450dc78fKenny Root            sslSession = sslParameters.setupSession(sslSessionNativePointer, sslNativePointer,
400ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root                    sessionToReuse, getHostnameOrIP(), getPort(), handshakeCompleted);
401fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom
402fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // Restore the original timeout now that the handshake is complete
403fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
404fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoTimeout(savedReadTimeoutMilliseconds);
405fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoWriteTimeout(savedWriteTimeoutMilliseconds);
406331900211d05cd282141a3a50cb1db626f418b2cDan Egnor            }
40708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
408fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
409fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeCompleted) {
410fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                notifyHandshakeCompletedListeners();
411fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
412f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
4138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
4148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                releaseResources = (state == STATE_CLOSED);
4158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_HANDSHAKE_STARTED) {
4178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_READY_HANDSHAKE_CUT_THROUGH;
4188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } else if (state == STATE_HANDSHAKE_COMPLETED) {
4198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_READY;
4208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
4218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (!releaseResources) {
4238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // Unblock threads that are waiting for our state to transition
4248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH.
4258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.notifyAll();
4268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
4278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
4288765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom        } catch (SSLProtocolException e) {
4293e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed")
4303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                    .initCause(e);
431fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom        } finally {
432aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom            // on exceptional exit, treat the socket as closed
4338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (releaseResources) {
4348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
4358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // Mark the socket as closed since we might have reached this as
4368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // a result on an exception thrown by the handshake process.
4378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    //
4388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // The state will already be set to closed if we reach this as a result of
4398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // an early return or an interruption due to a concurrent call to close().
4408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_CLOSED;
4418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.notifyAll();
4428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
4438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                try {
4458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    shutdownAndFreeSslNative();
4468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } catch (IOException ignored) {
4478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
449fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
45008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
451e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom    }
4523ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root
453cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    /**
45450dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root     * Returns the hostname that was supplied during socket creation. No DNS resolution is
45550dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root     * attempted before returning the hostname.
456cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root     */
4575012f2dc5bf0a28a47cf9b01bd1a63c1ebdc232fKenny Root    public String getHostname() {
45850dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root        return peerHostname;
4593967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson    }
4603967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson
461ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root    /**
462ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root     * For the purposes of an SSLSession, we want a way to represent the supplied hostname
463ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root     * or the IP address in a textual representation. We do not want to perform reverse DNS
464ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root     * lookups on this address.
465ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root     */
466ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root    public String getHostnameOrIP() {
467ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        if (peerHostname != null) {
468ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root            return peerHostname;
469ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        }
470ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root
471ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        InetAddress peerAddress = getInetAddress();
472ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        if (peerAddress != null) {
473ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root            return peerAddress.getHostAddress();
474ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        }
475ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root
476ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root        return null;
477ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root    }
478ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root
479cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    @Override
480cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root    public int getPort() {
481534de4ef4d384320ed80182defe6db7dff24e9a5Narayan Kamath        return peerPort == -1 ? super.getPort() : peerPort;
4823967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson    }
4833967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson
484f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
4855006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb
48698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
487f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            throws CertificateEncodingException, SSLException {
4883c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals,
4893c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                sslNativePointer, this);
49098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
49198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
492f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
49301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @SuppressWarnings("unused") // used by native psk_client_callback
49401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
49501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this);
49601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
49701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
49801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
49901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @SuppressWarnings("unused") // used by native psk_server_callback
50001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
50101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this);
50201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
50301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
50401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
5055006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback
506f878e438660d93f8689b864165230492e7a412d4Kenny Root    public void onSSLStateChange(long sslSessionNativePtr, int type, int val) {
507f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        if (type != NativeConstants.SSL_CB_HANDSHAKE_DONE) {
508f878e438660d93f8689b864165230492e7a412d4Kenny Root            return;
509f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
510f878e438660d93f8689b864165230492e7a412d4Kenny Root
5118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
5128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_HANDSHAKE_STARTED) {
5138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // If sslSession is null, the handshake was completed during
5148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // the call to NativeCrypto.SSL_do_handshake and not during a
5158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // later read operation. That means we do not need to fix up
5168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // the SSLSession and session cache or notify
5178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // HandshakeCompletedListeners, it will be done in
5188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // startHandshake.
5198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                state = STATE_HANDSHAKE_COMPLETED;
5218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
5228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } else if (state == STATE_READY_HANDSHAKE_CUT_THROUGH) {
5238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We've returned from startHandshake, which means we've set a sslSession etc.
5248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // we need to fix them up, which we'll do outside this lock.
5258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } else if (state == STATE_CLOSED) {
5268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Someone called "close" but the handshake hasn't been interrupted yet.
5278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
5288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
5292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
53008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // reset session id from the native pointer and update the
5322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // appropriate cache.
5332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        sslSession.resetId();
5342828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        AbstractSessionContext sessionContext =
5352828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            (sslParameters.getUseClientMode())
5362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            ? sslParameters.getClientSessionContext()
5372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                : sslParameters.getServerSessionContext();
53808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sessionContext.putSession(sslSession);
5392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // let listeners know we are finally done
5412828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        notifyHandshakeCompletedListeners();
5428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
5448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // Now that we've fixed up our state, we can tell waiting threads that
5458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // we're ready.
5468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            state = STATE_READY;
5478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // Notify all threads waiting for the handshake to complete.
5488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            stateLock.notifyAll();
5498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
5502828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
5512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
5522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
5532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
5542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // notify the listeners
5552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            HandshakeCompletedEvent event =
5562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
5572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
5582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                try {
5592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                    listener.handshakeCompleted(event);
5602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                } catch (RuntimeException e) {
561371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // The RI runs the handlers in a separate thread,
562371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // which we do not. But we try to preserve their
563371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // behavior of logging a problem and not killing
564371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // the handshaking thread just because a listener
565371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // has a problem.
566371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    Thread thread = Thread.currentThread();
567371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
5682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                }
5692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
5702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
57108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
57208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5735006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks
574f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
575d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, String authMethod)
57698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            throws CertificateException {
57708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
5788d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            X509TrustManager x509tm = sslParameters.getX509TrustManager();
5798d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            if (x509tm == null) {
5808d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin                throw new CertificateException("No X.509 TrustManager");
5818d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            }
5820e9746b7b132058651155b33f219c7789997985bKenny Root            if (certRefs == null || certRefs.length == 0) {
583371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                throw new SSLException("Peer sent no certificate");
584371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            }
5850e9746b7b132058651155b33f219c7789997985bKenny Root            OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length];
5860e9746b7b132058651155b33f219c7789997985bKenny Root            for (int i = 0; i < certRefs.length; i++) {
5870e9746b7b132058651155b33f219c7789997985bKenny Root                peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]);
58808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
589d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
590d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            // Used for verifyCertificateChain callback
591d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain,
592ee1a154153a1b20d55fc4b0dd9752277f0cd6451Kenny Root                    getHostnameOrIP(), getPort(), null);
593d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
5942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
5952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (client) {
59650dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root                Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, this);
5979f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                if (sslParameters.isCTVerificationEnabled(getHostname())) {
5989f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    byte[] tlsData = NativeCrypto.SSL_get_signed_cert_timestamp_list(
5999f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                                        sslNativePointer);
6009f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    byte[] ocspData = NativeCrypto.SSL_get_ocsp_response(sslNativePointer);
6019f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar
6029f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    CTVerifier ctVerifier = sslParameters.getCTVerifier();
6039f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    CTVerificationResult result =
6049f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                        ctVerifier.verifySignedCertificateTimestamps(peerCertChain, tlsData, ocspData);
6059f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar
6069f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    if (result.getValidSCTs().size() == 0) {
6079f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                        throw new CertificateException("No valid SCT found");
6089f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                    }
6099f5850838f16ec1cc53ec1f2ece559c2e6396d3ePaul Lietar                }
6102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            } else {
6110e9746b7b132058651155b33f219c7789997985bKenny Root                String authType = peerCertChain[0].getPublicKey().getAlgorithm();
61250dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root                Platform.checkClientTrusted(x509tm, peerCertChain, authType, this);
61308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
6142828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (CertificateException e) {
6152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw e;
6162828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (Exception e) {
6179400b50da5ca8f1e796f5b158063db0aefb58441Brian Carlstrom            throw new CertificateException(e);
618d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        } finally {
619d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            // Clear this before notifying handshake completed listeners
620d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            handshakeSession = null;
62108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
62208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
62308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
624f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
625f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public InputStream getInputStream() throws IOException {
626a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
6278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        InputStream returnVal;
6298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
6308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
6318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed.");
6328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (is == null) {
63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                is = new SSLInputStream();
63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
63708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            returnVal = is;
63908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
6408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Block waiting for a handshake without a lock held. It's possible that the socket
6428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // is closed at this point. If that happens, we'll still return the input stream but
6438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // all reads on it will throw.
6448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        waitForHandshake();
6458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        return returnVal;
64608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
648f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
649f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public OutputStream getOutputStream() throws IOException {
650a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
6518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        OutputStream returnVal;
6538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
6548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
6558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed.");
6568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (os == null) {
65908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                os = new SSLOutputStream();
66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            returnVal = os;
6638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
6648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Block waiting for a handshake without a lock held. It's possible that the socket
6668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // is closed at this point. If that happens, we'll still return the output stream but
6678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // all writes on it will throw.
6688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        waitForHandshake();
6698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        return returnVal;
6708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
6718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void assertReadableOrWriteableState() {
6738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) {
6748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            return;
6758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
6768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        throw new AssertionError("Invalid state: " + state);
6788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
6798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void waitForHandshake() throws IOException {
6828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        startHandshake();
6838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
6858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            while (state != STATE_READY &&
6868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state != STATE_READY_HANDSHAKE_CUT_THROUGH &&
6878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state != STATE_CLOSED) {
6888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                try {
6898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.wait();
6908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } catch (InterruptedException e) {
6918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    Thread.currentThread().interrupt();
6928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    IOException ioe = new IOException("Interrupted waiting for handshake");
6938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    ioe.initCause(e);
6948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    throw ioe;
6968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
6978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
7008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed");
7018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
70208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
70308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
70408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
7052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
70608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides input data stream functionality
70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
70808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * read data received via SSL protocol.
70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLInputStream extends InputStream {
7118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        /**
7128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * OpenSSL only lets one thread read at a time, so this is used to
7138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * make sure we serialize callers of SSL_read. Thread is already
7148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * expected to have completed handshaking.
7158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         */
7168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        private final Object readLock = new Object();
7178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLInputStream() {
71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
72108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
72208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
72308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * this operation can block until the data will be
72408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * available.
72508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @return read value.
7260e9746b7b132058651155b33f219c7789997985bKenny Root         * @throws IOException
72708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
72908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read() throws IOException {
7303e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            byte[] buffer = new byte[1];
7313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            int result = read(buffer, 0, 1);
7323e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return (result != -1) ? buffer[0] & 0xff : -1;
73308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
73408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
73508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
73608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
73708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
73808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
74097e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes        public int read(byte[] buf, int offset, int byteCount) throws IOException {
741126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root            Platform.blockGuardOnNetwork();
7428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            checkOpen();
7449b343fce2ab41569e858cc2503bc6d9411af0a3bKenny Root            ArrayUtils.checkOffsetAndCount(buf.length, offset, byteCount);
7458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (byteCount == 0) {
7468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return 0;
7478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
7488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
749f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
7508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
7518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
7528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        throw new SocketException("socket is closed");
7538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
7548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (DBG_STATE) assertReadableOrWriteableState();
7567b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom                }
7578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                return NativeCrypto.SSL_read(sslNativePointer, Platform.getFileDescriptor(socket),
759a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes                        OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout());
76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
7628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        public void awaitPendingOps() {
7648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (DBG_STATE) {
7658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
7668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state != STATE_CLOSED) throw new AssertionError("State is: " + state);
7678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
7688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
7698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (readLock) { }
7718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
77508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides output data stream functionality
77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * write data according to the encryption parameters given in SSL context.
77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
77908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLOutputStream extends OutputStream {
7808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        /**
7828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * OpenSSL only lets one thread write at a time, so this is used
7838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * to make sure we serialize callers of SSL_write. Thread is
7848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * already expected to have completed handshaking.
7858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         */
7868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        private final Object writeLock = new Object();
7878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLOutputStream() {
78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
79108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
79208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(int)
79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7950b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
7965c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom        public void write(int oneByte) throws IOException {
7973e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            byte[] buffer = new byte[1];
7983e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            buffer[0] = (byte) (oneByte & 0xff);
7993e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            write(buffer);
80008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
80108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
80308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
8060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
80797e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes        public void write(byte[] buf, int offset, int byteCount) throws IOException {
808126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root            Platform.blockGuardOnNetwork();
8098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            checkOpen();
8109b343fce2ab41569e858cc2503bc6d9411af0a3bKenny Root            ArrayUtils.checkOffsetAndCount(buf.length, offset, byteCount);
8118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (byteCount == 0) {
8128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
8138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
8148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
815f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
8168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
8178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
8188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        throw new SocketException("socket is closed");
8198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
8208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (DBG_STATE) assertReadableOrWriteableState();
8227b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom                }
8238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8243e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                NativeCrypto.SSL_write(sslNativePointer, Platform.getFileDescriptor(socket),
825fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                        OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds);
82608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
82708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
8288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        public void awaitPendingOps() {
8318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (DBG_STATE) {
8328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
8338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state != STATE_CLOSED) throw new AssertionError("State is: " + state);
8348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
8358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
8368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (writeLock) { }
8388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
83908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
84108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
842f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
843f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public SSLSession getSession() {
844e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        if (sslSession == null) {
845e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            try {
8468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                waitForHandshake();
847e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            } catch (IOException e) {
848e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // return an invalid session with
849e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
850f111f6235d016ce54ab95a2c634a400efe29f24bKenny Root                return SSLNullSession.getNullSession();
851e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            }
85208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
853ce18fe693803e95ab627929b8e69d3362340dd06Kenny Root        return Platform.wrapSSLSession(sslSession);
85408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
85508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
85650dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    // Comment annotation to compile Conscrypt unbundled with Java 6.
85750dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    /* @Override */
85850dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    public SSLSession getHandshakeSession() {
85950dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root        return handshakeSession;
86050dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    }
86150dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root
862d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    @Override
863f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void addHandshakeCompletedListener(
86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
86508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
8695006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson            listeners = new ArrayList<HandshakeCompletedListener>();
87008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        listeners.add(listener);
87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
87308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
874f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
875f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void removeHandshakeCompletedListener(
87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
87708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
87808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
88108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
88208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
88308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
88408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!listeners.remove(listener)) {
88508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
88608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
88708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
88808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
890f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
891f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getEnableSessionCreation() {
89208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getEnableSessionCreation();
89308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
89408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
895f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
896f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnableSessionCreation(boolean flag) {
89708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
89808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
89908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
900f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
901f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getSupportedCipherSuites() {
902f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
90308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
90408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
905f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
906f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getEnabledCipherSuites() {
907f878e438660d93f8689b864165230492e7a412d4Kenny Root        return sslParameters.getEnabledCipherSuites();
90808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
90908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
910f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
911f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnabledCipherSuites(String[] suites) {
912f878e438660d93f8689b864165230492e7a412d4Kenny Root        sslParameters.setEnabledCipherSuites(suites);
91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
915f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
916f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getSupportedProtocols() {
917f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
920f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
921f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getEnabledProtocols() {
922ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin        return sslParameters.getEnabledProtocols();
92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
925f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
926f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnabledProtocols(String[] protocols) {
927ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin        sslParameters.setEnabledProtocols(protocols);
92808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
92908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
93008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
9310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables session ticket support.
9320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param useSessionTickets True to enable session tickets
9340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
9363c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.useSessionTickets = useSessionTickets;
9370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
9390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
9400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables Server Name Indication
9410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
9420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
9430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
9440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHostname(String hostname) {
9453c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.setUseSni(hostname != null);
946cc2ef2e2e9ee64f2e0ac2abc7fdf636e2f81fa5eKenny Root        peerHostname = hostname;
9470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
9480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
949577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
950577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Enables/disables TLS Channel ID for this server socket.
951577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
952577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * <p>This method needs to be invoked before the handshake starts.
953577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
954577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a client socket or if the handshake has already
955577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         started.
956577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
957577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    public void setChannelIdEnabled(boolean enabled) {
958577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (getUseClientMode()) {
959577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Client mode");
960577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
9618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
9628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
9638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
9648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
9658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not enable/disable Channel ID after the initial handshake has"
9668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                                + " begun.");
9678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
968577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
9693c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.channelIdEnabled = enabled;
970577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
971577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
972577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
973577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Gets the TLS Channel ID for this server socket. Channel ID is only available once the
974577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * handshake completes.
975577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
976577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @return channel ID or {@code null} if not available.
977577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
978577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a client socket or if the handshake has not yet
979577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         completed.
980577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws SSLException if channel ID is available but could not be obtained.
981577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
982577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    public byte[] getChannelId() throws SSLException {
983577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (getUseClientMode()) {
984577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Client mode");
985577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
9868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
9878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
9888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_READY) {
9898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
9908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Channel ID is only available after handshake completes");
9918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
992577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
993577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer);
994577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
995577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
996577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
997577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket.
998577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
999577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * <p>This method needs to be invoked before the handshake starts.
1000577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
1001577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
10024022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin     *        TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST
1003577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *        P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
1004577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
1005577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a server socket or if the handshake has already
1006577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         started.
1007577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
10084022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin    public void setChannelIdPrivateKey(PrivateKey privateKey) {
1009577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (!getUseClientMode()) {
1010577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Server mode");
1011577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
10128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
10148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
10158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
10168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not change Channel ID private key after the initial handshake has"
10178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                                + " begun.");
10188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
1019577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
10208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10211ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        if (privateKey == null) {
10223c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.channelIdEnabled = false;
10233c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            channelIdPrivateKey = null;
10241ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        } else {
10253c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.channelIdEnabled = true;
10261ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            try {
10277dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                ECParameterSpec ecParams = null;
10287dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                if (privateKey instanceof ECKey) {
10297dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                    ecParams = ((ECKey) privateKey).getParams();
10307dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                }
10317dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                if (ecParams == null) {
10327dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                    // Assume this is a P-256 key, as specified in the contract of this method.
10337dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                    ecParams =
10347dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                            OpenSSLECGroupContext.getCurveByName("prime256v1").getECParameterSpec();
10357dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                }
10367dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                channelIdPrivateKey =
10377dab2fdf7cffde2f1b3b9e552c3a3f7c49953f13Alex Klyubin                        OpenSSLKey.fromECPrivateKeyForTLSStackOnly(privateKey, ecParams);
10381ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            } catch (InvalidKeyException e) {
10391ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                // Will have error in startHandshake
10401ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            }
10411ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        }
1042577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
1043577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
1044f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1045f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getUseClientMode() {
104608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getUseClientMode();
104708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
104808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1049f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1050f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setUseClientMode(boolean mode) {
10518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
10528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
10538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalArgumentException(
10548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not change the mode after the initial handshake has begun.");
10558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
105608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
105708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setUseClientMode(mode);
105808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
105908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1060f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1061f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getWantClientAuth() {
106208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getWantClientAuth();
106308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
106408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1065f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1066f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getNeedClientAuth() {
106708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getNeedClientAuth();
106808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
106908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1070f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1071f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setNeedClientAuth(boolean need) {
107208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setNeedClientAuth(need);
107308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
107408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1075f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1076f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setWantClientAuth(boolean want) {
107708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setWantClientAuth(want);
107808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
107908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1080f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1081f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void sendUrgentData(int data) throws IOException {
10825006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        throw new SocketException("Method sendUrgentData() is not supported.");
108308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
108408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1085f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1086f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setOOBInline(boolean on) throws SocketException {
10875006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        throw new SocketException("Methods sendUrgentData, setOOBInline are not supported.");
108808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
108908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1090f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1091f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException {
1092db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath        if (socket != this) {
1093db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath            socket.setSoTimeout(readTimeoutMilliseconds);
1094db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath        } else {
1095db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath            super.setSoTimeout(readTimeoutMilliseconds);
1096db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath        }
1097db1c62336d19fb11dd777e75f52faaafd8e7e94bNarayan Kamath
1098fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.readTimeoutMilliseconds = readTimeoutMilliseconds;
109972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    }
110072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
1101f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1102f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public int getSoTimeout() throws SocketException {
1103fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        return readTimeoutMilliseconds;
1104fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    }
1105fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
1106fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    /**
1107fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     * Note write timeouts are not part of the javax.net.ssl.SSLSocket API
1108fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     */
1109fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException {
1110fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.writeTimeoutMilliseconds = writeTimeoutMilliseconds;
1111fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
1112afb340348bfc54dbc46964e159fe803f9c93a4ddKenny Root        Platform.setSocketWriteTimeout(this, writeTimeoutMilliseconds);
1113fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    }
1114fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
1115fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    /**
1116fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     * Note write timeouts are not part of the javax.net.ssl.SSLSocket API
1117fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     */
1118fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public int getSoWriteTimeout() throws SocketException {
1119fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        return writeTimeoutMilliseconds;
112008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
112108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1122331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    /**
1123331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
1124331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * milliseconds and will be used only during the handshake process.
1125331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     */
1126fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException {
1127fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds;
1128331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    }
1129331900211d05cd282141a3a50cb1db626f418b2cDan Egnor
1130f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1131f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void close() throws IOException {
11325006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        // TODO: Close SSL sockets using a background thread so they close gracefully.
113308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLInputStream sslInputStream = null;
11358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLOutputStream sslOutputStream = null;
1136f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
11378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
11388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
11398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // close() has already been called, so do nothing and return.
11408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
11418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
114208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            int oldState = state;
11448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            state = STATE_CLOSED;
11458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
11468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (oldState == STATE_NEW) {
11478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // The handshake hasn't been started yet, so there's no OpenSSL related
11488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // state to clean up. We still need to close the underlying socket if
11498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // we're wrapping it and were asked to autoClose.
11508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                closeUnderlyingSocket();
1151f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
11528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                stateLock.notifyAll();
115308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
115408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
115508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) {
11578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // If we're in these states, we still haven't returned from startHandshake.
11588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then
11598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // set the state to STATE_CLOSED. startHandshake will handle all cleanup
11608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // after SSL_do_handshake returns, so we don't have anything to do here.
11618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                NativeCrypto.SSL_interrupt(sslNativePointer);
116208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
11638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                stateLock.notifyAll();
11648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
11658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
11668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
11678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            stateLock.notifyAll();
11688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // We've already returned from startHandshake, so we potentially have
11698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // input and output streams to clean up.
11708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslInputStream = is;
11718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslOutputStream = os;
11728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
11738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
11748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Don't bother interrupting unless we have something to interrupt.
11758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslInputStream != null || sslOutputStream != null) {
1176fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom            NativeCrypto.SSL_interrupt(sslNativePointer);
11778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
11788b352156f879e7b36d223d3f65b8de46b7dc4dcfBrian Carlstrom
11798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Wait for the input and output streams to finish any reads they have in
11808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // progress. If there are no reads in progress at this point, future reads will
11818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // throw because state == STATE_CLOSED
11828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslInputStream != null) {
11838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslInputStream.awaitPendingOps();
11848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
11858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslOutputStream != null) {
11868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslOutputStream.awaitPendingOps();
11878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
11888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
11898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        shutdownAndFreeSslNative();
11908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
11918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
11928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void shutdownAndFreeSslNative() throws IOException {
11938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        try {
1194126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root            Platform.blockGuardOnNetwork();
11953e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            NativeCrypto.SSL_shutdown(sslNativePointer, Platform.getFileDescriptor(socket),
11968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    this);
11978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } catch (IOException ignored) {
11988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            /*
11998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * Note that although close() can throw
12008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * IOException, the RI does not throw if there
12018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * is problem sending a "close notify" which
12028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * can happen if the underlying socket is closed.
12038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            */
12048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } finally {
12058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            free();
12068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            closeUnderlyingSocket();
12078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
12088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
12098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
12108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void closeUnderlyingSocket() throws IOException {
12118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (socket != this) {
12128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (autoClose && !socket.isClosed()) {
12138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                socket.close();
12148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
12158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } else {
12168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (!super.isClosed()) {
12178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                super.close();
121808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
121908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
122008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
122108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1222f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private void free() {
1223f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (sslNativePointer == 0) {
1224f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            return;
1225f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
1226f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1227f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        sslNativePointer = 0;
1228126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root        Platform.closeGuardClose(guard);
1229f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
123008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1231f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1232f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    protected void finalize() throws Throwable {
12331990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        try {
12341990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            /*
12351990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * Just worry about our own state. Notably we do not try and
12361990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * close anything. The SocketImpl, either our own
12371990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * PlainSocketImpl, or the Socket we are wrapping, will do
12381990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * that. This might mean we do not properly SSL_shutdown, but
12391990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * if you want to do that, properly close the socket yourself.
12401990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             *
12411990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * The reason why we don't try to SSL_shutdown, is that there
12421990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * can be a race between finalizers where the PlainSocketImpl
12431990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * finalizer runs first and closes the socket. However, in the
12441990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * meanwhile, the underlying file descriptor could be reused
12451990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * for another purpose. If we call SSL_shutdown, the
12461990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * underlying socket BIOs still have the old file descriptor
12471990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * and will write the close notify to some unsuspecting
12481990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * reader.
12491990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             */
1250f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom            if (guard != null) {
1251126ec77aacd58c8b5d62d433af65386fa3dd3fc1Kenny Root                Platform.closeGuardWarnIfOpen(guard);
1252f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom            }
12531990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            free();
12541990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        } finally {
12551990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            super.finalize();
12561990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        }
125708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
12580648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey
12593e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    /* @Override */
12600648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey    public FileDescriptor getFileDescriptor$() {
12610648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        if (socket == this) {
12623e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return Platform.getFileDescriptorFromSSLSocket(this);
12630648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        } else {
12643e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return Platform.getFileDescriptor(socket);
12650648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        }
12660648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey    }
1267721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson
1268721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    /**
1269721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * Returns the protocol agreed upon by client and server, or null if no
1270721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * protocol was agreed upon.
1271721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     */
1272721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    public byte[] getNpnSelectedProtocol() {
1273263808a68e1538db41196065830107991e9f974aJesse Wilson        return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer);
1274721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    }
1275721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson
1276721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    /**
12776fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * Returns the protocol agreed upon by client and server, or {@code null} if
12786fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * no protocol was agreed upon.
12796fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     */
12806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public byte[] getAlpnSelectedProtocol() {
12816fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer);
12826fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    }
12836fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
12846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    /**
1285721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * Sets the list of protocols this peer is interested in. If null no
1286721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * protocols will be used.
1287721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     *
1288d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     * @param npnProtocols a non-empty array of protocol names. From
1289d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     SSL_select_next_proto, "vector of 8-bit, length prefixed byte
1290d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     strings. The length byte itself is not included in the length. A byte
1291d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     string of length 0 is invalid. No byte string may be truncated.".
1292721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     */
1293721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    public void setNpnProtocols(byte[] npnProtocols) {
1294d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson        if (npnProtocols != null && npnProtocols.length == 0) {
1295d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson            throw new IllegalArgumentException("npnProtocols.length == 0");
1296d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson        }
12973c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.npnProtocols = npnProtocols;
1298721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    }
12996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
13006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    /**
13016fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * Sets the list of protocols this peer is interested in. If the list is
13026fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * {@code null}, no protocols will be used.
13036fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *
13046fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * @param alpnProtocols a non-empty array of protocol names. From
13056fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            SSL_select_next_proto, "vector of 8-bit, length prefixed byte
13066fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            strings. The length byte itself is not included in the length.
13076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            A byte string of length 0 is invalid. No byte string may be
13086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            truncated.".
13096fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     */
13106fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public void setAlpnProtocols(byte[] alpnProtocols) {
13116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        if (alpnProtocols != null && alpnProtocols.length == 0) {
13126fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            throw new IllegalArgumentException("alpnProtocols.length == 0");
13136fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        }
13143c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.alpnProtocols = alpnProtocols;
13152d089e18deae231149737cad6ce00f1e137a7199Alex Klyubin    }
1316d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
1317d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    @Override
131850dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    public SSLParameters getSSLParameters() {
131950dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root        SSLParameters params = super.getSSLParameters();
13205012f2dc5bf0a28a47cf9b01bd1a63c1ebdc232fKenny Root        Platform.getSSLParameters(params, sslParameters, this);
132150dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root        return params;
132250dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    }
132350dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root
132450dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    @Override
132550dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    public void setSSLParameters(SSLParameters p) {
132650dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root        super.setSSLParameters(p);
13275012f2dc5bf0a28a47cf9b01bd1a63c1ebdc232fKenny Root        Platform.setSSLParameters(p, sslParameters, this);
132850dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    }
132950dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root
133050dcd032dd00774cd5ab5a64a6e173b361d95024Kenny Root    @Override
13313c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    public String chooseServerAlias(X509KeyManager keyManager, String keyType) {
13323c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        return keyManager.chooseServerAlias(keyType, null, this);
13333c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    }
13343c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root
13353c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    @Override
13363c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers,
13373c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            String[] keyTypes) {
13383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        return keyManager.chooseClientAlias(keyTypes, null, this);
13393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    }
134001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
134101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
134201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) {
134301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.chooseServerKeyIdentityHint(this);
134401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
134501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
134601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
134701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) {
134801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.chooseClientKeyIdentity(identityHint, this);
134901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
135001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
135101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
135201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) {
135301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.getKey(identityHint, identity, this);
135401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
135508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project}
1356