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