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