OpenSSLSocketImpl.java revision 0dd7db8b85dfd8ad5d16d239432b9852450dc78f
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 19ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard; 20fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard; 210648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkeyimport java.io.FileDescriptor; 2208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException; 2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream; 2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream; 2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress; 2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket; 2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException; 281ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Rootimport java.security.InvalidKeyException; 2998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey; 3098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom; 311f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException; 3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException; 3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList; 3497e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughesimport java.util.Arrays; 3508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 38edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 39d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLParameters; 408765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException; 4108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 42d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.X509ExtendedTrustManager; 438d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubinimport javax.net.ssl.X509KeyManager; 44fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 46fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.ErrnoException; 47fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.Libcore; 485c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstromimport libcore.io.Streams; 49fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.StructTimeval; 5008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 518db22531f59b33539647ab95bb76354212d3866aNarayan Kamathimport static libcore.io.OsConstants.SOL_SOCKET; 528db22531f59b33539647ab95bb76354212d3866aNarayan Kamathimport static libcore.io.OsConstants.SO_SNDTIMEO; 538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 620b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 6308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 64f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 65f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 663c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser { 6790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final boolean DBG_STATE = false; 698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 7169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom * Protects handshakeStarted and handshakeCompleted. 7269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object stateLock = new Object(); 7469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 7569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * The {@link OpenSSLSocketImpl} object is constructed, but {@link #startHandshake()} 778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * has not yet been called. 7869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_NEW = 0; 8069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 8169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has been called at least once. 8369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_HANDSHAKE_STARTED = 1; 8569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 8669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #handshakeCompleted()} has been called, but {@link #startHandshake()} hasn't 888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * returned yet. 8969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_HANDSHAKE_COMPLETED = 2; 918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has completed but {@link #handshakeCompleted()} hasn't 948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake 958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * returns before the handshake is complete. We can now start writing data to the socket. 968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 3; 9869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 9969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has completed and {@link #handshakeCompleted()} has been 1018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * called. 10269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_READY = 4; 10469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 10569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #close()} has been called at least once. 10769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_CLOSED = 5; 1098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 1108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private int state = STATE_NEW; 11269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 11369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as 0, set by 1158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * startHandshake, reset to 0 on close. 11669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private long sslNativePointer; 11969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 12069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as null, set by 1228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * getInputStream. 12369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private SSLInputStream is; 1268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 1278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 1288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as null, set by 1298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * getInputStream. 1308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 1318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private SSLOutputStream os; 13369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 13469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final Socket socket; 13569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final boolean autoClose; 13657ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root private String wrappedHost; 13769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final int wrappedPort; 13869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final SSLParametersImpl sslParameters; 13969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 14069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 1413c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root private ArrayList<HandshakeCompletedListener> listeners; 1422828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 1432828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 1443c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root * Private key for the TLS Channel ID extension. This field is client-side 1453c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root * only. Set during startHandshake. 1462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 1473c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root OpenSSLKey channelIdPrivateKey; 14869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 14969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** Set during startHandshake. */ 15069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private OpenSSLSessionImpl sslSession; 1512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 152d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root /** Used during handshake callbacks. */ 153d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root private OpenSSLSessionImpl handshakeSession; 154d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 15572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom /** 15672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 15772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * write for non-wrapped sockets. Note that 15872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 15972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 16072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom */ 161fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int readTimeoutMilliseconds = 0; 162fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int writeTimeoutMilliseconds = 0; 16372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 16472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 16508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 166cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 16790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 16869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 16969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 17069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 17169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 17208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 17308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 174cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 1752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1765ea53c028b903ce252e08c1b67508ce8dafcff34Brian Carlstrom String[] enabledCipherSuites) throws IOException { 17790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 17869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 17969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 18069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 18169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 1823c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root this.sslParameters.openSslEnabledProtocols = enabledProtocols; 1833c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root this.sslParameters.openSslEnabledCipherSuites = enabledCipherSuites; 1842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 1852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 186cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 18790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port); 18990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 19069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 19169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 19269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 19369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 196cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 19790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port); 19990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 20069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 20169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 20269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 20369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 20408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 20508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 20608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 207c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, 208c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 2095006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 21008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port, clientAddress, clientPort); 21190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 21269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 21369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 21469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 21569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 21608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 21708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 21808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 219c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 2205006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 22108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port, clientAddress, clientPort); 22290ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 22369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 22469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 22569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 22669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 22708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 22808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 22908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 2305006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Create an SSL socket that wraps another socket. Invoked by 2315006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * OpenSSLSocketImplWrapper constructor. 23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 234cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.socket = socket; 2366e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedHost = host; 2376e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedPort = port; 23808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.autoClose = autoClose; 23969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 24072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 24172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // this.timeout is not set intentionally. 24272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 24372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // to wrapped socket 244f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 245f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 246a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom private void checkOpen() throws SocketException { 247a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom if (isClosed()) { 248a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom throw new SocketException("Socket is closed"); 249a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 250a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 251a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom 252a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom /** 253d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 254d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 255d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 256d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * verified if the correspondent property in java.Security is set. All 257d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 2582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 259f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 260f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void startHandshake() throws IOException { 2618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 2628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 2638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_NEW) { 2648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_HANDSHAKE_STARTED; 26508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 2668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've either started the handshake already or have been closed. 2678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Do nothing in both cases. 26808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 26908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 27008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 27108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 27298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 27398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 27498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 27598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (secureRandom == null) { 27698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 27798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } else { 27898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 27998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 28098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 28198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 28298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslNativePointer = 0; 2848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath boolean releaseResources = true; 285fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 2863c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final AbstractSessionContext sessionContext = sslParameters.getSessionContext(); 2873c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final long sslCtxNativePointer = sessionContext.sslCtxNativePointer; 288fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 289fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.open("close"); 29098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2913c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root boolean enableSessionCreation = getEnableSessionCreation(); 292fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 293fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 2943c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root enableSessionCreation); 2952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 2962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 2973c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final OpenSSLSessionImpl sessionToReuse = sslParameters.getSessionToReuse( 2983c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslNativePointer, getPeerHostName(), getPeerPort()); 2993c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, 3003c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root getPeerHostName()); 3013c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setCertificateValidation(sslNativePointer); 3023c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey); 303f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 304fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 305fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 306fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 307fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 308fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 309fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 310fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 3128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 3148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 3158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3187dd8d0b433cf8212538aaaf8726f5222abf035ddMatteo Franchin long sslSessionNativePointer; 319fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 320a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 3213c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root socket.getFileDescriptor$(), this, getSoTimeout(), client, 3223c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.npnProtocols, client ? null : sslParameters.alpnProtocols); 323fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 324d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 325d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 326d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 3278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (SSLException e) { 3288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Swallow this exception if it's thrown as the result of an interruption. 3298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // 3308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake 3318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ 3328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // (or WANT_WRITE). Catching that exception here doesn't seem much worse than 3338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // changing the native code to return a "special" native pointer value when that 3348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // happens. 3358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 3378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 3388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw e; 3422828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath boolean handshakeCompleted = false; 3458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_COMPLETED) { 3478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath handshakeCompleted = true; 3488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_CLOSED) { 3498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 3508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3530dd7db8b85dfd8ad5d16d239432b9852450dc78fKenny Root sslSession = sslParameters.setupSession(sslSessionNativePointer, sslNativePointer, 3543c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sessionToReuse, getPeerHostName(), getPeerPort(), handshakeCompleted); 355fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 357fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 358fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 359fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 360331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 36108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 362fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 363fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 364fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 365fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 366f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 3678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath releaseResources = (state == STATE_CLOSED); 3698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_STARTED) { 3718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY_HANDSHAKE_CUT_THROUGH; 3728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_HANDSHAKE_COMPLETED) { 3738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY; 3748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (!releaseResources) { 3778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Unblock threads that are waiting for our state to transition 3788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH. 3798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 3808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3828765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } catch (SSLProtocolException e) { 3838765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom throw new SSLHandshakeException(e); 384fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 385aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 3868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (releaseResources) { 3878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Mark the socket as closed since we might have reached this as 3898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // a result on an exception thrown by the handshake process. 3908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // 3918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // The state will already be set to closed if we reach this as a result of 3928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // an early return or an interruption due to a concurrent call to close(). 3938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_CLOSED; 3948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 3958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 3988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath shutdownAndFreeSslNative(); 3998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (IOException ignored) { 4008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 402fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 40308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 404e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 4053ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root 406bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra String getPeerHostName() { 4078ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (wrappedHost != null) { 4088ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return wrappedHost; 4098ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4108ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom InetAddress inetAddress = super.getInetAddress(); 4118ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (inetAddress != null) { 4128ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return inetAddress.getHostName(); 4138ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4148ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return null; 4153967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4163967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 417bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra int getPeerPort() { 4183967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 4193967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4203967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 421f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 4225006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 42398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 424f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 4253c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals, 4263c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslNativePointer, this); 42798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 42898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 429f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 4305006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 431f878e438660d93f8689b864165230492e7a412d4Kenny Root public void onSSLStateChange(long sslSessionNativePtr, int type, int val) { 432f878e438660d93f8689b864165230492e7a412d4Kenny Root if (type != NativeCrypto.SSL_CB_HANDSHAKE_DONE) { 433f878e438660d93f8689b864165230492e7a412d4Kenny Root return; 434f878e438660d93f8689b864165230492e7a412d4Kenny Root } 435f878e438660d93f8689b864165230492e7a412d4Kenny Root 4368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 4378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_STARTED) { 4388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // If sslSession is null, the handshake was completed during 4398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // the call to NativeCrypto.SSL_do_handshake and not during a 4408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // later read operation. That means we do not need to fix up 4418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // the SSLSession and session cache or notify 4428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // HandshakeCompletedListeners, it will be done in 4438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // startHandshake. 4448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_HANDSHAKE_COMPLETED; 4468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 4478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 4488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've returned from startHandshake, which means we've set a sslSession etc. 4498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we need to fix them up, which we'll do outside this lock. 4508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_CLOSED) { 4518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Someone called "close" but the handshake hasn't been interrupted yet. 4528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 4538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 4542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 45508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 4572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 4582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 4592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 4602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 4612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 4622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 46308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 4642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 4652828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 4662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 4678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 4698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Now that we've fixed up our state, we can tell waiting threads that 4708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we're ready. 4718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY; 4728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Notify all threads waiting for the handshake to complete. 4738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 4748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 4752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 4772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 4782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 4792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 4802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 4812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 4822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 4832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 4842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 4852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 486371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 487371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 488371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 489371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 490371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 491371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 492371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 4932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 49608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 49708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4985006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 499f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 500d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, String authMethod) 50198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 50208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 5038d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin X509TrustManager x509tm = sslParameters.getX509TrustManager(); 5048d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin if (x509tm == null) { 5058d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin throw new CertificateException("No X.509 TrustManager"); 5068d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin } 5070e9746b7b132058651155b33f219c7789997985bKenny Root if (certRefs == null || certRefs.length == 0) { 508371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 509371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 5100e9746b7b132058651155b33f219c7789997985bKenny Root OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length]; 5110e9746b7b132058651155b33f219c7789997985bKenny Root for (int i = 0; i < certRefs.length; i++) { 5120e9746b7b132058651155b33f219c7789997985bKenny Root peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]); 51308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 514d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 515d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root // Used for verifyCertificateChain callback 516d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain, 517d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root getPeerHostName(), getPeerPort(), null); 518d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 5192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 5202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 521d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root if (x509tm instanceof X509ExtendedTrustManager) { 522d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) x509tm; 523d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root x509etm.checkServerTrusted(peerCertChain, authMethod, this); 524bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra } else { 5250e9746b7b132058651155b33f219c7789997985bKenny Root x509tm.checkServerTrusted(peerCertChain, authMethod); 526bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra } 5272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 5280e9746b7b132058651155b33f219c7789997985bKenny Root String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 529d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root if (x509tm instanceof X509ExtendedTrustManager) { 530d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root X509ExtendedTrustManager x509etm = (X509ExtendedTrustManager) x509tm; 531d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root x509etm.checkClientTrusted(peerCertChain, authType, this); 532d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } else { 533d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root x509tm.checkClientTrusted(peerCertChain, authType); 534d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } 53508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 5372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 5382828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 5399400b50da5ca8f1e796f5b158063db0aefb58441Brian Carlstrom throw new CertificateException(e); 540d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } finally { 541d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root // Clear this before notifying handshake completed listeners 542d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root handshakeSession = null; 54308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 54408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 54508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 546f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 547f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public InputStream getInputStream() throws IOException { 548a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 5498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath InputStream returnVal; 5518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 5528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 5538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed."); 5548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 55608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 55708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 55808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 55908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath returnVal = is; 56108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Block waiting for a handshake without a lock held. It's possible that the socket 5648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // is closed at this point. If that happens, we'll still return the input stream but 5658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // all reads on it will throw. 5668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 5678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return returnVal; 56808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 56908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 570f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 571f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public OutputStream getOutputStream() throws IOException { 572a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 5738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath OutputStream returnVal; 5758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 5768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 5778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed."); 5788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 58008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 58108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 58208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 58308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath returnVal = os; 5858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Block waiting for a handshake without a lock held. It's possible that the socket 5888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // is closed at this point. If that happens, we'll still return the output stream but 5898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // all writes on it will throw. 5908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 5918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return returnVal; 5928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void assertReadableOrWriteableState() { 5958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 5968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 5978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new AssertionError("Invalid state: " + state); 6008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void waitForHandshake() throws IOException { 6048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath startHandshake(); 6058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath while (state != STATE_READY && 6088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state != STATE_READY_HANDSHAKE_CUT_THROUGH && 6098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state != STATE_CLOSED) { 6108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 6118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.wait(); 6128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (InterruptedException e) { 6138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Thread.currentThread().interrupt(); 6148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath IOException ioe = new IOException("Interrupted waiting for handshake"); 6158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath ioe.initCause(e); 6168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw ioe; 6188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 6228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed"); 6238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 62408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 62808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 62908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 63008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 63108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 63208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 6338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 6348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * OpenSSL only lets one thread read at a time, so this is used to 6358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * make sure we serialize callers of SSL_read. Thread is already 6368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * expected to have completed handshaking. 6378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 6388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object readLock = new Object(); 6398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLInputStream() { 64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 64608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 6480e9746b7b132058651155b33f219c7789997985bKenny Root * @throws IOException 64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 6525c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom return Streams.readSingleByte(this); 65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 65508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 65608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 66097e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 661ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 6628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 6648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 6658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (byteCount == 0) { 6668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return 0; 6678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 669f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 6728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("socket is closed"); 6738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) assertReadableOrWriteableState(); 6767b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 6778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 678a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 679a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 68108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath public void awaitPendingOps() { 6848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) { 6858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 6878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (readLock) { } 6918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 69208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 7008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 7028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * OpenSSL only lets one thread write at a time, so this is used 7038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * to make sure we serialize callers of SSL_write. Thread is 7048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * already expected to have completed handshaking. 7058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 7068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object writeLock = new Object(); 7078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLOutputStream() { 70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 71108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 71308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(int) 71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 7165c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom public void write(int oneByte) throws IOException { 7175c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom Streams.writeSingleByte(this, oneByte); 71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 72108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 72208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 72308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 72597e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 726ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 7278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 7288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 7298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (byteCount == 0) { 7308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 7318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 733f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 7358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 7368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("socket is closed"); 7378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) assertReadableOrWriteableState(); 7407b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 7418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 742a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 743fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 74408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 7468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath public void awaitPendingOps() { 7498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) { 7508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 7518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 7528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (writeLock) { } 7568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 760f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 761f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public SSLSession getSession() { 762e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 763e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 7648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 765e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 766e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 767e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 768f111f6235d016ce54ab95a2c634a400efe29f24bKenny Root return SSLNullSession.getNullSession(); 769e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 774f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 775d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root public SSLSession getHandshakeSession() { 776d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root return handshakeSession; 777d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } 778d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 779d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root @Override 780f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void addHandshakeCompletedListener( 78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 78208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 78308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 78408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 7865006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 78708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 791f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 792f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void removeHandshakeCompletedListener( 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 79508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 79608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 79908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 80008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!listeners.remove(listener)) { 80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 80308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 807f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 808f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getEnableSessionCreation() { 80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 81008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 812f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 813f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnableSessionCreation(boolean flag) { 81408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 81508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 817f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 818f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getSupportedCipherSuites() { 819f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 82008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 82108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 822f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 823f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getEnabledCipherSuites() { 824f878e438660d93f8689b864165230492e7a412d4Kenny Root return sslParameters.getEnabledCipherSuites(); 82508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 82608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 827f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 828f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnabledCipherSuites(String[] suites) { 829f878e438660d93f8689b864165230492e7a412d4Kenny Root sslParameters.setEnabledCipherSuites(suites); 83008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 832f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 833f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getSupportedProtocols() { 834f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 83508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 837f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 838f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getEnabledProtocols() { 8393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root return sslParameters.openSslEnabledProtocols.clone(); 84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 84108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 842f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 843f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnabledProtocols(String[] protocols) { 8443c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.openSslEnabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 84508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 84608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 84708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 8480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 8490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 8510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8533c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.useSessionTickets = useSessionTickets; 8540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 8580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 8623c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setUseSni(hostname != null); 86357ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root wrappedHost = hostname; 8640b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 866577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 867577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Enables/disables TLS Channel ID for this server socket. 868577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 869577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 870577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 871577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has already 872577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 873577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 874577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 875577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public void setChannelIdEnabled(boolean enabled) { 876577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 877577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 878577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 8808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 8818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 8828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 8838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not enable/disable Channel ID after the initial handshake has" 8848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath + " begun."); 8858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 886577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8873c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = enabled; 888577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 889577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 890577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 891577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 892577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * handshake completes. 893577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 894577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @return channel ID or {@code null} if not available. 895577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 896577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has not yet 897577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * completed. 898577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws SSLException if channel ID is available but could not be obtained. 899577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 900577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public byte[] getChannelId() throws SSLException { 901577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 902577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 903577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 9048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 9058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 9068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_READY) { 9078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 9088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Channel ID is only available after handshake completes"); 9098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 910577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 911577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 912577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 913577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 914577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 915577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 916577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 917577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 918577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 919577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 9204022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 921577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 922577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 923577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a server socket or if the handshake has already 924577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 925577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 9264022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin public void setChannelIdPrivateKey(PrivateKey privateKey) { 927577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (!getUseClientMode()) { 928577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Server mode"); 929577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 9308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 9318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 9328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 9338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 9348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not change Channel ID private key after the initial handshake has" 9358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath + " begun."); 9368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 937577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 9388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 9391ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (privateKey == null) { 9403c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = false; 9413c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root channelIdPrivateKey = null; 9421ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } else { 9433c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = true; 9441ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root try { 9453c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey); 9461ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } catch (InvalidKeyException e) { 9471ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root // Will have error in startHandshake 9481ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 9491ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 950577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 951577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 952f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 953f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getUseClientMode() { 95408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 95508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 957f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 958f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setUseClientMode(boolean mode) { 9598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 9608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 9618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalArgumentException( 9628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not change the mode after the initial handshake has begun."); 9638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 96408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 96608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 968f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 969f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getWantClientAuth() { 97008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 97108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 973f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 974f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getNeedClientAuth() { 97508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 97608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 978f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 979f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setNeedClientAuth(boolean need) { 98008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 98108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 98208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 983f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 984f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setWantClientAuth(boolean want) { 98508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 98608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 98708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 988f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 989f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void sendUrgentData(int data) throws IOException { 9905006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 99108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 993f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 994f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setOOBInline(boolean on) throws SocketException { 9955006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 99608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 998f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 999f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 1000fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 1001fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 100272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 100372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 1004f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 1005f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public int getSoTimeout() throws SocketException { 1006fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return readTimeoutMilliseconds; 1007fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 1008fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 1009fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 1010fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1011fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 1012fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 1013fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 1014fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 1015fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom StructTimeval tv = StructTimeval.fromMillis(writeTimeoutMilliseconds); 1016fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom try { 1017fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom Libcore.os.setsockoptTimeval(getFileDescriptor$(), SOL_SOCKET, SO_SNDTIMEO, tv); 1018fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } catch (ErrnoException errnoException) { 1019fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom throw errnoException.rethrowAsSocketException(); 1020fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 1021fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 1022fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 1023fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 1024fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1025fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 1026fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 1027fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return writeTimeoutMilliseconds; 102808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 102908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1030331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 1031331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 1032331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 1033331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 1034fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 1035fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 1036331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 1037331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 1038f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 1039f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void close() throws IOException { 10405006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 104108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLInputStream sslInputStream = null; 10438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLOutputStream sslOutputStream = null; 1044f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 10458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 10468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 10478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // close() has already been called, so do nothing and return. 10488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 10498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 105008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath int oldState = state; 10528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_CLOSED; 10538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (oldState == STATE_NEW) { 10558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // The handshake hasn't been started yet, so there's no OpenSSL related 10568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // state to clean up. We still need to close the underlying socket if 10578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we're wrapping it and were asked to autoClose. 10588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath closeUnderlyingSocket(); 1059f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 10608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 106108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 106208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 106308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) { 10658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // If we're in these states, we still haven't returned from startHandshake. 10668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then 10678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // set the state to STATE_CLOSED. startHandshake will handle all cleanup 10688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // after SSL_do_handshake returns, so we don't have anything to do here. 10698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath NativeCrypto.SSL_interrupt(sslNativePointer); 107008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 10728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 10738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 10768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've already returned from startHandshake, so we potentially have 10778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // input and output streams to clean up. 10788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslInputStream = is; 10798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslOutputStream = os; 10808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Don't bother interrupting unless we have something to interrupt. 10838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslInputStream != null || sslOutputStream != null) { 1084fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 10858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10868b352156f879e7b36d223d3f65b8de46b7dc4dcfBrian Carlstrom 10878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Wait for the input and output streams to finish any reads they have in 10888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // progress. If there are no reads in progress at this point, future reads will 10898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // throw because state == STATE_CLOSED 10908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslInputStream != null) { 10918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslInputStream.awaitPendingOps(); 10928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslOutputStream != null) { 10948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslOutputStream.awaitPendingOps(); 10958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath shutdownAndFreeSslNative(); 10988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 11008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void shutdownAndFreeSslNative() throws IOException { 11018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 11028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath BlockGuard.getThreadPolicy().onNetwork(); 11038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 11048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath this); 11058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (IOException ignored) { 11068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /* 11078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Note that although close() can throw 11088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * IOException, the RI does not throw if there 11098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * is problem sending a "close notify" which 11108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * can happen if the underlying socket is closed. 11118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 11128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } finally { 11138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath free(); 11148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath closeUnderlyingSocket(); 11158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 11188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void closeUnderlyingSocket() throws IOException { 11198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (socket != this) { 11208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (autoClose && !socket.isClosed()) { 11218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath socket.close(); 11228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else { 11248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (!super.isClosed()) { 11258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath super.close(); 112608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 112708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 112808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 112908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1130f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 1131f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 1132f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 1133f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 1134f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1135f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 1136fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 1137f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 113808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1139f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 1140f06338c01394610174fe2b3532beac56d61d9e26Kenny Root protected void finalize() throws Throwable { 11411990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 11421990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 11431990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 11441990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 11451990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 11461990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 11471990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 11481990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 11491990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 11501990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 11511990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 11521990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 11531990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 11541990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 11551990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 11561990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 11571990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 1158f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 1159f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 1160f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 11611990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 11621990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 11631990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 11641990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 116508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 11660648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey 11670648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey @Override 11680648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 11690648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey if (socket == this) { 11700648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return super.getFileDescriptor$(); 11710648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } else { 11720648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return socket.getFileDescriptor$(); 11730648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 11740648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 1175721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1176721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 1177721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Returns the protocol agreed upon by client and server, or null if no 1178721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocol was agreed upon. 1179721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1180721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public byte[] getNpnSelectedProtocol() { 1181263808a68e1538db41196065830107991e9f974aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 1182721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 1183721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1184721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 11856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Returns the protocol agreed upon by client and server, or {@code null} if 11866fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * no protocol was agreed upon. 11876fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 11886fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public byte[] getAlpnSelectedProtocol() { 11896fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 11906fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 11916fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 11926fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 1193721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Sets the list of protocols this peer is interested in. If null no 1194721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocols will be used. 1195721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * 1196d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 1197d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1198d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * strings. The length byte itself is not included in the length. A byte 1199d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 1200721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1201721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 1202d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 1203d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 1204d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson } 12053c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.npnProtocols = npnProtocols; 1206721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 12076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 12086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 12096fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Sets the list of protocols this peer is interested in. If the list is 12106fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * {@code null}, no protocols will be used. 12116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * 12126fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * @param alpnProtocols a non-empty array of protocol names. From 12136fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 12146fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * strings. The length byte itself is not included in the length. 12156fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * A byte string of length 0 is invalid. No byte string may be 12166fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * truncated.". 12176fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 12186fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public void setAlpnProtocols(byte[] alpnProtocols) { 12196fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root if (alpnProtocols != null && alpnProtocols.length == 0) { 12206fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root throw new IllegalArgumentException("alpnProtocols.length == 0"); 12216fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 12223c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.alpnProtocols = alpnProtocols; 12232d089e18deae231149737cad6ce00f1e137a7199Alex Klyubin } 1224d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 1225d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root @Override 1226d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root public SSLParameters getSSLParameters() { 1227d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root SSLParameters params = super.getSSLParameters(); 1228d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root params.setEndpointIdentificationAlgorithm( 1229d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root sslParameters.getEndpointIdentificationAlgorithm()); 1230d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root return params; 1231d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } 1232d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 1233d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root @Override 1234d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root public void setSSLParameters(SSLParameters p) { 1235d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root super.setSSLParameters(p); 1236d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root sslParameters.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm()); 1237d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } 12383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root 12393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root @Override 12403c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root public String chooseServerAlias(X509KeyManager keyManager, String keyType) { 12413c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root return keyManager.chooseServerAlias(keyType, null, this); 12423c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root } 12433c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root 12443c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root @Override 12453c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 12463c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root String[] keyTypes) { 12473c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root return keyManager.chooseClientAlias(keyTypes, null, this); 12483c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root } 124908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 1250