108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/* 208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * you may not use this file except in compliance with the License. 608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * You may obtain a copy of the License at 708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * See the License for the specific language governing permissions and 1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * limitations under the License. 1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 193e46e4ee56c8e37158f46941dedd5b436d724baaKenny Rootimport org.conscrypt.util.Arrays; 20ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard; 21fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard; 220648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkeyimport java.io.FileDescriptor; 2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException; 2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream; 2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream; 2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress; 2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket; 2808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException; 291ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Rootimport java.security.InvalidKeyException; 3098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey; 3198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom; 321f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException; 3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException; 3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList; 3501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubinimport javax.crypto.SecretKey; 3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 39edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 40d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Rootimport javax.net.ssl.SSLParameters; 418765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException; 4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 438d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubinimport javax.net.ssl.X509KeyManager; 44fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 5608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 57f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 58f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 5901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser, 6001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin SSLParametersImpl.PSKCallbacks { 6190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final boolean DBG_STATE = false; 638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 6569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom * Protects handshakeStarted and handshakeCompleted. 6669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object stateLock = new Object(); 6869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 6969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * The {@link OpenSSLSocketImpl} object is constructed, but {@link #startHandshake()} 718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * has not yet been called. 7269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_NEW = 0; 7469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 7569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has been called at least once. 7769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_HANDSHAKE_STARTED = 1; 7969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 8069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #handshakeCompleted()} has been called, but {@link #startHandshake()} hasn't 828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * returned yet. 8369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_HANDSHAKE_COMPLETED = 2; 858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has completed but {@link #handshakeCompleted()} hasn't 888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake 898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * returns before the handshake is complete. We can now start writing data to the socket. 908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 3; 9269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 9369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #startHandshake()} has completed and {@link #handshakeCompleted()} has been 958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * called. 9669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_READY = 4; 9869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 9969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * {@link #close()} has been called at least once. 10169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private static final int STATE_CLOSED = 5; 1038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 1048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private int state = STATE_NEW; 10669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 10769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as 0, set by 1098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * startHandshake, reset to 0 on close. 11069c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private long sslNativePointer; 11369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 11469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** 1158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as null, set by 1168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * getInputStream. 11769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom */ 1188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private SSLInputStream is; 1208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 1218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 1228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Protected by synchronizing on stateLock. Starts as null, set by 1238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * getInputStream. 1248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 1258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // @GuardedBy("stateLock"); 1268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private SSLOutputStream os; 12769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 12869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final Socket socket; 12969c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final boolean autoClose; 13057ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root private String wrappedHost; 13169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final int wrappedPort; 13269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final SSLParametersImpl sslParameters; 13369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 13469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 1353c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root private ArrayList<HandshakeCompletedListener> listeners; 1362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 1372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 1383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root * Private key for the TLS Channel ID extension. This field is client-side 1393c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root * only. Set during startHandshake. 1402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 1413c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root OpenSSLKey channelIdPrivateKey; 14269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom 14369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom /** Set during startHandshake. */ 14469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom private OpenSSLSessionImpl sslSession; 1452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 146d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root /** Used during handshake callbacks. */ 147d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root private OpenSSLSessionImpl handshakeSession; 148d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 14972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom /** 15072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 15172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * write for non-wrapped sockets. Note that 15272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 15372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 15472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom */ 155fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int readTimeoutMilliseconds = 0; 156fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int writeTimeoutMilliseconds = 0; 15772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 15872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 15908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 160cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 16190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 16269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 16369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 16469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 16569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 16608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 16708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 168cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 16990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port); 17190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 17269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 17369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 17469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 17569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 17608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 178cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 17990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port); 18190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 18269c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 18369c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 18469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 18569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 18608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 18708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 189c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, 190c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 1915006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port, clientAddress, clientPort); 19390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 19469c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 19569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 19669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 19769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 19908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 20008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 201c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 2025006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 20308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port, clientAddress, clientPort); 20490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 20569c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedHost = null; 20669c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.wrappedPort = -1; 20769c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.autoClose = false; 20869c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 20908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 21008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 21108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 2125006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Create an SSL socket that wraps another socket. Invoked by 2135006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * OpenSSLSocketImplWrapper constructor. 21408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 21508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 216cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 21708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.socket = socket; 2186e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedHost = host; 2196e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedPort = port; 22008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.autoClose = autoClose; 22169c9293abd67eee175870a81f9ee24d7bd6acb50Brian Carlstrom this.sslParameters = sslParameters; 22272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 22372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // this.timeout is not set intentionally. 22472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 22572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // to wrapped socket 226f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 227f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 228a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom private void checkOpen() throws SocketException { 229a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom if (isClosed()) { 230a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom throw new SocketException("Socket is closed"); 231a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 232a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 233a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom 234a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom /** 235d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 236d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 237d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 238d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * verified if the correspondent property in java.Security is set. All 239d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 2402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 241f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 242f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void startHandshake() throws IOException { 2438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 2448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 2458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_NEW) { 2468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_HANDSHAKE_STARTED; 24708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 2488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've either started the handshake already or have been closed. 2498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Do nothing in both cases. 25008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 25108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 25208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 25308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 25498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 25598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 25698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 25798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (secureRandom == null) { 25898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 25998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } else { 26098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 26198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 26298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 26398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 26498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslNativePointer = 0; 2668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath boolean releaseResources = true; 267fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 2683c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final AbstractSessionContext sessionContext = sslParameters.getSessionContext(); 2693c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final long sslCtxNativePointer = sessionContext.sslCtxNativePointer; 270fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 271fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.open("close"); 27298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2733c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root boolean enableSessionCreation = getEnableSessionCreation(); 274fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 275fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 2763c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root enableSessionCreation); 2772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 2782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 2793c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root final OpenSSLSessionImpl sessionToReuse = sslParameters.getSessionToReuse( 2803c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslNativePointer, getPeerHostName(), getPeerPort()); 28101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this, 2823c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root getPeerHostName()); 2833c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setCertificateValidation(sslNativePointer); 2843c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey); 285f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 286fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 287fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 288fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 289fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 290fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 291fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 292fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 2932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 2948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 2958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 2968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 2978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 2988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 2998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3007dd8d0b433cf8212538aaaf8726f5222abf035ddMatteo Franchin long sslSessionNativePointer; 301fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 302a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 3033e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root Platform.getFileDescriptor(socket), this, getSoTimeout(), client, 3043c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.npnProtocols, client ? null : sslParameters.alpnProtocols); 305fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 306d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 307d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 308d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 3098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (SSLException e) { 3108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Swallow this exception if it's thrown as the result of an interruption. 3118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // 3128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake 3138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ 3148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // (or WANT_WRITE). Catching that exception here doesn't seem much worse than 3158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // changing the native code to return a "special" native pointer value when that 3168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // happens. 3178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3188db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 3198db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 3208db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3218db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3228db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3232e1be9d876e8c5554f91afee914641f323eebd4crich cannings // Write CCS errors to EventLog 3242e1be9d876e8c5554f91afee914641f323eebd4crich cannings String message = e.getMessage(); 3252e1be9d876e8c5554f91afee914641f323eebd4crich cannings // Must match error string of SSL_R_UNEXPECTED_CCS 3262e1be9d876e8c5554f91afee914641f323eebd4crich cannings if (message.contains("unexpected CCS")) { 3272e1be9d876e8c5554f91afee914641f323eebd4crich cannings String logMessage = String.format("ssl_unexpected_ccs: host=%s", 3282e1be9d876e8c5554f91afee914641f323eebd4crich cannings getPeerHostName()); 3292e1be9d876e8c5554f91afee914641f323eebd4crich cannings Platform.logEvent(logMessage); 3302e1be9d876e8c5554f91afee914641f323eebd4crich cannings } 3312e1be9d876e8c5554f91afee914641f323eebd4crich cannings 3328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw e; 3332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath boolean handshakeCompleted = false; 3368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_COMPLETED) { 3388db22531f59b33539647ab95bb76354212d3866aNarayan Kamath handshakeCompleted = true; 3398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_CLOSED) { 3408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 3418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3440dd7db8b85dfd8ad5d16d239432b9852450dc78fKenny Root sslSession = sslParameters.setupSession(sslSessionNativePointer, sslNativePointer, 3453c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sessionToReuse, getPeerHostName(), getPeerPort(), handshakeCompleted); 346fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 347fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 348fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 349fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 350fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 351331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 35208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 353fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 354fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 355fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 357f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 3588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath releaseResources = (state == STATE_CLOSED); 3608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_STARTED) { 3628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY_HANDSHAKE_CUT_THROUGH; 3638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_HANDSHAKE_COMPLETED) { 3648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY; 3658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (!releaseResources) { 3688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Unblock threads that are waiting for our state to transition 3698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH. 3708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 3718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3738765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } catch (SSLProtocolException e) { 3743e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed") 3753e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root .initCause(e); 376fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 377aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 3788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (releaseResources) { 3798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 3808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Mark the socket as closed since we might have reached this as 3818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // a result on an exception thrown by the handshake process. 3828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // 3838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // The state will already be set to closed if we reach this as a result of 3848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // an early return or an interruption due to a concurrent call to close(). 3858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_CLOSED; 3868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 3878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 3888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 3908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath shutdownAndFreeSslNative(); 3918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (IOException ignored) { 3928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 3938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 394fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 39508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 396e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 3973ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root 398bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra String getPeerHostName() { 3998ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (wrappedHost != null) { 4008ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return wrappedHost; 4018ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4028ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom InetAddress inetAddress = super.getInetAddress(); 4038ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (inetAddress != null) { 4048ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return inetAddress.getHostName(); 4058ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4068ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return null; 4073967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4083967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 409bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra int getPeerPort() { 4103967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 4113967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4123967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 413f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 4145006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 41598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 416f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 4173c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals, 4183c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslNativePointer, this); 41998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 42098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 421f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 42201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @SuppressWarnings("unused") // used by native psk_client_callback 42301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) { 42401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this); 42501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin } 42601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin 42701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @Override 42801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @SuppressWarnings("unused") // used by native psk_server_callback 42901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) { 43001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this); 43101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin } 43201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin 43301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @Override 4345006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 435f878e438660d93f8689b864165230492e7a412d4Kenny Root public void onSSLStateChange(long sslSessionNativePtr, int type, int val) { 436f878e438660d93f8689b864165230492e7a412d4Kenny Root if (type != NativeCrypto.SSL_CB_HANDSHAKE_DONE) { 437f878e438660d93f8689b864165230492e7a412d4Kenny Root return; 438f878e438660d93f8689b864165230492e7a412d4Kenny Root } 439f878e438660d93f8689b864165230492e7a412d4Kenny Root 4408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 4418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_HANDSHAKE_STARTED) { 4428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // If sslSession is null, the handshake was completed during 4438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // the call to NativeCrypto.SSL_do_handshake and not during a 4448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // later read operation. That means we do not need to fix up 4458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // the SSLSession and session cache or notify 4468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // HandshakeCompletedListeners, it will be done in 4478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // startHandshake. 4488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_HANDSHAKE_COMPLETED; 4508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 4518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 4528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've returned from startHandshake, which means we've set a sslSession etc. 4538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we need to fix them up, which we'll do outside this lock. 4548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else if (state == STATE_CLOSED) { 4558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Someone called "close" but the handshake hasn't been interrupted yet. 4568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 4578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 4582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 45908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 4612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 4622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 4632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 4642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 4652828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 4662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 46708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 4682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 4692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 4702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 4718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 4728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 4738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Now that we've fixed up our state, we can tell waiting threads that 4748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we're ready. 4758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_READY; 4768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Notify all threads waiting for the handshake to complete. 4778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 4788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 4792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 4812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 4822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 4832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 4842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 4852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 4862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 4872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 4882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 4892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 490371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 491371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 492371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 493371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 494371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 495371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 496371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 4972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4992828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 50008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 50108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5025006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 503f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 504d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, String authMethod) 50598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 50608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 5078d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin X509TrustManager x509tm = sslParameters.getX509TrustManager(); 5088d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin if (x509tm == null) { 5098d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin throw new CertificateException("No X.509 TrustManager"); 5108d63ff1384e46407a7618df2b79b2b455795c396Alex Klyubin } 5110e9746b7b132058651155b33f219c7789997985bKenny Root if (certRefs == null || certRefs.length == 0) { 512371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 513371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 5140e9746b7b132058651155b33f219c7789997985bKenny Root OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length]; 5150e9746b7b132058651155b33f219c7789997985bKenny Root for (int i = 0; i < certRefs.length; i++) { 5160e9746b7b132058651155b33f219c7789997985bKenny Root peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]); 51708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 518d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 519d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root // Used for verifyCertificateChain callback 520d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain, 521d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root getPeerHostName(), getPeerPort(), null); 522d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 5232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 5242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 525b860016f415dfc5655dcee45f70e8871a2e3edfeBrian Carlstrom Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, getPeerHostName()); 5262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 5270e9746b7b132058651155b33f219c7789997985bKenny Root String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 528b860016f415dfc5655dcee45f70e8871a2e3edfeBrian Carlstrom x509tm.checkClientTrusted(peerCertChain, authType); 52908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 5312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 5322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 5339400b50da5ca8f1e796f5b158063db0aefb58441Brian Carlstrom throw new CertificateException(e); 534d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root } finally { 535d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root // Clear this before notifying handshake completed listeners 536d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root handshakeSession = null; 53708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 53808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 53908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 540f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 541f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public InputStream getInputStream() throws IOException { 542a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 5438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath InputStream returnVal; 5458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 5468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 5478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed."); 5488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 55008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 55108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 55208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 55308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath returnVal = is; 55508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Block waiting for a handshake without a lock held. It's possible that the socket 5588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // is closed at this point. If that happens, we'll still return the input stream but 5598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // all reads on it will throw. 5608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 5618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return returnVal; 56208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 56308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 564f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 565f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public OutputStream getOutputStream() throws IOException { 566a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 5678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath OutputStream returnVal; 5698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 5708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 5718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed."); 5728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 57408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 57508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 57608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 57708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath returnVal = os; 5798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Block waiting for a handshake without a lock held. It's possible that the socket 5828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // is closed at this point. If that happens, we'll still return the output stream but 5838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // all writes on it will throw. 5848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 5858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return returnVal; 5868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void assertReadableOrWriteableState() { 5898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 5908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 5918db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new AssertionError("Invalid state: " + state); 5948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 5958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 5978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void waitForHandshake() throws IOException { 5988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath startHandshake(); 5998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath while (state != STATE_READY && 6028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state != STATE_READY_HANDSHAKE_CUT_THROUGH && 6038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state != STATE_CLOSED) { 6048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 6058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.wait(); 6068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (InterruptedException e) { 6078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Thread.currentThread().interrupt(); 6088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath IOException ioe = new IOException("Interrupted waiting for handshake"); 6098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath ioe.initCause(e); 6108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw ioe; 6128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6148db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6158db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 6168db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("Socket is closed"); 6178db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 61808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 61908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 62208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 62308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 62408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 62508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 62608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 6278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 6288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * OpenSSL only lets one thread read at a time, so this is used to 6298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * make sure we serialize callers of SSL_read. Thread is already 6308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * expected to have completed handshaking. 6318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 6328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object readLock = new Object(); 6338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLInputStream() { 63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 63708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 63808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 63908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 64008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 6420e9746b7b132058651155b33f219c7789997985bKenny Root * @throws IOException 64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 6463e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root byte[] buffer = new byte[1]; 6473e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root int result = read(buffer, 0, 1); 6483e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return (result != -1) ? buffer[0] & 0xff : -1; 64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 65208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 65697e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 657ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 6588db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 6608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 6618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (byteCount == 0) { 6628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return 0; 6638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 665f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 6688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("socket is closed"); 6698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) assertReadableOrWriteableState(); 6727b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 6738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6743e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return NativeCrypto.SSL_read(sslNativePointer, Platform.getFileDescriptor(socket), 675a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath public void awaitPendingOps() { 6808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) { 6818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 6828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 6838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 6858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (readLock) { } 6878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 68808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 68908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 69108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 69208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 6968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 6978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /** 6988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * OpenSSL only lets one thread write at a time, so this is used 6998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * to make sure we serialize callers of SSL_write. Thread is 7008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * already expected to have completed handshaking. 7018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 7028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private final Object writeLock = new Object(); 7038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLOutputStream() { 70508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 70608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 70808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(int) 71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 7125c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom public void write(int oneByte) throws IOException { 7133e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root byte[] buffer = new byte[1]; 7143e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root buffer[0] = (byte) (oneByte & 0xff); 7153e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root write(buffer); 71608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 72108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 72397e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 724ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 7258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath checkOpen(); 7268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 7278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (byteCount == 0) { 7288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 7298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 731f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7328db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 7338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 7348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new SocketException("socket is closed"); 7358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) assertReadableOrWriteableState(); 7387b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 7398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7403e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root NativeCrypto.SSL_write(sslNativePointer, Platform.getFileDescriptor(socket), 741fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 74208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 7448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath public void awaitPendingOps() { 7478db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (DBG_STATE) { 7488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 7498db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 7508db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7518db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 7528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 7538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (writeLock) { } 7548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 75508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 758f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 759f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public SSLSession getSession() { 760e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 761e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 7628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath waitForHandshake(); 763e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 764e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 765e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 766f111f6235d016ce54ab95a2c634a400efe29f24bKenny Root return SSLNullSession.getNullSession(); 767e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 772d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root @Override 773f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void addHandshakeCompletedListener( 77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 77508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 7795006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 78208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 784f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 785f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void removeHandshakeCompletedListener( 78608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 78708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 79108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 79208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!listeners.remove(listener)) { 79508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 79608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 800f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 801f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getEnableSessionCreation() { 80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 80308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 805f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 806f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnableSessionCreation(boolean flag) { 80708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 80808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 810f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 811f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getSupportedCipherSuites() { 812f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 81308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 815f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 816f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getEnabledCipherSuites() { 817f878e438660d93f8689b864165230492e7a412d4Kenny Root return sslParameters.getEnabledCipherSuites(); 81808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 820f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 821f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnabledCipherSuites(String[] suites) { 822f878e438660d93f8689b864165230492e7a412d4Kenny Root sslParameters.setEnabledCipherSuites(suites); 82308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 82408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 825f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 826f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getSupportedProtocols() { 827f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 82808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 82908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 830f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 831f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public String[] getEnabledProtocols() { 832ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin return sslParameters.getEnabledProtocols(); 83308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 835f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 836f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setEnabledProtocols(String[] protocols) { 837ae2ecac00779167b0381c48da7c612567d1c646fAlex Klyubin sslParameters.setEnabledProtocols(protocols); 83808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 8410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 8420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 8440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8450b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8463c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.useSessionTickets = useSessionTickets; 8470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 8510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 8553c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.setUseSni(hostname != null); 85657ef6334828dfb4f7f6834ddddf5a0ac61f1a4d0Kenny Root wrappedHost = hostname; 8570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 859577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 860577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Enables/disables TLS Channel ID for this server socket. 861577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 862577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 863577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 864577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has already 865577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 866577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 867577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 868577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public void setChannelIdEnabled(boolean enabled) { 869577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 870577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 871577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8728db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 8738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 8748db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 8758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 8768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not enable/disable Channel ID after the initial handshake has" 8778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath + " begun."); 8788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 879577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8803c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = enabled; 881577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 882577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 883577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 884577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 885577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * handshake completes. 886577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 887577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @return channel ID or {@code null} if not available. 888577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 889577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has not yet 890577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * completed. 891577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws SSLException if channel ID is available but could not be obtained. 892577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 893577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public byte[] getChannelId() throws SSLException { 894577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 895577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 896577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 8988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 8998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_READY) { 9008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 9018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Channel ID is only available after handshake completes"); 9028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 903577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 904577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 905577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 906577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 907577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 908577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 909577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 910577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 911577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 912577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 9134022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 914577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 915577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 916577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a server socket or if the handshake has already 917577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 918577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 9194022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin public void setChannelIdPrivateKey(PrivateKey privateKey) { 920577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (!getUseClientMode()) { 921577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Server mode"); 922577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 9238db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 9248db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 9258db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 9268db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalStateException( 9278db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not change Channel ID private key after the initial handshake has" 9288db22531f59b33539647ab95bb76354212d3866aNarayan Kamath + " begun."); 9298db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 930577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 9318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 9321ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (privateKey == null) { 9333c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = false; 9343c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root channelIdPrivateKey = null; 9351ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } else { 9363c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.channelIdEnabled = true; 9371ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root try { 9383c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey); 9391ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } catch (InvalidKeyException e) { 9401ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root // Will have error in startHandshake 9411ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 9421ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 943577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 944577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 945f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 946f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getUseClientMode() { 94708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 94808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 94908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 950f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 951f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setUseClientMode(boolean mode) { 9528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 9538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state != STATE_NEW) { 9548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath throw new IllegalArgumentException( 9558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath "Could not change the mode after the initial handshake has begun."); 9568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 95708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 95908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 961f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 962f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getWantClientAuth() { 96308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 96408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 966f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 967f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public boolean getNeedClientAuth() { 96808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 96908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 971f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 972f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setNeedClientAuth(boolean need) { 97308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 97408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 976f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 977f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setWantClientAuth(boolean want) { 97808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 97908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 98008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 981f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 982f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void sendUrgentData(int data) throws IOException { 9835006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 98408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 98508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 986f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 987f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setOOBInline(boolean on) throws SocketException { 9885006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 98908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 991f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 992f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 993fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 994fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 99572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 99672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 997f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 998f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public int getSoTimeout() throws SocketException { 999fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return readTimeoutMilliseconds; 1000fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 1001fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 1002fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 1003fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1004fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 1005fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 1006fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 1007fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 10083e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root Platform.setSocketTimeout(this, writeTimeoutMilliseconds); 1009fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 1010fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 1011fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 1012fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1013fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 1014fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 1015fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return writeTimeoutMilliseconds; 101608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 101708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1018331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 1019331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 1020331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 1021331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 1022fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 1023fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 1024331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 1025331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 1026f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 1027f06338c01394610174fe2b3532beac56d61d9e26Kenny Root public void close() throws IOException { 10285006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 102908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10308db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLInputStream sslInputStream = null; 10318db22531f59b33539647ab95bb76354212d3866aNarayan Kamath SSLOutputStream sslOutputStream = null; 1032f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 10338db22531f59b33539647ab95bb76354212d3866aNarayan Kamath synchronized (stateLock) { 10348db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (state == STATE_CLOSED) { 10358db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // close() has already been called, so do nothing and return. 10368db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 10378db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 103808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10398db22531f59b33539647ab95bb76354212d3866aNarayan Kamath int oldState = state; 10408db22531f59b33539647ab95bb76354212d3866aNarayan Kamath state = STATE_CLOSED; 10418db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10428db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (oldState == STATE_NEW) { 10438db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // The handshake hasn't been started yet, so there's no OpenSSL related 10448db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // state to clean up. We still need to close the underlying socket if 10458db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // we're wrapping it and were asked to autoClose. 10468db22531f59b33539647ab95bb76354212d3866aNarayan Kamath closeUnderlyingSocket(); 1047f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 10488db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 104908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 105008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 105108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10528db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) { 10538db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // If we're in these states, we still haven't returned from startHandshake. 10548db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then 10558db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // set the state to STATE_CLOSED. startHandshake will handle all cleanup 10568db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // after SSL_do_handshake returns, so we don't have anything to do here. 10578db22531f59b33539647ab95bb76354212d3866aNarayan Kamath NativeCrypto.SSL_interrupt(sslNativePointer); 105808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10598db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 10608db22531f59b33539647ab95bb76354212d3866aNarayan Kamath return; 10618db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10628db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10638db22531f59b33539647ab95bb76354212d3866aNarayan Kamath stateLock.notifyAll(); 10648db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // We've already returned from startHandshake, so we potentially have 10658db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // input and output streams to clean up. 10668db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslInputStream = is; 10678db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslOutputStream = os; 10688db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10698db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10708db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Don't bother interrupting unless we have something to interrupt. 10718db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslInputStream != null || sslOutputStream != null) { 1072fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 10738db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10748b352156f879e7b36d223d3f65b8de46b7dc4dcfBrian Carlstrom 10758db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // Wait for the input and output streams to finish any reads they have in 10768db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // progress. If there are no reads in progress at this point, future reads will 10778db22531f59b33539647ab95bb76354212d3866aNarayan Kamath // throw because state == STATE_CLOSED 10788db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslInputStream != null) { 10798db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslInputStream.awaitPendingOps(); 10808db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10818db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (sslOutputStream != null) { 10828db22531f59b33539647ab95bb76354212d3866aNarayan Kamath sslOutputStream.awaitPendingOps(); 10838db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10848db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10858db22531f59b33539647ab95bb76354212d3866aNarayan Kamath shutdownAndFreeSslNative(); 10868db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 10878db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 10888db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void shutdownAndFreeSslNative() throws IOException { 10898db22531f59b33539647ab95bb76354212d3866aNarayan Kamath try { 10908db22531f59b33539647ab95bb76354212d3866aNarayan Kamath BlockGuard.getThreadPolicy().onNetwork(); 10913e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root NativeCrypto.SSL_shutdown(sslNativePointer, Platform.getFileDescriptor(socket), 10928db22531f59b33539647ab95bb76354212d3866aNarayan Kamath this); 10938db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } catch (IOException ignored) { 10948db22531f59b33539647ab95bb76354212d3866aNarayan Kamath /* 10958db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * Note that although close() can throw 10968db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * IOException, the RI does not throw if there 10978db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * is problem sending a "close notify" which 10988db22531f59b33539647ab95bb76354212d3866aNarayan Kamath * can happen if the underlying socket is closed. 10998db22531f59b33539647ab95bb76354212d3866aNarayan Kamath */ 11008db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } finally { 11018db22531f59b33539647ab95bb76354212d3866aNarayan Kamath free(); 11028db22531f59b33539647ab95bb76354212d3866aNarayan Kamath closeUnderlyingSocket(); 11038db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11048db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11058db22531f59b33539647ab95bb76354212d3866aNarayan Kamath 11068db22531f59b33539647ab95bb76354212d3866aNarayan Kamath private void closeUnderlyingSocket() throws IOException { 11078db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (socket != this) { 11088db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (autoClose && !socket.isClosed()) { 11098db22531f59b33539647ab95bb76354212d3866aNarayan Kamath socket.close(); 11108db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } 11118db22531f59b33539647ab95bb76354212d3866aNarayan Kamath } else { 11128db22531f59b33539647ab95bb76354212d3866aNarayan Kamath if (!super.isClosed()) { 11138db22531f59b33539647ab95bb76354212d3866aNarayan Kamath super.close(); 111408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 111508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 111608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 111708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1118f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 1119f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 1120f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 1121f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 1122f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1123f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 1124fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 1125f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 112608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1127f06338c01394610174fe2b3532beac56d61d9e26Kenny Root @Override 1128f06338c01394610174fe2b3532beac56d61d9e26Kenny Root protected void finalize() throws Throwable { 11291990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 11301990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 11311990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 11321990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 11331990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 11341990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 11351990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 11361990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 11371990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 11381990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 11391990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 11401990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 11411990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 11421990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 11431990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 11441990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 11451990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 1146f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 1147f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 1148f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 11491990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 11501990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 11511990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 11521990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 115308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 11540648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey 11553e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root /* @Override */ 11560648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 11570648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey if (socket == this) { 11583e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return Platform.getFileDescriptorFromSSLSocket(this); 11590648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } else { 11603e46e4ee56c8e37158f46941dedd5b436d724baaKenny Root return Platform.getFileDescriptor(socket); 11610648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 11620648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 1163721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1164721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 1165721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Returns the protocol agreed upon by client and server, or null if no 1166721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocol was agreed upon. 1167721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1168721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public byte[] getNpnSelectedProtocol() { 1169263808a68e1538db41196065830107991e9f974aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 1170721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 1171721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1172721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 11736fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Returns the protocol agreed upon by client and server, or {@code null} if 11746fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * no protocol was agreed upon. 11756fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 11766fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public byte[] getAlpnSelectedProtocol() { 11776fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 11786fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 11796fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 11806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 1181721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Sets the list of protocols this peer is interested in. If null no 1182721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocols will be used. 1183721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * 1184d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 1185d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1186d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * strings. The length byte itself is not included in the length. A byte 1187d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 1188721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1189721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 1190d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 1191d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 1192d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson } 11933c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.npnProtocols = npnProtocols; 1194721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 11956fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 11966fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 11976fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Sets the list of protocols this peer is interested in. If the list is 11986fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * {@code null}, no protocols will be used. 11996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * 12006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * @param alpnProtocols a non-empty array of protocol names. From 12016fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 12026fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * strings. The length byte itself is not included in the length. 12036fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * A byte string of length 0 is invalid. No byte string may be 12046fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * truncated.". 12056fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 12066fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public void setAlpnProtocols(byte[] alpnProtocols) { 12076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root if (alpnProtocols != null && alpnProtocols.length == 0) { 12086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root throw new IllegalArgumentException("alpnProtocols.length == 0"); 12096fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 12103c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root sslParameters.alpnProtocols = alpnProtocols; 12112d089e18deae231149737cad6ce00f1e137a7199Alex Klyubin } 1212d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root 1213d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root @Override 12143c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root public String chooseServerAlias(X509KeyManager keyManager, String keyType) { 12153c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root return keyManager.chooseServerAlias(keyType, null, this); 12163c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root } 12173c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root 12183c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root @Override 12193c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 12203c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root String[] keyTypes) { 12213c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root return keyManager.chooseClientAlias(keyTypes, null, this); 12223c072fb087eaa1a363fc673c60f5ef65390e356fKenny Root } 122301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin 122401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @Override 122501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) { 122601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin return keyManager.chooseServerKeyIdentityHint(this); 122701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin } 122801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin 122901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @Override 123001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) { 123101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin return keyManager.chooseClientKeyIdentity(identityHint, this); 123201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin } 123301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin 123401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin @Override 123501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) { 123601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin return keyManager.getKey(identityHint, identity, this); 123701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin } 123808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 1239