OpenSSLSocketImpl.java revision b860016f415dfc5655dcee45f70e8871a2e3edfe
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
193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootimport org.conscrypt.util.Arrays;
20ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard;
21fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard;
220648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkeyimport java.io.FileDescriptor;
2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException;
2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream;
2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream;
2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress;
2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket;
2808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException;
291ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Rootimport java.security.InvalidKeyException;
3098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey;
3198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom;
321f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException;
3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException;
3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList;
3501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubinimport javax.crypto.SecretKey;
3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent;
3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener;
3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException;
39edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException;
40d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLParameters;
418765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException;
4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession;
438d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubinimport javax.net.ssl.X509KeyManager;
44fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager;
4598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal;
468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/**
480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL.
490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p>
500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include:
510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul>
520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout
530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets
540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication
550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul>
5608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */
57f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl
58f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        extends javax.net.ssl.SSLSocket
5901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser,
6001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        SSLParametersImpl.PSKCallbacks {
6190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom
628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final boolean DBG_STATE = false;
638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
6569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     * Protects handshakeStarted and handshakeCompleted.
6669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private final Object stateLock = new Object();
6869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
6969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * The {@link OpenSSLSocketImpl} object is constructed, but {@link #startHandshake()}
718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * has not yet been called.
7269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_NEW = 0;
7469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
7569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has been called at least once.
7769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_HANDSHAKE_STARTED = 1;
7969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
8069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #handshakeCompleted()} has been called, but {@link #startHandshake()} hasn't
828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * returned yet.
8369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_HANDSHAKE_COMPLETED = 2;
858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    /**
878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has completed but {@link #handshakeCompleted()} hasn't
888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake
898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * returns before the handshake is complete. We can now start writing data to the socket.
908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     */
918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 3;
9269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
9369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #startHandshake()} has completed and {@link #handshakeCompleted()} has been
958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * called.
9669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_READY = 4;
9869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
9969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * {@link #close()} has been called at least once.
10169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private static final int STATE_CLOSED = 5;
1038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
1048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private int state = STATE_NEW;
10669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
10769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as 0, set by
1098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * startHandshake, reset to 0 on close.
11069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private long sslNativePointer;
11369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
11469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /**
1158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as null, set by
1168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * getInputStream.
11769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom     */
1188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private SSLInputStream is;
1208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
1218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    /**
1228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * Protected by synchronizing on stateLock. Starts as null, set by
1238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     * getInputStream.
1248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath     */
1258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    // @GuardedBy("stateLock");
1268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private SSLOutputStream os;
12769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
12869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final Socket socket;
12969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final boolean autoClose;
13057ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root    private String wrappedHost;
13169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final int wrappedPort;
13269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final SSLParametersImpl sslParameters;
13369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private final CloseGuard guard = CloseGuard.get();
13469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
1353c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    private ArrayList<HandshakeCompletedListener> listeners;
1362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
1372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
1383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root     * Private key for the TLS Channel ID extension. This field is client-side
1393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root     * only. Set during startHandshake.
1402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
1413c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    OpenSSLKey channelIdPrivateKey;
14269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom
14369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    /** Set during startHandshake. */
14469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom    private OpenSSLSessionImpl sslSession;
1452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
146d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    /** Used during handshake callbacks. */
147d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    private OpenSSLSessionImpl handshakeSession;
148d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
14972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    /**
15072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * Local cache of timeout to avoid getsockopt on every read and
15172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * write for non-wrapped sockets. Note that
15272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * OpenSSLSocketImplWrapper overrides setSoTimeout and
15372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     * getSoTimeout to delegate to the wrapped socket.
15472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom     */
155fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    private int readTimeoutMilliseconds = 0;
156fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    private int writeTimeoutMilliseconds = 0;
15772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
15872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    private int handshakeTimeoutMilliseconds = -1;  // -1 = same as timeout; 0 = infinite
15908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
160cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException {
16190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
16269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedHost = null;
16369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedPort = -1;
16469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
16569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
16608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
16708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
168cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters)
16990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom            throws IOException {
17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(host, port);
17190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
17269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedHost = null;
17369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedPort = -1;
17469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
17569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
17608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
178cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom    protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters)
17990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom            throws IOException {
18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port);
18190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
18269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedHost = null;
18369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedPort = -1;
18469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
18569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
18608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
18708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
189c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom    protected OpenSSLSocketImpl(String host, int port,
190c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
1915006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson                                SSLParametersImpl sslParameters) throws IOException {
19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(host, port, clientAddress, clientPort);
19390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
19469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedHost = null;
19569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedPort = -1;
19669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
19769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
19908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
20008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(InetAddress address, int port,
201c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom                                InetAddress clientAddress, int clientPort,
2025006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson                                SSLParametersImpl sslParameters) throws IOException {
20308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        super(address, port, clientAddress, clientPort);
20490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom        this.socket = this;
20569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedHost = null;
20669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.wrappedPort = -1;
20769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.autoClose = false;
20869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
20908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
21008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
21108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
2125006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson     * Create an SSL socket that wraps another socket. Invoked by
2135006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson     * OpenSSLSocketImplWrapper constructor.
21408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
21508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    protected OpenSSLSocketImpl(Socket socket, String host, int port,
216cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom            boolean autoClose, SSLParametersImpl sslParameters) throws IOException {
21708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.socket = socket;
2186e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom        this.wrappedHost = host;
2196e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom        this.wrappedPort = port;
22008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        this.autoClose = autoClose;
22169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom        this.sslParameters = sslParameters;
22272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
22372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // this.timeout is not set intentionally.
22472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout
22572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom        // to wrapped socket
226f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
227f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
228a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    private void checkOpen() throws SocketException {
229a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        if (isClosed()) {
230a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom            throw new SocketException("Socket is closed");
231a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        }
232a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    }
233a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom
234a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom    /**
235d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * Starts a TLS/SSL handshake on this connection using some native methods
236d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * from the OpenSSL library. It can negotiate new encryption keys, change
237d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * cipher suites, or initiate a new session. The certificate chain is
238d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * verified if the correspondent property in java.Security is set. All
239d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson     * listeners are notified at the end of the TLS/SSL handshake.
2402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom     */
241f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
242f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void startHandshake() throws IOException {
2438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        checkOpen();
2448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
2458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_NEW) {
2468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                state = STATE_HANDSHAKE_STARTED;
24708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            } else {
2488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We've either started the handshake already or have been closed.
2498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Do nothing in both cases.
25008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
25108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
25208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
25308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
25498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        // note that this modifies the global seed, not something specific to the connection
25598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES;
25698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final SecureRandom secureRandom = sslParameters.getSecureRandomMember();
25798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        if (secureRandom == null) {
25898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes);
25998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        } else {
26098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes));
26198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        }
26298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
26398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom        final boolean client = sslParameters.getUseClientMode();
26498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
2658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        sslNativePointer = 0;
2668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        boolean releaseResources = true;
267fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom        try {
2683c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final AbstractSessionContext sessionContext = sslParameters.getSessionContext();
2693c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final long sslCtxNativePointer = sessionContext.sslCtxNativePointer;
270fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer);
271fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            guard.open("close");
27298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
2733c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            boolean enableSessionCreation = getEnableSessionCreation();
274fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (!enableSessionCreation) {
275fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer,
2763c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                        enableSessionCreation);
2772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
2782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
2793c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            final OpenSSLSessionImpl sessionToReuse = sslParameters.getSessionToReuse(
2803c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                    sslNativePointer, getPeerHostName(), getPeerPort());
28101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this,
2823c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                    getPeerHostName());
2833c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.setCertificateValidation(sslNativePointer);
2843c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey);
285f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
286fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // Temporarily use a different timeout for the handshake process
287fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom            int savedReadTimeoutMilliseconds = getSoTimeout();
288fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom            int savedWriteTimeoutMilliseconds = getSoWriteTimeout();
289fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
290fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                setSoTimeout(handshakeTimeoutMilliseconds);
291fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoWriteTimeout(handshakeTimeoutMilliseconds);
292fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
2932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
2948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
2958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_CLOSED) {
2968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    return;
2978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
2988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
2998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3007dd8d0b433cf8212538aaaf8726f5222abf035ddMatteo Franchin            long sslSessionNativePointer;
301fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            try {
302a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes                sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer,
3033e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                        Platform.getFileDescriptor(socket), this, getSoTimeout(), client,
3043c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                        sslParameters.npnProtocols, client ? null : sslParameters.alpnProtocols);
305fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            } catch (CertificateException e) {
306d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage());
307d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                wrapper.initCause(e);
308d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom                throw wrapper;
3098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } catch (SSLException e) {
3108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Swallow this exception if it's thrown as the result of an interruption.
3118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                //
3128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake
3138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ
3148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // (or WANT_WRITE). Catching that exception here doesn't seem much worse than
3158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // changing the native code to return a "special" native pointer value when that
3168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // happens.
3178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
3188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
3198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        return;
3208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
3218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw e;
3242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
3258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            boolean handshakeCompleted = false;
3278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
3288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_HANDSHAKE_COMPLETED) {
3298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    handshakeCompleted = true;
3308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } else if (state == STATE_CLOSED) {
3318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    return;
3328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
3348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3350dd7db8b85dfd8ad5d16d239432b9852450dc78fKenny Root            sslSession = sslParameters.setupSession(sslSessionNativePointer, sslNativePointer,
3363c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                    sessionToReuse, getPeerHostName(), getPeerPort(), handshakeCompleted);
337fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom
338fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // Restore the original timeout now that the handshake is complete
339fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeTimeoutMilliseconds >= 0) {
340fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoTimeout(savedReadTimeoutMilliseconds);
341fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                setSoWriteTimeout(savedWriteTimeoutMilliseconds);
342331900211d05cd282141a3a50cb1db626f418b2cDan Egnor            }
34308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
344fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback
345fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            if (handshakeCompleted) {
346fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom                notifyHandshakeCompletedListeners();
347fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
348f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
3498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (stateLock) {
3508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                releaseResources = (state == STATE_CLOSED);
3518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (state == STATE_HANDSHAKE_STARTED) {
3538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_READY_HANDSHAKE_CUT_THROUGH;
3548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } else if (state == STATE_HANDSHAKE_COMPLETED) {
3558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_READY;
3568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                if (!releaseResources) {
3598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // Unblock threads that are waiting for our state to transition
3608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH.
3618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.notifyAll();
3628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
3648765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom        } catch (SSLProtocolException e) {
3653e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed")
3663e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                    .initCause(e);
367fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom        } finally {
368aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom            // on exceptional exit, treat the socket as closed
3698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (releaseResources) {
3708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
3718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // Mark the socket as closed since we might have reached this as
3728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // a result on an exception thrown by the handshake process.
3738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    //
3748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // The state will already be set to closed if we reach this as a result of
3758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    // an early return or an interruption due to a concurrent call to close().
3768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state = STATE_CLOSED;
3778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.notifyAll();
3788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
3798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                try {
3818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    shutdownAndFreeSslNative();
3828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } catch (IOException ignored) {
3838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
3848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
385fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom            }
38608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
387e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom    }
3883ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root
389bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra    String getPeerHostName() {
3908ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        if (wrappedHost != null) {
3918ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom            return wrappedHost;
3928ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        }
3938ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        InetAddress inetAddress = super.getInetAddress();
3948ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        if (inetAddress != null) {
3958ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom            return inetAddress.getHostName();
3968ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        }
3978ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom        return null;
3983967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson    }
3993967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson
400bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra    int getPeerPort() {
4013967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson        return wrappedHost == null ? super.getPort() : wrappedPort;
4023967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson    }
4033967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson
404f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
4055006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb
40698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom    public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals)
407f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            throws CertificateEncodingException, SSLException {
4083c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals,
4093c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                sslNativePointer, this);
41098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom    }
41198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom
412f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
41301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @SuppressWarnings("unused") // used by native psk_client_callback
41401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
41501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this);
41601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
41701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
41801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
41901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @SuppressWarnings("unused") // used by native psk_server_callback
42001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
42101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this);
42201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
42301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
42401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
4255006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback
426f878e438660d93f8689b864165230492e7a412d4Kenny Root    public void onSSLStateChange(long sslSessionNativePtr, int type, int val) {
427f878e438660d93f8689b864165230492e7a412d4Kenny Root        if (type != NativeCrypto.SSL_CB_HANDSHAKE_DONE) {
428f878e438660d93f8689b864165230492e7a412d4Kenny Root            return;
429f878e438660d93f8689b864165230492e7a412d4Kenny Root        }
430f878e438660d93f8689b864165230492e7a412d4Kenny Root
4318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
4328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_HANDSHAKE_STARTED) {
4338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // If sslSession is null, the handshake was completed during
4348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // the call to NativeCrypto.SSL_do_handshake and not during a
4358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // later read operation. That means we do not need to fix up
4368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // the SSLSession and session cache or notify
4378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // HandshakeCompletedListeners, it will be done in
4388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // startHandshake.
4398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                state = STATE_HANDSHAKE_COMPLETED;
4418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
4428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } else if (state == STATE_READY_HANDSHAKE_CUT_THROUGH) {
4438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We've returned from startHandshake, which means we've set a sslSession etc.
4448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // we need to fix them up, which we'll do outside this lock.
4458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            } else if (state == STATE_CLOSED) {
4468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // Someone called "close" but the handshake hasn't been interrupted yet.
4478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
4488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
4492828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
45008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // reset session id from the native pointer and update the
4522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // appropriate cache.
4532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        sslSession.resetId();
4542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        AbstractSessionContext sessionContext =
4552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            (sslParameters.getUseClientMode())
4562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            ? sslParameters.getClientSessionContext()
4572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                : sslParameters.getServerSessionContext();
45808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sessionContext.putSession(sslSession);
4592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
4602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        // let listeners know we are finally done
4612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        notifyHandshakeCompletedListeners();
4628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
4638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
4648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // Now that we've fixed up our state, we can tell waiting threads that
4658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // we're ready.
4668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            state = STATE_READY;
4678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // Notify all threads waiting for the handshake to complete.
4688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            stateLock.notifyAll();
4698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
4702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    }
4712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom
4722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    private void notifyHandshakeCompletedListeners() {
4732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        if (listeners != null && !listeners.isEmpty()) {
4742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            // notify the listeners
4752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            HandshakeCompletedEvent event =
4762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                new HandshakeCompletedEvent(this, sslSession);
4772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            for (HandshakeCompletedListener listener : listeners) {
4782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                try {
4792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                    listener.handshakeCompleted(event);
4802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                } catch (RuntimeException e) {
481371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // The RI runs the handlers in a separate thread,
482371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // which we do not. But we try to preserve their
483371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // behavior of logging a problem and not killing
484371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // the handshaking thread just because a listener
485371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    // has a problem.
486371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    Thread thread = Thread.currentThread();
487371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                    thread.getUncaughtExceptionHandler().uncaughtException(thread, e);
4882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom                }
4892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            }
4902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        }
49108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
49208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
4935006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson    @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks
494f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
495d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, String authMethod)
49698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom            throws CertificateException {
49708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        try {
4988d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            X509TrustManager x509tm = sslParameters.getX509TrustManager();
4998d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            if (x509tm == null) {
5008d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin                throw new CertificateException("No X.509 TrustManager");
5018d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin            }
5020e9746b7b132058651155b33f219c7789997985bKenny Root            if (certRefs == null || certRefs.length == 0) {
503371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom                throw new SSLException("Peer sent no certificate");
504371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom            }
5050e9746b7b132058651155b33f219c7789997985bKenny Root            OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length];
5060e9746b7b132058651155b33f219c7789997985bKenny Root            for (int i = 0; i < certRefs.length; i++) {
5070e9746b7b132058651155b33f219c7789997985bKenny Root                peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]);
50808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
509d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
510d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            // Used for verifyCertificateChain callback
511d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain,
512d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                    getPeerHostName(), getPeerPort(), null);
513d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
5142828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            boolean client = sslParameters.getUseClientMode();
5152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            if (client) {
516b860016f415dfc5655dcee45f70e8871a2e3edfeBrian Carlstrom                Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, getPeerHostName());
5172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            } else {
5180e9746b7b132058651155b33f219c7789997985bKenny Root                String authType = peerCertChain[0].getPublicKey().getAlgorithm();
519b860016f415dfc5655dcee45f70e8871a2e3edfeBrian Carlstrom                x509tm.checkClientTrusted(peerCertChain, authType);
52008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
5212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (CertificateException e) {
5222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom            throw e;
5232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom        } catch (Exception e) {
5249400b50da5ca8f1e796f5b158063db0aefb58441Brian Carlstrom            throw new CertificateException(e);
525d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        } finally {
526d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            // Clear this before notifying handshake completed listeners
527d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root            handshakeSession = null;
52808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
52908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
53008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
531f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
532f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public InputStream getInputStream() throws IOException {
533a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
5348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        InputStream returnVal;
5368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
5378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
5388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed.");
5398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
5408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
54108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (is == null) {
54208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                is = new SSLInputStream();
54308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
54408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            returnVal = is;
54608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
5478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Block waiting for a handshake without a lock held. It's possible that the socket
5498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // is closed at this point. If that happens, we'll still return the input stream but
5508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // all reads on it will throw.
5518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        waitForHandshake();
5528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        return returnVal;
55308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
55408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
555f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
556f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public OutputStream getOutputStream() throws IOException {
557a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom        checkOpen();
5588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        OutputStream returnVal;
5608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
5618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
5628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed.");
5638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
5648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
56508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            if (os == null) {
56608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                os = new SSLOutputStream();
56708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
56808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
5698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            returnVal = os;
5708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
5718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Block waiting for a handshake without a lock held. It's possible that the socket
5738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // is closed at this point. If that happens, we'll still return the output stream but
5748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // all writes on it will throw.
5758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        waitForHandshake();
5768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        return returnVal;
5778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
5788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void assertReadableOrWriteableState() {
5808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) {
5818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            return;
5828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
5838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        throw new AssertionError("Invalid state: " + state);
5858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
5868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void waitForHandshake() throws IOException {
5898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        startHandshake();
5908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
5918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
5928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            while (state != STATE_READY &&
5938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state != STATE_READY_HANDSHAKE_CUT_THROUGH &&
5948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    state != STATE_CLOSED) {
5958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                try {
5968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    stateLock.wait();
5978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                } catch (InterruptedException e) {
5988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    Thread.currentThread().interrupt();
5998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    IOException ioe = new IOException("Interrupted waiting for handshake");
6008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    ioe.initCause(e);
6018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    throw ioe;
6038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
6048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
6078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new SocketException("Socket is closed");
6088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
60908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
61008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
61108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
6122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom    /**
61308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides input data stream functionality
61408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
61508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * read data received via SSL protocol.
61608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
61708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLInputStream extends InputStream {
6188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        /**
6198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * OpenSSL only lets one thread read at a time, so this is used to
6208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * make sure we serialize callers of SSL_read. Thread is already
6218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * expected to have completed handshaking.
6228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         */
6238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        private final Object readLock = new Object();
6248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLInputStream() {
62608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
62708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
62808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
62908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Reads one byte. If there is no data in the underlying buffer,
63008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * this operation can block until the data will be
63108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * available.
63208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @return read value.
6330e9746b7b132058651155b33f219c7789997985bKenny Root         * @throws IOException
63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
6350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        public int read() throws IOException {
6373e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            byte[] buffer = new byte[1];
6383e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            int result = read(buffer, 0, 1);
6393e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return (result != -1) ? buffer[0] & 0xff : -1;
64008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.InputStream#read(byte[],int,int)
64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
6460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
64797e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes        public int read(byte[] buf, int offset, int byteCount) throws IOException {
648ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
6498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            checkOpen();
6518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            Arrays.checkOffsetAndCount(buf.length, offset, byteCount);
6528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (byteCount == 0) {
6538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return 0;
6548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
656f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (readLock) {
6578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
6588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
6598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        throw new SocketException("socket is closed");
6608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
6618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (DBG_STATE) assertReadableOrWriteableState();
6637b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom                }
6648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6653e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                return NativeCrypto.SSL_read(sslNativePointer, Platform.getFileDescriptor(socket),
666a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes                        OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout());
66708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
66808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
6698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        public void awaitPendingOps() {
6718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (DBG_STATE) {
6728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
6738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state != STATE_CLOSED) throw new AssertionError("State is: " + state);
6748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
6758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
6768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (readLock) { }
6788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
67908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
68108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
68208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * This inner class provides output data stream functionality
68308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * for the OpenSSL native implementation. It is used to
68408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     * write data according to the encryption parameters given in SSL context.
68508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project     */
68608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    private class SSLOutputStream extends OutputStream {
6878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        /**
6898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * OpenSSL only lets one thread write at a time, so this is used
6908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * to make sure we serialize callers of SSL_write. Thread is
6918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         * already expected to have completed handshaking.
6928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath         */
6938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        private final Object writeLock = new Object();
6948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
6958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLOutputStream() {
69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
70008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(int)
70108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7020b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
7035c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom        public void write(int oneByte) throws IOException {
7043e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            byte[] buffer = new byte[1];
7053e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            buffer[0] = (byte) (oneByte & 0xff);
7063e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            write(buffer);
70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
70808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        /**
71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * Method acts as described in spec for superclass.
71108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         * @see java.io.OutputStream#write(byte[],int,int)
71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project         */
7130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom        @Override
71497e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes        public void write(byte[] buf, int offset, int byteCount) throws IOException {
715ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick            BlockGuard.getThreadPolicy().onNetwork();
7168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            checkOpen();
7178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            Arrays.checkOffsetAndCount(buf.length, offset, byteCount);
7188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (byteCount == 0) {
7198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
7208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
7218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
722f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom            synchronized (writeLock) {
7238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
7248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state == STATE_CLOSED) {
7258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        throw new SocketException("socket is closed");
7268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    }
7278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (DBG_STATE) assertReadableOrWriteableState();
7297b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom                }
7308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7313e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root                NativeCrypto.SSL_write(sslNativePointer, Platform.getFileDescriptor(socket),
732fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom                        OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds);
73308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
73408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
7358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        public void awaitPendingOps() {
7388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (DBG_STATE) {
7398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                synchronized (stateLock) {
7408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    if (state != STATE_CLOSED) throw new AssertionError("State is: " + state);
7418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                }
7428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
7438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
7448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            synchronized (writeLock) { }
7458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
74608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
74708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
74808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
749f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
750f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public SSLSession getSession() {
751e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom        if (sslSession == null) {
752e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            try {
7538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                waitForHandshake();
754e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            } catch (IOException e) {
755e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // return an invalid session with
756e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom                // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL"
757f111f6235d016ce54ab95a2c634a400efe29f24bKenny Root                return SSLNullSession.getNullSession();
758e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom            }
75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslSession;
76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
763d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    @Override
764f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void addHandshakeCompletedListener(
76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
76608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
7705006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson            listeners = new ArrayList<HandshakeCompletedListener>();
77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        listeners.add(listener);
77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
775f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
776f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void removeHandshakeCompletedListener(
77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            HandshakeCompletedListener listener) {
77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listener == null) {
77908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException("Provided listener is null");
78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (listeners == null) {
78208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
78308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
78408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
78508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        if (!listeners.remove(listener)) {
78608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            throw new IllegalArgumentException(
78708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                    "Provided listener is not registered");
78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
791f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
792f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getEnableSessionCreation() {
79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getEnableSessionCreation();
79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
79508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
796f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
797f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnableSessionCreation(boolean flag) {
79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setEnableSessionCreation(flag);
79908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
80008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
801f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
802f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getSupportedCipherSuites() {
803f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedCipherSuites();
80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
806f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
807f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getEnabledCipherSuites() {
808f878e438660d93f8689b864165230492e7a412d4Kenny Root        return sslParameters.getEnabledCipherSuites();
80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
81008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
811f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
812f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnabledCipherSuites(String[] suites) {
813f878e438660d93f8689b864165230492e7a412d4Kenny Root        sslParameters.setEnabledCipherSuites(suites);
81408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
81508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
816f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
817f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getSupportedProtocols() {
818f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        return NativeCrypto.getSupportedProtocols();
81908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
82008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
821f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
822f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public String[] getEnabledProtocols() {
823ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin        return sslParameters.getEnabledProtocols();
82408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
82508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
826f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
827f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setEnabledProtocols(String[] protocols) {
828ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin        sslParameters.setEnabledProtocols(protocols);
82908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
83008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
83108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    /**
8320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables session ticket support.
8330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
8340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param useSessionTickets True to enable session tickets
8350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
8360b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setUseSessionTickets(boolean useSessionTickets) {
8373c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.useSessionTickets = useSessionTickets;
8380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
8390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
8400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    /**
8410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * This method enables Server Name Indication
8420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     *
8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     * @param hostname the desired SNI hostname, or null to disable
8440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom     */
8450b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    public void setHostname(String hostname) {
8463c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.setUseSni(hostname != null);
84757ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root        wrappedHost = hostname;
8480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom    }
8490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom
850577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
851577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Enables/disables TLS Channel ID for this server socket.
852577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
853577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * <p>This method needs to be invoked before the handshake starts.
854577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
855577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a client socket or if the handshake has already
856577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         started.
857577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
858577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
859577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    public void setChannelIdEnabled(boolean enabled) {
860577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (getUseClientMode()) {
861577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Client mode");
862577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
8638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
8658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
8668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
8678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not enable/disable Channel ID after the initial handshake has"
8688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                                + " begun.");
8698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
870577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
8713c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.channelIdEnabled = enabled;
872577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
873577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
874577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
875577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Gets the TLS Channel ID for this server socket. Channel ID is only available once the
876577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * handshake completes.
877577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
878577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @return channel ID or {@code null} if not available.
879577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
880577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a client socket or if the handshake has not yet
881577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         completed.
882577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws SSLException if channel ID is available but could not be obtained.
883577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
884577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    public byte[] getChannelId() throws SSLException {
885577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (getUseClientMode()) {
886577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Client mode");
887577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
8888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
8898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
8908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_READY) {
8918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
8928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Channel ID is only available after handshake completes");
8938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
894577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
895577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer);
896577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
897577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
898577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    /**
899577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket.
900577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
901577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * <p>This method needs to be invoked before the handshake starts.
902577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
903577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables
9044022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin     *        TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST
905577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *        P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1).
906577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *
907577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     * @throws IllegalStateException if this is a server socket or if the handshake has already
908577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     *         started.
909577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin     */
9104022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin    public void setChannelIdPrivateKey(PrivateKey privateKey) {
911577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        if (!getUseClientMode()) {
912577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin            throw new IllegalStateException("Server mode");
913577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
9148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
9158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
9168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
9178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalStateException(
9188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not change Channel ID private key after the initial handshake has"
9198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                                + " begun.");
9208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
921577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin        }
9228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
9231ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        if (privateKey == null) {
9243c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.channelIdEnabled = false;
9253c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            channelIdPrivateKey = null;
9261ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        } else {
9273c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            sslParameters.channelIdEnabled = true;
9281ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            try {
9293c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root                channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey);
9301ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            } catch (InvalidKeyException e) {
9311ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                // Will have error in startHandshake
9321ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            }
9331ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        }
934577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin    }
935577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin
936f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
937f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getUseClientMode() {
93808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getUseClientMode();
93908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
94008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
941f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
942f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setUseClientMode(boolean mode) {
9438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
9448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state != STATE_NEW) {
9458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                throw new IllegalArgumentException(
9468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                        "Could not change the mode after the initial handshake has begun.");
9478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
94808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
94908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setUseClientMode(mode);
95008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
95108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
952f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
953f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getWantClientAuth() {
95408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getWantClientAuth();
95508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
95608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
957f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
958f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public boolean getNeedClientAuth() {
95908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        return sslParameters.getNeedClientAuth();
96008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
96108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
962f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
963f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setNeedClientAuth(boolean need) {
96408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setNeedClientAuth(need);
96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
96608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
967f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
968f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setWantClientAuth(boolean want) {
96908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        sslParameters.setWantClientAuth(want);
97008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
97108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
972f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
973f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void sendUrgentData(int data) throws IOException {
9745006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        throw new SocketException("Method sendUrgentData() is not supported.");
97508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
97608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
977f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
978f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setOOBInline(boolean on) throws SocketException {
9795006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        throw new SocketException("Methods sendUrgentData, setOOBInline are not supported.");
98008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
98108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
982f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
983f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException {
984fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        super.setSoTimeout(readTimeoutMilliseconds);
985fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.readTimeoutMilliseconds = readTimeoutMilliseconds;
98672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom    }
98772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom
988f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
989f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public int getSoTimeout() throws SocketException {
990fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        return readTimeoutMilliseconds;
991fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    }
992fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
993fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    /**
994fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     * Note write timeouts are not part of the javax.net.ssl.SSLSocket API
995fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     */
996fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException {
997fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.writeTimeoutMilliseconds = writeTimeoutMilliseconds;
998fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
9993e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root        Platform.setSocketTimeout(this, writeTimeoutMilliseconds);
1000fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    }
1001fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom
1002fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    /**
1003fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     * Note write timeouts are not part of the javax.net.ssl.SSLSocket API
1004fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom     */
1005fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public int getSoWriteTimeout() throws SocketException {
1006fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        return writeTimeoutMilliseconds;
100708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
100808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1009331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    /**
1010331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * Set the handshake timeout on this socket.  This timeout is specified in
1011331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     * milliseconds and will be used only during the handshake process.
1012331900211d05cd282141a3a50cb1db626f418b2cDan Egnor     */
1013fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom    public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException {
1014fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom        this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds;
1015331900211d05cd282141a3a50cb1db626f418b2cDan Egnor    }
1016331900211d05cd282141a3a50cb1db626f418b2cDan Egnor
1017f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1018f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    public void close() throws IOException {
10195006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson        // TODO: Close SSL sockets using a background thread so they close gracefully.
102008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
10218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLInputStream sslInputStream = null;
10228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        SSLOutputStream sslOutputStream = null;
1023f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
10248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        synchronized (stateLock) {
10258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (state == STATE_CLOSED) {
10268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // close() has already been called, so do nothing and return.
10278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
10288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
102908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
10308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            int oldState = state;
10318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            state = STATE_CLOSED;
10328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (oldState == STATE_NEW) {
10348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // The handshake hasn't been started yet, so there's no OpenSSL related
10358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // state to clean up. We still need to close the underlying socket if
10368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // we're wrapping it and were asked to autoClose.
10378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                closeUnderlyingSocket();
1038f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom
10398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                stateLock.notifyAll();
104008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project                return;
104108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
104208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
10438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) {
10448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // If we're in these states, we still haven't returned from startHandshake.
10458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then
10468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // set the state to STATE_CLOSED. startHandshake will handle all cleanup
10478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                // after SSL_do_handshake returns, so we don't have anything to do here.
10488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                NativeCrypto.SSL_interrupt(sslNativePointer);
104908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
10508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                stateLock.notifyAll();
10518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                return;
10528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
10538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            stateLock.notifyAll();
10558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // We've already returned from startHandshake, so we potentially have
10568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            // input and output streams to clean up.
10578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslInputStream = is;
10588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslOutputStream = os;
10598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
10608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Don't bother interrupting unless we have something to interrupt.
10628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslInputStream != null || sslOutputStream != null) {
1063fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom            NativeCrypto.SSL_interrupt(sslNativePointer);
10648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
10658b352156f879e7b36d223d3f65b8de46b7dc4dcfBrian Carlstrom
10668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // Wait for the input and output streams to finish any reads they have in
10678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // progress. If there are no reads in progress at this point, future reads will
10688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        // throw because state == STATE_CLOSED
10698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslInputStream != null) {
10708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslInputStream.awaitPendingOps();
10718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
10728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (sslOutputStream != null) {
10738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            sslOutputStream.awaitPendingOps();
10748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
10758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        shutdownAndFreeSslNative();
10778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
10788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void shutdownAndFreeSslNative() throws IOException {
10808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        try {
10818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            BlockGuard.getThreadPolicy().onNetwork();
10823e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            NativeCrypto.SSL_shutdown(sslNativePointer, Platform.getFileDescriptor(socket),
10838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                    this);
10848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } catch (IOException ignored) {
10858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            /*
10868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * Note that although close() can throw
10878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * IOException, the RI does not throw if there
10888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * is problem sending a "close notify" which
10898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            * can happen if the underlying socket is closed.
10908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            */
10918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } finally {
10928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            free();
10938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            closeUnderlyingSocket();
10948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        }
10958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    }
10968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath
10978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath    private void closeUnderlyingSocket() throws IOException {
10988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        if (socket != this) {
10998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (autoClose && !socket.isClosed()) {
11008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                socket.close();
11018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            }
11028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath        } else {
11038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath            if (!super.isClosed()) {
11048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath                super.close();
110508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project            }
110608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project        }
110708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
110808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1109f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    private void free() {
1110f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        if (sslNativePointer == 0) {
1111f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom            return;
1112f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        }
1113f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        NativeCrypto.SSL_free(sslNativePointer);
1114f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom        sslNativePointer = 0;
1115fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom        guard.close();
1116f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom    }
111708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project
1118f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    @Override
1119f06338c01394610174fe2b3532beac56d61d9e26Kenny Root    protected void finalize() throws Throwable {
11201990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        try {
11211990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            /*
11221990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * Just worry about our own state. Notably we do not try and
11231990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * close anything. The SocketImpl, either our own
11241990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * PlainSocketImpl, or the Socket we are wrapping, will do
11251990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * that. This might mean we do not properly SSL_shutdown, but
11261990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * if you want to do that, properly close the socket yourself.
11271990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             *
11281990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * The reason why we don't try to SSL_shutdown, is that there
11291990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * can be a race between finalizers where the PlainSocketImpl
11301990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * finalizer runs first and closes the socket. However, in the
11311990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * meanwhile, the underlying file descriptor could be reused
11321990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * for another purpose. If we call SSL_shutdown, the
11331990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * underlying socket BIOs still have the old file descriptor
11341990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * and will write the close notify to some unsuspecting
11351990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             * reader.
11361990574e420184f3ad43400171f624dad44700d8Brian Carlstrom             */
1137f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom            if (guard != null) {
1138f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom                guard.warnIfOpen();
1139f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom            }
11401990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            free();
11411990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        } finally {
11421990574e420184f3ad43400171f624dad44700d8Brian Carlstrom            super.finalize();
11431990574e420184f3ad43400171f624dad44700d8Brian Carlstrom        }
114408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project    }
11450648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey
11463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root    /* @Override */
11470648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey    public FileDescriptor getFileDescriptor$() {
11480648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        if (socket == this) {
11493e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return Platform.getFileDescriptorFromSSLSocket(this);
11500648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        } else {
11513e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root            return Platform.getFileDescriptor(socket);
11520648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey        }
11530648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey    }
1154721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson
1155721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    /**
1156721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * Returns the protocol agreed upon by client and server, or null if no
1157721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * protocol was agreed upon.
1158721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     */
1159721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    public byte[] getNpnSelectedProtocol() {
1160263808a68e1538db41196065830107991e9f974aJesse Wilson        return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer);
1161721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    }
1162721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson
1163721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    /**
11646fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * Returns the protocol agreed upon by client and server, or {@code null} if
11656fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * no protocol was agreed upon.
11666fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     */
11676fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public byte[] getAlpnSelectedProtocol() {
11686fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer);
11696fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    }
11706fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
11716fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    /**
1172721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * Sets the list of protocols this peer is interested in. If null no
1173721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     * protocols will be used.
1174721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     *
1175d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     * @param npnProtocols a non-empty array of protocol names. From
1176d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     SSL_select_next_proto, "vector of 8-bit, length prefixed byte
1177d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     strings. The length byte itself is not included in the length. A byte
1178d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson     *     string of length 0 is invalid. No byte string may be truncated.".
1179721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson     */
1180721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    public void setNpnProtocols(byte[] npnProtocols) {
1181d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson        if (npnProtocols != null && npnProtocols.length == 0) {
1182d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson            throw new IllegalArgumentException("npnProtocols.length == 0");
1183d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson        }
11843c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.npnProtocols = npnProtocols;
1185721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson    }
11866fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
11876fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    /**
11886fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * Sets the list of protocols this peer is interested in. If the list is
11896fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * {@code null}, no protocols will be used.
11906fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *
11916fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     * @param alpnProtocols a non-empty array of protocol names. From
11926fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            SSL_select_next_proto, "vector of 8-bit, length prefixed byte
11936fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            strings. The length byte itself is not included in the length.
11946fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            A byte string of length 0 is invalid. No byte string may be
11956fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     *            truncated.".
11966fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root     */
11976fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public void setAlpnProtocols(byte[] alpnProtocols) {
11986fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        if (alpnProtocols != null && alpnProtocols.length == 0) {
11996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            throw new IllegalArgumentException("alpnProtocols.length == 0");
12006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        }
12013c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        sslParameters.alpnProtocols = alpnProtocols;
12022d089e18deae231149737cad6ce00f1e137a7199Alex Klyubin    }
1203d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root
1204d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root    @Override
12053c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    public String chooseServerAlias(X509KeyManager keyManager, String keyType) {
12063c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        return keyManager.chooseServerAlias(keyType, null, this);
12073c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    }
12083c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root
12093c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    @Override
12103c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers,
12113c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root            String[] keyTypes) {
12123c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root        return keyManager.chooseClientAlias(keyTypes, null, this);
12133c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root    }
121401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
121501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
121601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) {
121701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.chooseServerKeyIdentityHint(this);
121801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
121901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
122001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
122101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) {
122201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.chooseClientKeyIdentity(identityHint, this);
122301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
122401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
122501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    @Override
122601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) {
122701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        return keyManager.getKey(identityHint, identity, this);
122801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
122908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project}
1230