OpenSSLSocketImpl.java revision 5006f3bedbfd19dc905416bbf28bb0e95807f845
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 1708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 1808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrickimport dalvik.system.BlockGuard; 20fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport dalvik.system.CloseGuard; 2108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.IOException; 2208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.InputStream; 2308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.io.OutputStream; 2408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.InetAddress; 2508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.Socket; 2608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.net.SocketException; 2798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey; 2898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom; 291f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException; 3008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException; 3108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.X509Certificate; 3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList; 3397e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughesimport java.util.Arrays; 34d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.HashSet; 35d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.Set; 3608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 39edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 408765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException; 4108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 42fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 4408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 4508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 4908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 50f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * later, for example in the package.html or a separate reference document. 510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>compression methods 560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 5908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 60f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 61f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 6298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 6390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 64f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private int sslNativePointer; 6508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private InputStream is; 6608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OutputStream os; 6708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private final Object handshakeLock = new Object(); 68f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object readLock = new Object(); 69f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object writeLock = new Object(); 70cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private SSLParametersImpl sslParameters; 712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledProtocols; 722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledCipherSuites; 730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private String[] enabledCompressionMethods; 740b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private boolean useSessionTickets; 750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private String hostname; 7608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OpenSSLSessionImpl sslSession; 7790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private final Socket socket; 7808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean autoClose; 7908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean handshakeStarted = false; 80f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom private final CloseGuard guard = CloseGuard.get(); 812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Not set to true until the update from native that tells us the 842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * before the handshake is completely done due to 862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * handshake_cutthrough support. 872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private boolean handshakeCompleted = false; 892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 9008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 9172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 9272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom /** 9372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 9472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * write for non-wrapped sockets. Note that 9572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 9672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 9772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom */ 9872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int timeoutMilliseconds = 0; 9972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 10072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 1016e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private String wrappedHost; 1026e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private int wrappedPort; 10308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 104cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 10590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 106f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 10708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 109cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 1102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCipherSuites, 1120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 11390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 1140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods); 1152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 1162828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 117cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 11890ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 11908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port); 12090ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 121f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 12208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 12308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 124cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 12590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 12608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port); 12790ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 128f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 12908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 13008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 13108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 132c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, 133c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 1345006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 13508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port, clientAddress, clientPort); 13690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 137f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 13808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 13908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 14008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 141c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 1425006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson SSLParametersImpl sslParameters) throws IOException { 14308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, 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 /** 1495006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1505006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * OpenSSLSocketImplWrapper constructor. 15108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 15208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 153cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 15408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.socket = socket; 1556e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedHost = host; 1566e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedPort = port; 15708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.autoClose = autoClose; 158f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 15972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 16072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // this.timeout is not set intentionally. 16172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 16272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // to wrapped socket 163f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 164f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 165f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 166f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * Initialize the SSL socket and set the certificates for the 167f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * future handshaking. 168f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 169cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 1702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom init(sslParameters, 1712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom NativeCrypto.getSupportedProtocols(), 1720b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom NativeCrypto.getDefaultCipherSuites(), 1730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom NativeCrypto.getDefaultCompressionMethods()); 174f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 175f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 176f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 1772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Initialize the SSL socket and set the certificates for the 1782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * future handshaking. 179f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 180cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters, 1812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCipherSuites, 1830b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 1842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.sslParameters = sslParameters; 1852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledProtocols = enabledProtocols; 1862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 1870b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.enabledCompressionMethods = enabledCompressionMethods; 18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 19108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Gets the suitable session reference from the session cache container. 19208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 1932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (super.getInetAddress() == null || 19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostAddress() == null || 19608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostName() == null) { 19708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return null; 19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 19961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession( 20008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostName(), 20108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getPort()); 20261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (session == null) { 20361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 20461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 20561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 20661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String protocol = session.getProtocol(); 20761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean protocolFound = false; 20861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 20961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (protocol.equals(enabledProtocol)) { 21061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom protocolFound = true; 21161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 21261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!protocolFound) { 21561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 21661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 21861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String cipherSuite = session.getCipherSuite(); 21961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean cipherSuiteFound = false; 22061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 22161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 22261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom cipherSuiteFound = true; 22361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 22461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!cipherSuiteFound) { 22761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 22861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String compressionMethod = session.getCompressionMethod(); 2310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom boolean compressionMethodFound = false; 2320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom for (String enabledCompressionMethod : enabledCompressionMethods) { 2330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom if (compressionMethod.equals(enabledCompressionMethod)) { 2340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom compressionMethodFound = true; 2350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom break; 2360b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom if (!compressionMethodFound) { 2390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return null; 2400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 24261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return session; 24308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 24408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 24508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 24608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Starts a TLS/SSL handshake on this connection using some native methods 24708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * from the OpenSSL library. It can negotiate new encryption keys, change 24808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * cipher suites, or initiate a new session. The certificate chain is 24908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * verified if the correspondent property in java.Security is set. All 250f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * listeners are notified at the end of the TLS/SSL handshake. 25108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 2520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 2532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void startHandshake() throws IOException { 2542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom startHandshake(true); 2552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 2562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 257a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom private void checkOpen() throws SocketException { 258a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom if (isClosed()) { 259a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom throw new SocketException("Socket is closed"); 260a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 261a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 262a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom 263a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom /** 2642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Perform the handshake 2655006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * 2662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @param full If true, disable handshake cutthrough for a fully synchronous handshake 2672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 2682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public synchronized void startHandshake(boolean full) throws IOException { 26908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 2707b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 27108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 27208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 27308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 27408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 27508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 27608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 27708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 27898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 27998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 28098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 28198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (secureRandom == null) { 28298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 28398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } else { 28498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 28598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 28698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 28798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 28898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 28998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int sslCtxNativePointer = (client) ? 29098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 29198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 29298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 293fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this.sslNativePointer = 0; 294fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean exception = true; 295fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 296fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 297fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.open("close"); 29898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 299fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup server certificates and private keys. 300fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // clients will receive a call back to request certificates. 301fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!client) { 302d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 303d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 304aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 305aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom continue; 306aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom } 307ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 308d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom if (keyType != null) { 309d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom keyTypes.add(keyType); 310d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 311d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 312d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String keyType : keyTypes) { 313fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 314fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 315fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom null, 316fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this)); 317fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 318fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException(e); 319fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 320f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 32198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 32298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 323fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 324fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 325fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (enabledCompressionMethods.length != 0) { 326fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCompressionMethods(sslNativePointer, 327fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enabledCompressionMethods); 328fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 329fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (useSessionTickets) { 330fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 331fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 332fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (hostname != null) { 333fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 334fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3352828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 336fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 337fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 338fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 339fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enableSessionCreation); 3402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3412828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 342fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom AbstractSessionContext sessionContext; 343fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 344fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // look for client session to reuse 345fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 346fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = clientSessionContext; 3475006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson OpenSSLSessionImpl session = getCachedClientSession(clientSessionContext); 348fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (session != null) { 349fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 350fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom session.sslSessionNativePointer); 351fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 352f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } else { 353fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 354f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 35598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup peer certificate verification 357fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 358fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // TODO support for anonymous cipher would require us to 359fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // conditionally use SSL_VERIFY_NONE 360fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 361fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // needing client auth takes priority... 3625006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson boolean certRequested; 363fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 364fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 365fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 366fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 367fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 368fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... over just wanting it... 369fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 370fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 371fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 372fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 373fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 374fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 375fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = false; 376fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 377fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 378fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (certRequested) { 379fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 380fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 381fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (issuers != null && issuers.length != 0) { 382fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[][] issuersBytes; 383fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 384fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 385fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 386fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException("Problem encoding principals", e); 387fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 388fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 389f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 390f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 391f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 392f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 393fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client && full) { 394fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 395fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 396fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 397fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 398f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 399fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 400fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int savedTimeoutMilliseconds = getSoTimeout(); 401fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 402fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 403fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 4042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 405fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int sslSessionNativePointer; 406fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 407a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 408a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes socket.getFileDescriptor$(), this, getSoTimeout(), client); 409fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 410d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 411d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 412d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 4132828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 414fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 415fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 416fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslSession != null) { 417fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 418fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 419fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 420fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 421fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 422fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 423fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 424fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] localCertificates 425fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 426fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] peerCertificates 427fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 428fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (wrappedHost == null) { 429fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 430fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom localCertificates, peerCertificates, 431fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom super.getInetAddress().getHostName(), 432fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom super.getPort(), sessionContext); 433fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 434fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 435fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom localCertificates, peerCertificates, 436fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom wrappedHost, wrappedPort, 437fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext); 438fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 439fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 440fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 441fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext.putSession(sslSession); 442fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 443f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 444fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 445fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 446fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 447fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(savedTimeoutMilliseconds); 448331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 44908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 450fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 451fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 452fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 453fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 454f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 455fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom exception = false; 4568765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } catch (SSLProtocolException e) { 4578765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom throw new SSLHandshakeException(e); 458fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 459aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 460fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (exception) { 461aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom close(); 462fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 46308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 464e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 46508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 466e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom /** 467e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * Return a possibly null array of X509Certificates given the 468e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * possibly null array of DER encoded bytes. 469e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom */ 47090ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 471e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (certificatesBytes == null) { 472e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 473e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 474e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 475e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 476e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 477e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 478e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 479e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 480e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 481e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 482e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return certificates; 4832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 48408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 485f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 48698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (alias == null) { 48798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom return; 48898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 48998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 4908765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (privateKey == null) { 4918765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 4928765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 49398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 4948765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (certificates == null) { 4958765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 4968765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 4978765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom 4988765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom byte[] privateKeyBytes = privateKey.getEncoded(); 499f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 5008765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 50198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 50298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 50398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // checks the last installed private key and certificate, 50498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // so need to do this once per loop iteration 50598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 50698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 50798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5085006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 50998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 510f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 51198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 51298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 51398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 514ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 51598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 51698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 51798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom X500Principal[] issuers; 51898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom if (asn1DerEncodedPrincipals == null) { 51998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = null; 52098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } else { 52198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 52298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 52398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 52498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 52598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 52698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 52798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 52898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5295006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 5302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void handshakeCompleted() { 5312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom handshakeCompleted = true; 53208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // If sslSession is null, the handshake was completed during 5342828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5355006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // later read operation. That means we do not need to fix up 5362828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the SSLSession and session cache or notify 5372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // HandshakeCompletedListeners, it will be done in 5382828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // startHandshake. 5392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (sslSession == null) { 5402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return; 5412828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 54208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5432828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 5442828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 5452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 5462828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 5472828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 5482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 5492828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 55008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 5512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 5532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 5542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5552828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 5572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 5582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 5592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 5602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 5612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 5622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 5632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 5642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 565371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 566371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 567371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 568371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 569371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 570371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 571371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 5722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 57508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 57608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5775006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5785006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 57998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 58008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 581371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom if (bytes == null || bytes.length == 0) { 582371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 583371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 5842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 5852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 5866e24f16869f652c340bb973069ec5fec21317137Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 58708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 5892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 59098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 59198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom authMethod); 5922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 593ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 59498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 595ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom authType); 59608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 5972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5982828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 5992828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 6003a246337af275463275e608f6bd6f48b57322aacBrian Carlstrom } catch (RuntimeException e) { 6013a246337af275463275e608f6bd6f48b57322aacBrian Carlstrom throw e; 6022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 6032828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw new RuntimeException(e); 60408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 60508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 60608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6075006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public InputStream getInputStream() throws IOException { 608a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 609f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 61008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 61108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 61208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 61308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 61408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return is; 61508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 61608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 61708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6185006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public OutputStream getOutputStream() throws IOException { 619a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 620f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 62108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 62208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 62308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 62508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return os; 62608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 63008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 63108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 63208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 63308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLInputStream() throws IOException { 63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 63708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 63808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * SSLInputStream object will be created. 63908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 64608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 64808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> 64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 652ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 653f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6547b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 655a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read_byte(sslNativePointer, socket.getFileDescriptor$(), 656a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, getSoTimeout()); 65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 66208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 66308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6640b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 66597e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 666ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 667f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6687b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 66997e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 67097e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 6717b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return 0; 6727b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 673a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 674a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 67508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 67908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 68108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 68208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 68308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 68408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 68508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLOutputStream() throws IOException { 68608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 68708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 688f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * SSLOutputStream object will be created. 68908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 69108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(int) 69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6970b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void write(int b) throws IOException { 699ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 700f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7017b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 702a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write_byte(sslNativePointer, socket.getFileDescriptor$(), 703a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, b); 70408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 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(byte[],int,int) 71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 71297e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 713ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 714f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7157b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 71697e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 71797e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 7187b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return; 7197b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 720a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 721a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount); 72208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 72308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 72408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 72508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 72608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7275006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public SSLSession getSession() { 728e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 729e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 730e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom startHandshake(true); 731e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 732e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 733e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 734e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 735e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 73608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 73808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7405006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void addHandshakeCompletedListener( 74108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 74208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 74308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 74408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 7465006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 74708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 74808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 74908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7515006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void removeHandshakeCompletedListener( 75208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 75308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 75408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 75508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!listeners.remove(listener)) { 76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 76308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7665006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getEnableSessionCreation() { 76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7705006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7745006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedCipherSuites() { 775f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7785006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledCipherSuites() { 7792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledCipherSuites.clone(); 78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7825006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 7832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 78408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7865006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedProtocols() { 787f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7905006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledProtocols() { 7912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledProtocols.clone(); 79208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7945006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 7952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 79608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 7990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods that may be used on this SSL 8000b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * connection. 8010b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 8020b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getSupportedCompressionMethods() { 8040b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return NativeCrypto.getSupportedCompressionMethods(); 8050b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods versions that are in use 8090b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * on this SSL connection. 8100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 8120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getEnabledCompressionMethods() { 8140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return enabledCompressionMethods.clone(); 8150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8185006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Enables compression methods listed by getSupportedCompressionMethods(). 8190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @throws IllegalArgumentException when one or more of the names in the 8210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * array are not supported, or when the array is null. 8220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8235006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson public void setEnabledCompressionMethods(String[] methods) { 8240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 8250b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 8290b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 8310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.useSessionTickets = useSessionTickets; 8340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8360b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 8380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 8420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.hostname = hostname; 8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8455006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getUseClientMode() { 84608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 84708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 84808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8495006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setUseClientMode(boolean mode) { 85008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 85108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 8525006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson "Could not change the mode after the initial handshake has begun."); 85308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 85408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 85508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 85608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8575006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getWantClientAuth() { 85808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 85908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8615006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getNeedClientAuth() { 86208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 86308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8655006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setNeedClientAuth(boolean need) { 86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8695006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setWantClientAuth(boolean want) { 87008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8735006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void sendUrgentData(int data) throws IOException { 8745006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 87508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8775006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 8785006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8815006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setSoTimeout(int timeoutMilliseconds) throws SocketException { 88272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom super.setSoTimeout(timeoutMilliseconds); 88372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.timeoutMilliseconds = timeoutMilliseconds; 88472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 88572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 8865006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public int getSoTimeout() throws SocketException { 88772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom return timeoutMilliseconds; 88808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 890331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 891331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 892331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 893331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 89472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException { 89572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.handshakeTimeoutMilliseconds = timeoutMilliseconds; 896331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 897331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 8985006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void close() throws IOException { 8995006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 90008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 90108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 9035006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // prevent further attempts to start handshake 90408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 905f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 90608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 907f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 90808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 90990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 91008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 91108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 91208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) super.close(); 91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 915f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 91608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 91708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 92058a44774b954fed596ee22307a231de783ea8121Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 92108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 92208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (writeLock) { 92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (readLock) { 92508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 92608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // Shut down the SSL connection, per se. 92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 92808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 929ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 930a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 931a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes this); 93208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93386c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom } catch (IOException ignored) { 93408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 93586c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * Note that although close() can throw 93686c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * IOException, the RI does not throw if there 93786c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * is problem sending a "close notify" which 93886c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * can happen if the underlying socket is closed. 93908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 94008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 94108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 94208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 94308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Even if the above call failed, it is still safe to free 94408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * the native structs, and we need to do so lest we leak 94508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * memory. 94608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 947f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 94808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 94990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 95008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) 95108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project socket.close(); 95208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 95308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) 95408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.close(); 95508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 961f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 962f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 963f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 964f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 965f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 966f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 967fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 968f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 96908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9701990574e420184f3ad43400171f624dad44700d8Brian Carlstrom @Override protected void finalize() throws Throwable { 9711990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 9721990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 9731990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 9741990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 9751990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 9761990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 9771990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 9781990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 9791990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 9801990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 9811990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 9821990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 9831990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 9841990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 9851990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 9861990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 9871990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 988f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 989f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 990f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 9911990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 9921990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 9931990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 9941990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 99508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 997