OpenSSLSocketImpl.java revision 6fcf0cbeec79d1f2491d8d0774fdb314fc419ba3
108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/* 208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * you may not use this file except in compliance with the License. 608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * You may obtain a copy of the License at 708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 1008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 1108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 1208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * See the License for the specific language governing permissions and 1408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * limitations under the License. 1508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 1608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt; 1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard; 20fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard; 210648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkeyimport java.io.FileDescriptor; 2208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException; 2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream; 2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream; 2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress; 2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket; 2708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException; 281ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Rootimport java.security.InvalidKeyException; 2998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey; 3098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom; 311f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException; 3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException; 3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.X509Certificate; 3408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList; 3597e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughesimport java.util.Arrays; 36d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.HashSet; 37d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.Set; 3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 3908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 41edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 42a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException; 438765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException; 4408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 45fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 47fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport static libcore.io.OsConstants.*; 48fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.ErrnoException; 49fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.Libcore; 505c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstromimport libcore.io.Streams; 51fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstromimport libcore.io.StructTimeval; 5208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 6208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 63f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 64f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 6598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 6690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 6738c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice private long sslNativePointer; 6808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private InputStream is; 6908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OutputStream os; 7008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private final Object handshakeLock = new Object(); 71f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object readLock = new Object(); 72f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object writeLock = new Object(); 73cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private SSLParametersImpl sslParameters; 74721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson private byte[] npnProtocols; 756fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root private byte[] alpnProtocols; 762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledProtocols; 772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledCipherSuites; 780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private boolean useSessionTickets; 790b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private String hostname; 80577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** Whether the TLS Channel ID extension is enabled. This field is server-side only. */ 81577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin private boolean channelIdEnabled; 82577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** Private key for the TLS Channel ID extension. This field is client-side only. */ 831ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root private OpenSSLKey channelIdPrivateKey; 8408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OpenSSLSessionImpl sslSession; 8590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private final Socket socket; 8608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean autoClose; 8708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean handshakeStarted = false; 88f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom private final CloseGuard guard = CloseGuard.get(); 892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Not set to true until the update from native that tells us the 922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * before the handshake is completely done due to 942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * handshake_cutthrough support. 952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private boolean handshakeCompleted = false; 972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 9808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 9972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 10072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom /** 10172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 10272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * write for non-wrapped sockets. Note that 10372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 10472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 10572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom */ 106fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int readTimeoutMilliseconds = 0; 107fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom private int writeTimeoutMilliseconds = 0; 10872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 10972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 1106e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private String wrappedHost; 1116e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private int wrappedPort; 11208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 113cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 11490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 115f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 11608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 11708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 118cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 1192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1205ea53c028b903ce252e08c1b67508ce8dafcff34Brian Carlstrom String[] enabledCipherSuites) throws IOException { 12190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 1225ea53c028b903ce252e08c1b67508ce8dafcff34Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites); 1232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 1242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 125cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 12690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 12708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port); 12890ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 129f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 13008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 13108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 132cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 13390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 13408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port); 13590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 136f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 13708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 13808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 13908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 140c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, 141c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 1425006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 14308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port, clientAddress, clientPort); 14490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 145f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 14608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 14708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 14808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 149c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 1505006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 15108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port, clientAddress, clientPort); 15290ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 153f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 15408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 15508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 15608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 1575006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1585006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * OpenSSLSocketImplWrapper constructor. 15908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 16008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 161cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 16208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.socket = socket; 1636e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedHost = host; 1646e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedPort = port; 16508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.autoClose = autoClose; 166f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 16772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 16872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // this.timeout is not set intentionally. 16972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 17072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // to wrapped socket 171f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 172f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 173f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 174f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * Initialize the SSL socket and set the certificates for the 175f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * future handshaking. 176f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 177cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 1782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom init(sslParameters, 1797fce41e05553f8edd1468a68eafb40249a6337cbBrian Carlstrom NativeCrypto.getDefaultProtocols(), 1805ea53c028b903ce252e08c1b67508ce8dafcff34Brian Carlstrom NativeCrypto.getDefaultCipherSuites()); 181f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 182f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 183f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 1842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Initialize the SSL socket and set the certificates for the 1852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * future handshaking. 186f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 187cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters, 1882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1895ea53c028b903ce252e08c1b67508ce8dafcff34Brian Carlstrom String[] enabledCipherSuites) throws IOException { 1902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.sslParameters = sslParameters; 1912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledProtocols = enabledProtocols; 1922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 19308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 19608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Gets the suitable session reference from the session cache container. 19708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 1982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 1993967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson String hostName = getPeerHostName(); 2003967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson int port = getPeerPort(); 2013967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson if (hostName == null) { 20208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return null; 20308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 2043967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 20561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (session == null) { 20661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 20761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 20861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 20961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String protocol = session.getProtocol(); 21061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean protocolFound = false; 21161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 21261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (protocol.equals(enabledProtocol)) { 21361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom protocolFound = true; 21461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 21561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!protocolFound) { 21861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 21961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 22161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String cipherSuite = session.getCipherSuite(); 22261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean cipherSuiteFound = false; 22361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 22461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 22561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom cipherSuiteFound = true; 22661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 22761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!cipherSuiteFound) { 23061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 23161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 23298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 23361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return session; 23408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 236a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom private void checkOpen() throws SocketException { 237a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom if (isClosed()) { 238a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom throw new SocketException("Socket is closed"); 239a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 240a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 241a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom 242a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom /** 243d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 244d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 245d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 246d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * verified if the correspondent property in java.Security is set. All 247d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 2482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 249d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson @Override public synchronized void startHandshake() throws IOException { 25008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 2517b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 25208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 25308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 25408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 25508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 25608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 25708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 25808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 25998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 26098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 26198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 26298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (secureRandom == null) { 26398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 26498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } else { 26598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 26698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 26798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 26898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 26998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 27038c70d393f14cf0963a289caefb72e6ac14e23d3Joel Dice final long sslCtxNativePointer = (client) ? 27198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 27298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 27398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 274fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this.sslNativePointer = 0; 275fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean exception = true; 276fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 277fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 278fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.open("close"); 27998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 280721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson if (npnProtocols != null) { 281721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 282721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 283721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 2846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root if (client && alpnProtocols != null) { 2856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root NativeCrypto.SSL_CTX_set_alpn_protos(sslCtxNativePointer, alpnProtocols); 2866fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 2876fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 288fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup server certificates and private keys. 289fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // clients will receive a call back to request certificates. 290fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!client) { 291d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 292d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 293aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 294aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom continue; 295aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom } 296ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 297d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom if (keyType != null) { 298d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom keyTypes.add(keyType); 299d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 300d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 301d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String keyType : keyTypes) { 302fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 303fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 304fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom null, 305fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this)); 306fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 307fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException(e); 308fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 309f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 31098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 31198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 312fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 313fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 314fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (useSessionTickets) { 315fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 316fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 317fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (hostname != null) { 318fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 319fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 321fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 322fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 323fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 324fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enableSessionCreation); 3252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 327fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom AbstractSessionContext sessionContext; 328a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom OpenSSLSessionImpl sessionToReuse; 329fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 330fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // look for client session to reuse 331fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 332fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = clientSessionContext; 333a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom sessionToReuse = getCachedClientSession(clientSessionContext); 334a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom if (sessionToReuse != null) { 335fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 336a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom sessionToReuse.sslSessionNativePointer); 337fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 338f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } else { 339fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 340a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom sessionToReuse = null; 341f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 34298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 343fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup peer certificate verification 344fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 345fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // TODO support for anonymous cipher would require us to 346fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // conditionally use SSL_VERIFY_NONE 347fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 348fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // needing client auth takes priority... 3495006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson boolean certRequested; 350fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 351fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 352fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 353fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 354fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 355fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... over just wanting it... 356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 357fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 358fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 359fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 360fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 361fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 362fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = false; 363fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 364fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 365fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (certRequested) { 366fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 367fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 368fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (issuers != null && issuers.length != 0) { 369fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[][] issuersBytes; 370fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 3713ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root issuersBytes = encodeIssuerX509Principals(issuers); 372fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 373fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException("Problem encoding principals", e); 374fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 375fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 376f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 377f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 378f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 379f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 380fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 381fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 382fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 383fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 384fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 385fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 386fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 388577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin // TLS Channel ID 3891ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (channelIdEnabled) { 3901ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (client) { 3911ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root // Client-side TLS Channel ID 3921ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (channelIdPrivateKey == null) { 3931ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root throw new SSLHandshakeException("Invalid TLS channel ID key specified"); 3941ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 3951ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, 3961ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root channelIdPrivateKey.getPkeyContext()); 3971ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } else { 3981ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root // Server-side TLS Channel ID 399577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer); 400577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 401577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 402577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 403fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int sslSessionNativePointer; 404fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 405a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 4066fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols, 4076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root client ? null : alpnProtocols); 408fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 409d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 410d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 411d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 4122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 413fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 414a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom if (sessionToReuse != null && Arrays.equals(sessionToReuse.getId(), sessionId)) { 415a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom this.sslSession = sessionToReuse; 416fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 417fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 418fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 419fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 420fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 421fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 422fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 423fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] localCertificates 424fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 425fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] peerCertificates 426fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 427a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom this.sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 4283967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 429fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 430fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 431fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext.putSession(sslSession); 432fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 433f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 434fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 435fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 436fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 437fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 438fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 439331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 44008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 441fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 442fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 443fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 444fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 445f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 446fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom exception = false; 4478765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } catch (SSLProtocolException e) { 4488765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom throw new SSLHandshakeException(e); 449fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 450aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 451fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (exception) { 452aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom close(); 453fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 45408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 455e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 4563ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root 4573ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root private static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates) 4583ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root throws CertificateEncodingException { 4593ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root byte[][] principalBytes = new byte[certificates.length][]; 4603ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root for (int i = 0; i < certificates.length; i++) { 4613ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded(); 4623ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root } 4633ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root return principalBytes; 4643ff2b34d00ea89eec5b895d866fddf05942fd2a7Kenny Root } 46508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 466bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra String getPeerHostName() { 4678ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (wrappedHost != null) { 4688ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return wrappedHost; 4698ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4708ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom InetAddress inetAddress = super.getInetAddress(); 4718ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (inetAddress != null) { 4728ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return inetAddress.getHostName(); 4738ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4748ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return null; 4753967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4763967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 477bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra int getPeerPort() { 4783967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 4793967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4803967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 481e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom /** 482e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * Return a possibly null array of X509Certificates given the 483e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * possibly null array of DER encoded bytes. 484e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom */ 485a5c365c0867e66e6b5ad8e3e9a1cbd306f35226bBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) throws IOException { 486e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (certificatesBytes == null) { 487e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 488e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 489e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 490e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 491860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root certificates[i] = OpenSSLX509Certificate.fromX509Der(certificatesBytes[i]); 492e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 493e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return certificates; 4942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 49508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 496f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 49798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (alias == null) { 49898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom return; 49998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 50098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 5018765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (privateKey == null) { 5028765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 5038765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 50498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 5058765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (certificates == null) { 5068765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 5078765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 5088765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom 5091ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root try { 5101ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root final OpenSSLKey key = OpenSSLKey.fromPrivateKey(privateKey); 5111ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext()); 5121ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } catch (InvalidKeyException e) { 5131ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root throw new SSLException(e); 514a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root } 515a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root 516f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 51798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 51898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 51998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // checks the last installed private key and certificate, 52098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // so need to do this once per loop iteration 52198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 52298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 52398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5245006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 52598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 526f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 52798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 52898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 52998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 530ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 53198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 53298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 53398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom X500Principal[] issuers; 53498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom if (asn1DerEncodedPrincipals == null) { 53598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = null; 53698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } else { 53798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 53898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 53998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 54098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 54198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 54298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 54398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 54498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5455006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 5462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void handshakeCompleted() { 5472828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom handshakeCompleted = true; 54808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5492828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // If sslSession is null, the handshake was completed during 5502828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5515006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // later read operation. That means we do not need to fix up 5522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the SSLSession and session cache or notify 5532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // HandshakeCompletedListeners, it will be done in 5542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // startHandshake. 5552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (sslSession == null) { 5562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return; 5572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 55808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 5602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 5612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 5622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 5632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 5642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 5652828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 56608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 5672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 5692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 5702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 5732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 5742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 5752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 5762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 5772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 5782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 5792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 5802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 581371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 582371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 583371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 584371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 585371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 586371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 587371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 5882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 59108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 59208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5935006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5945006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 59598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 59608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 597371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom if (bytes == null || bytes.length == 0) { 598371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 599371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 6002828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 6012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root peerCertificateChain[i] = OpenSSLX509Certificate.fromX509Der(bytes[i]); 60308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 6052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 606bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra X509TrustManager x509tm = sslParameters.getTrustManager(); 607bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra if (x509tm instanceof TrustManagerImpl) { 608bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra TrustManagerImpl tm = (TrustManagerImpl) x509tm; 609bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra tm.checkServerTrusted(peerCertificateChain, authMethod, wrappedHost); 610bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra } else { 611bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra x509tm.checkServerTrusted(peerCertificateChain, authMethod); 612bbe7b9241a63a18bebebf38206d0aebb015f1518Geremy Condra } 6132828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 614ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 61598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 616ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom authType); 61708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 6192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 6202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 6212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 6229400b50da5ca8f1e796f5b158063db0aefb58441Brian Carlstrom throw new CertificateException(e); 62308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6265006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public InputStream getInputStream() throws IOException { 627a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 628f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 62908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 63008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 63108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 63308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return is; 63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6375006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public OutputStream getOutputStream() throws IOException { 638a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 639f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 64008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return os; 64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 65208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLInputStream() throws IOException { 655d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson /* 656d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * Note: When startHandshake() throws an exception, no 65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * SSLInputStream object will be created. 65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 659d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 66208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 66308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 66408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 66508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 66608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 66708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> 66808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6690b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 67008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 6715c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom return Streams.readSingleByte(this); 67208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 67408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 67508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 67997e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 680ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 681f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6827b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 68397e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 68497e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 6857b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return 0; 6867b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 687a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 688a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 68908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLOutputStream() throws IOException { 700d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson /* 701d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson * Note: When startHandshake() throws an exception, no 702f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * SSLOutputStream object will be created. 70308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 704d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 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 { 7135c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom Streams.writeSingleByte(this, oneByte); 71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 71608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 71708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 72197e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 722ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 723f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7247b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 72597e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 72697e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 7277b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return; 7287b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 729a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 730fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 73108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 73508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7365006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public SSLSession getSession() { 737e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 738e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 739d7f42443e3358023ee2848e4634a2f0ce11138e9Jesse Wilson startHandshake(); 740e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 741e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 742e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 743e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 744e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 74508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 74708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7495006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void addHandshakeCompletedListener( 75008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 75108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 75208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 75308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 7555006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7605006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void removeHandshakeCompletedListener( 76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 76308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 76408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 76608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!listeners.remove(listener)) { 77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7755006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getEnableSessionCreation() { 77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7795006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7835006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedCipherSuites() { 784f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 78508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7875006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledCipherSuites() { 7882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledCipherSuites.clone(); 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7915006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 7922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7955006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedProtocols() { 796f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7995006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledProtocols() { 8002828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledProtocols.clone(); 80108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8035006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 8042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 80708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 8080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 8090b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 8110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.useSessionTickets = useSessionTickets; 8140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 8180b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 8220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.hostname = hostname; 8230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 825577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 826577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Enables/disables TLS Channel ID for this server socket. 827577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 828577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 829577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 830577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has already 831577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 832577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 833577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 834577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public void setChannelIdEnabled(boolean enabled) { 835577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 836577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 837577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 838577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (handshakeStarted) { 839577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException( 840577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin "Could not enable/disable Channel ID after the initial handshake has" 841577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin + " begun."); 842577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 843577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin this.channelIdEnabled = enabled; 844577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 845577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 846577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 847577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 848577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * handshake completes. 849577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 850577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @return channel ID or {@code null} if not available. 851577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 852577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has not yet 853577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * completed. 854577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws SSLException if channel ID is available but could not be obtained. 855577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 856577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin public byte[] getChannelId() throws SSLException { 857577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (getUseClientMode()) { 858577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Client mode"); 859577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 860577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (!handshakeCompleted) { 861577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException( 862577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin "Channel ID is only available after handshake completes"); 863577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 864577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 865577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 866577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 867577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin /** 868577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 869577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 870577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 871577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 872577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 8734022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 874577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 875577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * 876577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * @throws IllegalStateException if this is a server socket or if the handshake has already 877577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin * started. 878577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin */ 8794022a5d005758bec373f5b6544fe9be2ef1c0378Alex Klyubin public void setChannelIdPrivateKey(PrivateKey privateKey) { 880577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (!getUseClientMode()) { 881577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException("Server mode"); 882577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 883577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin if (handshakeStarted) { 884577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin throw new IllegalStateException( 885577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin "Could not change Channel ID private key after the initial handshake has" 886577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin + " begun."); 887577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 8881ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root if (privateKey == null) { 8891ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root this.channelIdEnabled = false; 8901ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root this.channelIdPrivateKey = null; 8911ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } else { 8921ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root this.channelIdEnabled = true; 8931ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root try { 8941ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root this.channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey); 8951ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } catch (InvalidKeyException e) { 8961ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root // Will have error in startHandshake 8971ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 8981ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root } 899577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin } 900577e146ed2c9c9d166c4d30a495d95d4b171a7e8Alex Klyubin 9015006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getUseClientMode() { 90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 90308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 90408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9055006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setUseClientMode(boolean mode) { 90608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 90708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 9085006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson "Could not change the mode after the initial handshake has begun."); 90908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 91108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9135006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getWantClientAuth() { 91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 91508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9175006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getNeedClientAuth() { 91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 92008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9215006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setNeedClientAuth(boolean need) { 92208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9255006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setWantClientAuth(boolean want) { 92608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 92808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9295006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void sendUrgentData(int data) throws IOException { 9305006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 93108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9335006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 9345006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 93508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 937fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom @Override public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 938fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 939fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 94072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 94172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 9425006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public int getSoTimeout() throws SocketException { 943fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return readTimeoutMilliseconds; 944fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 945fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 946fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 947fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 948fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 949fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 950fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 951fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 952fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom StructTimeval tv = StructTimeval.fromMillis(writeTimeoutMilliseconds); 953fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom try { 954fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom Libcore.os.setsockoptTimeval(getFileDescriptor$(), SOL_SOCKET, SO_SNDTIMEO, tv); 955fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } catch (ErrnoException errnoException) { 956fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom throw errnoException.rethrowAsSocketException(); 957fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 958fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom } 959fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom 960fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom /** 961fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 962fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom */ 963fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 964fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom return writeTimeoutMilliseconds; 96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 967331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 968331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 969331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 970331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 971fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 972fba8b41283914ec1ba08dabfc23ecc974951a481Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 973331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 974331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 9755006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void close() throws IOException { 9765006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 97708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 97808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 97908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 9805006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // prevent further attempts to start handshake 98108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 982f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 98308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 984f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 98508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 98690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 98708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 98808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 98908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) super.close(); 99008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 992f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 99308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 99408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 99708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 99808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 999fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom // Interrupt any outstanding reads or writes before taking the writeLock and readLock 1000fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 10018b352156f879e7b36d223d3f65b8de46b7dc4dcfBrian Carlstrom 1002fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom synchronized (writeLock) { 1003fa6657aaf2fadbb1aeb2f869cba82042c1faedeaBrian Carlstrom synchronized (readLock) { 100408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // Shut down the SSL connection, per se. 100508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 100608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 1007ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 1008a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 1009a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes this); 101008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 101186c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom } catch (IOException ignored) { 101208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 101386c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * Note that although close() can throw 101486c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * IOException, the RI does not throw if there 101586c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * is problem sending a "close notify" which 101686c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * can happen if the underlying socket is closed. 101708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 101806327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } finally { 101906327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom /* 102006327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * Even if the above call failed, it is still safe to free 102106327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * the native structs, and we need to do so lest we leak 102206327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * memory. 102306327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom */ 102406327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom free(); 102506327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom 102606327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (socket != this) { 102706327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (autoClose && !socket.isClosed()) { 102806327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom socket.close(); 102906327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 103006327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } else { 103106327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (!super.isClosed()) { 103206327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom super.close(); 103306327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 103406327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 103508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 103608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 103708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 103808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 103908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 104008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1041f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 1042f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 1043f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 1044f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 1045f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1046f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 1047fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 1048f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 104908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10501990574e420184f3ad43400171f624dad44700d8Brian Carlstrom @Override protected void finalize() throws Throwable { 10511990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 10521990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 10531990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 10541990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 10551990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 10561990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 10571990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 10581990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 10591990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 10601990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 10611990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 10621990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 10631990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 10641990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 10651990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 10661990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 10671990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 1068f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 1069f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 1070f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 10711990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 10721990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 10731990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 10741990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 107508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10760648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey 10770648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey @Override 10780648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 10790648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey if (socket == this) { 10800648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return super.getFileDescriptor$(); 10810648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } else { 10820648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return socket.getFileDescriptor$(); 10830648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 10840648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 1085721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1086721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 1087721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Returns the protocol agreed upon by client and server, or null if no 1088721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocol was agreed upon. 1089721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1090721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public byte[] getNpnSelectedProtocol() { 1091263808a68e1538db41196065830107991e9f974aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 1092721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 1093721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1094721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 10956fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Returns the protocol agreed upon by client and server, or {@code null} if 10966fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * no protocol was agreed upon. 10976fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 10986fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public byte[] getAlpnSelectedProtocol() { 10996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 11006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 11016fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 11026fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 1103721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Sets the list of protocols this peer is interested in. If null no 1104721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocols will be used. 1105721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * 1106d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 1107d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1108d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * strings. The length byte itself is not included in the length. A byte 1109d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 1110721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1111721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 1112d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 1113d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 1114d38e01d8984d319fd8111193b9bf0fa14bbe1629Jesse Wilson } 1115721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson this.npnProtocols = npnProtocols; 1116721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 11176fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root 11186fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root /** 11196fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * Sets the list of protocols this peer is interested in. If the list is 11206fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * {@code null}, no protocols will be used. 11216fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * 11226fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * @param alpnProtocols a non-empty array of protocol names. From 11236fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 11246fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * strings. The length byte itself is not included in the length. 11256fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * A byte string of length 0 is invalid. No byte string may be 11266fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root * truncated.". 11276fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root */ 11286fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root public void setAlpnProtocols(byte[] alpnProtocols) { 11296fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root if (alpnProtocols != null && alpnProtocols.length == 0) { 11306fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root throw new IllegalArgumentException("alpnProtocols.length == 0"); 11316fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 11326fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root this.alpnProtocols = alpnProtocols; 11336fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root } 113408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 1135