OpenSSLSocketImpl.java revision 263808a68e1538db41196065830107991e9f974a
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; 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; 2898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.PrivateKey; 2998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstromimport java.security.SecureRandom; 301f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstromimport java.security.cert.CertificateEncodingException; 3108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.CertificateException; 3208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.security.cert.X509Certificate; 3308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.ArrayList; 3497e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughesimport java.util.Arrays; 35d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.HashSet; 36d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstromimport java.util.Set; 3708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 3908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 40edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 418765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstromimport javax.net.ssl.SSLProtocolException; 4208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 43fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 455c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstromimport libcore.io.Streams; 4608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 4708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project/** 490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>compression methods 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 5808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 59f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 60f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 6198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 6290ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 63f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private int sslNativePointer; 6408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private InputStream is; 6508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OutputStream os; 6608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private final Object handshakeLock = new Object(); 67f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object readLock = new Object(); 68f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object writeLock = new Object(); 69cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private SSLParametersImpl sslParameters; 70721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson private byte[] npnProtocols; 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) { 1943967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson String hostName = getPeerHostName(); 1953967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson int port = getPeerPort(); 1963967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson if (hostName == null) { 19708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return null; 19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 1993967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 20061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (session == null) { 20161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 20261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 20361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 20461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String protocol = session.getProtocol(); 20561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean protocolFound = false; 20661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 20761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (protocol.equals(enabledProtocol)) { 20861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom protocolFound = true; 20961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 21061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!protocolFound) { 21361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 21461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 21561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 21661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String cipherSuite = session.getCipherSuite(); 21761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean cipherSuiteFound = false; 21861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 21961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 22061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom cipherSuiteFound = true; 22161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 22261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!cipherSuiteFound) { 22561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 22661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 22798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String compressionMethod = session.getCompressionMethod(); 2293967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson if (!compressionMethod.equals(NativeCrypto.SUPPORTED_COMPRESSION_METHOD_NULL)) { 2303967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson boolean compressionMethodFound = false; 2313967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson for (String enabledCompressionMethod : enabledCompressionMethods) { 2323967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson if (compressionMethod.equals(enabledCompressionMethod)) { 2333967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson compressionMethodFound = true; 2343967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson break; 2353967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 2363967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 2373967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson if (!compressionMethodFound) { 2383967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson return null; 2390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 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 299721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson if (npnProtocols != null) { 300721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 301721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 302721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 303fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup server certificates and private keys. 304fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // clients will receive a call back to request certificates. 305fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!client) { 306d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 307d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 308aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 309aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom continue; 310aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom } 311ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 312d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom if (keyType != null) { 313d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom keyTypes.add(keyType); 314d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 315d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 316d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String keyType : keyTypes) { 317fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 318fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 319fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom null, 320fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this)); 321fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 322fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException(e); 323fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 324f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 32598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 32698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 327fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 328fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 329fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (enabledCompressionMethods.length != 0) { 330fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCompressionMethods(sslNativePointer, 331fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enabledCompressionMethods); 332fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 333fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (useSessionTickets) { 334fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 335fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 336fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (hostname != null) { 337fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 338fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 340fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 341fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 342fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 343fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enableSessionCreation); 3442828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3452828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 346fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom AbstractSessionContext sessionContext; 347fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 348fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // look for client session to reuse 349fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 350fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = clientSessionContext; 3515006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson OpenSSLSessionImpl session = getCachedClientSession(clientSessionContext); 352fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (session != null) { 353fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 354fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom session.sslSessionNativePointer); 355fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 356f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } else { 357fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 358f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 35998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 360fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup peer certificate verification 361fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 362fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // TODO support for anonymous cipher would require us to 363fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // conditionally use SSL_VERIFY_NONE 364fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 365fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // needing client auth takes priority... 3665006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson boolean certRequested; 367fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 368fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 369fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 370fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 371fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 372fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... over just wanting it... 373fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 374fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 375fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 376fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 377fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 378fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 379fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = false; 380fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 381fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 382fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (certRequested) { 383fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 384fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 385fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (issuers != null && issuers.length != 0) { 386fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[][] issuersBytes; 387fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 388fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 389fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 390fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException("Problem encoding principals", e); 391fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 392fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 393f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 394f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 395f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 396f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 397fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client && full) { 398fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 399fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 400fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 401fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 402f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 403fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 404fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int savedTimeoutMilliseconds = getSoTimeout(); 405fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 406fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 407fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 4082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 409fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int sslSessionNativePointer; 410fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 411a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 412721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols); 413fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 414d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 415d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 416d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 4172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 418fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 419fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 420fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslSession != null) { 421fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 422fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 423fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 424fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 425fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 426fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 427fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 428fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] localCertificates 429fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 430fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] peerCertificates 431fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 4323967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 4333967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 434fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 435fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 436fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext.putSession(sslSession); 437fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 438f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 439fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 440fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 441fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 442fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(savedTimeoutMilliseconds); 443331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 44408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 445fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 446fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 447fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 448fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 449f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 450fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom exception = false; 4518765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } catch (SSLProtocolException e) { 4528765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom throw new SSLHandshakeException(e); 453fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 454aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 455fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (exception) { 456aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom close(); 457fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 45808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 459e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 46008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 4613967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson private String getPeerHostName() { 4628ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (wrappedHost != null) { 4638ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return wrappedHost; 4648ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4658ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom InetAddress inetAddress = super.getInetAddress(); 4668ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom if (inetAddress != null) { 4678ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return inetAddress.getHostName(); 4688ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom } 4698ca27778bfc34425a4b13ca3090dd517dd61519eBrian Carlstrom return null; 4703967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4713967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 4723967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson private int getPeerPort() { 4733967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 4743967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson } 4753967cef89302e18c0a651f7d90f4813ec2c1dc59Jesse Wilson 476e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom /** 477e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * Return a possibly null array of X509Certificates given the 478e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * possibly null array of DER encoded bytes. 479e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom */ 48090ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 481e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (certificatesBytes == null) { 482e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 483e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 484e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 485e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 486e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 487e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 488e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 489e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 490e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 491e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 492e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return certificates; 4932828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 49408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 495f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 49698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (alias == null) { 49798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom return; 49898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 49998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 5008765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (privateKey == null) { 5018765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 5028765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 50398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 5048765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom if (certificates == null) { 5058765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom return; 5068765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom } 5078765df62ff836a2c4ee8b956945c38ba017cf309Brian Carlstrom 508a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root if (privateKey instanceof OpenSSLRSAPrivateKey) { 509a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root OpenSSLRSAPrivateKey rsaKey = (OpenSSLRSAPrivateKey) privateKey; 510a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root OpenSSLKey key = rsaKey.getOpenSSLKey(); 511a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext()); 512a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root } else if (privateKey instanceof OpenSSLDSAPrivateKey) { 513a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root OpenSSLDSAPrivateKey dsaKey = (OpenSSLDSAPrivateKey) privateKey; 514a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root OpenSSLKey key = dsaKey.getOpenSSLKey(); 515a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext()); 516a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root } else if ("PKCS#8".equals(privateKey.getFormat())) { 517a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root byte[] privateKeyBytes = privateKey.getEncoded(); 518a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 519a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root } else { 520a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root throw new SSLException("Unsupported PrivateKey format: " + privateKey.getFormat()); 521a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root } 522a590ec8553482f097f10c5cb6dfaa4d44bdda1a0Kenny Root 523f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 52498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 52598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 52698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // checks the last installed private key and certificate, 52798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // so need to do this once per loop iteration 52898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 52998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 53098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5315006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 53298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 533f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 53498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 53598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 53698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 537ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 53898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 53998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 54098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom X500Principal[] issuers; 54198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom if (asn1DerEncodedPrincipals == null) { 54298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = null; 54398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } else { 54498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 54598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 54698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 54798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 54898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 54998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 55098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 55198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 5525006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 5532828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void handshakeCompleted() { 5542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom handshakeCompleted = true; 55508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5562828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // If sslSession is null, the handshake was completed during 5572828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5585006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // later read operation. That means we do not need to fix up 5592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the SSLSession and session cache or notify 5602828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // HandshakeCompletedListeners, it will be done in 5612828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // startHandshake. 5622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (sslSession == null) { 5632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return; 5642828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 56508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 5672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 5682828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 5692828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 5702828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 5712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 5722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 57308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 5742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 5762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 5772828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5782828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 5792828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 5802828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 5812828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 5822828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 5832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 5842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 5852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 5862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 5872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 588371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 589371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 590371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 591371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 592371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 593371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 594371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 5952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 5972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 59808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 59908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6005006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 6015006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 60298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 60308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 604371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom if (bytes == null || bytes.length == 0) { 605371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 606371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 6072828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 6082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 6096e24f16869f652c340bb973069ec5fec21317137Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 61008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 6122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 61398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 61498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom authMethod); 6152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 616ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 61798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 618ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom authType); 61908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 6212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 6222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 6233a246337af275463275e608f6bd6f48b57322aacBrian Carlstrom } catch (RuntimeException e) { 6243a246337af275463275e608f6bd6f48b57322aacBrian Carlstrom throw e; 6252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 6262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw new RuntimeException(e); 62708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 62908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6305006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public InputStream getInputStream() throws IOException { 631a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 632f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 63308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 63408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 63508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 63708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return is; 63808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 63908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6415006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public OutputStream getOutputStream() throws IOException { 642a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 643f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 64408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 64508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 64608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 64808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return os; 64908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6522828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 65308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 65508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 65608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 65708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 65808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLInputStream() throws IOException { 65908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 66008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * SSLInputStream object will be created. 66208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 66408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 66508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 66608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 66708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 66808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 66908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 67008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 67108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> 67208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6730b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 67408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 6755c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom return Streams.readSingleByte(this); 67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 67808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 67908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 68108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 68397e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 684ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 685f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 6867b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 68797e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 68897e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 6897b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return 0; 6907b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 691a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 692a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 70008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 70108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 70208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 70308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLOutputStream() throws IOException { 70408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 70508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 706f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * SSLOutputStream object will be created. 70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 71108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 71308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(int) 71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 7165c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom public void write(int oneByte) throws IOException { 7175c44d1fc26c081cf85af010b6e751449bde14b80Brian Carlstrom Streams.writeSingleByte(this, oneByte); 71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 72008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 72108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 72208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 72308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 72597e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 726ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 727f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 7287b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 72997e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 73097e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 7317b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return; 7327b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 733a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 734a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount); 73508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 73908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7405006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public SSLSession getSession() { 741e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 742e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 743e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom startHandshake(true); 744e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 745e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 746e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 747e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 748e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 74908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 75108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7535006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void addHandshakeCompletedListener( 75408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 75508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 7595006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7645006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void removeHandshakeCompletedListener( 76508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 76608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 76708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 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 if (!listeners.remove(listener)) { 77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 77508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 77608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7795006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getEnableSessionCreation() { 78008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 78108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7835006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 78408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 78508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7875006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedCipherSuites() { 788f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7915006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledCipherSuites() { 7922828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledCipherSuites.clone(); 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7955006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 7962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7995006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getSupportedProtocols() { 800f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 80108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8035006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public String[] getEnabledProtocols() { 8042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledProtocols.clone(); 80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8075006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 8082828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 81108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 8120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods that may be used on this SSL 8130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * connection. 8140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 8150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getSupportedCompressionMethods() { 8170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return NativeCrypto.getSupportedCompressionMethods(); 8180b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods versions that are in use 8220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * on this SSL connection. 8230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 8250b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getEnabledCompressionMethods() { 8270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return enabledCompressionMethods.clone(); 8280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8290b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8315006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson * Enables compression methods listed by getSupportedCompressionMethods(). 8320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @throws IllegalArgumentException when one or more of the names in the 8340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * array are not supported, or when the array is null. 8350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8365006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson public void setEnabledCompressionMethods(String[] methods) { 8370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 8380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 8420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 8440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8450b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.useSessionTickets = useSessionTickets; 8470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 8500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 8510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 8520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 8540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 8550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.hostname = hostname; 8560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 8570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 8585006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getUseClientMode() { 85908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 86008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8625006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setUseClientMode(boolean mode) { 86308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 8655006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson "Could not change the mode after the initial handshake has begun."); 86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 86908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8705006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getWantClientAuth() { 87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8745006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public boolean getNeedClientAuth() { 87508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8785006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setNeedClientAuth(boolean need) { 87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8825006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setWantClientAuth(boolean want) { 88308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 88408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8865006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void sendUrgentData(int data) throws IOException { 8875006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 88808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8905006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 8915006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 89208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 89308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 8945006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void setSoTimeout(int timeoutMilliseconds) throws SocketException { 89572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom super.setSoTimeout(timeoutMilliseconds); 89672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.timeoutMilliseconds = timeoutMilliseconds; 89772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 89872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 8995006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public int getSoTimeout() throws SocketException { 90072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom return timeoutMilliseconds; 90108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 903331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 904331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 905331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 906331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 90772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException { 90872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.handshakeTimeoutMilliseconds = timeoutMilliseconds; 909331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 910331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 9115006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson @Override public void close() throws IOException { 9125006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 91508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 9165006f3bedbfd19dc905416bbf28bb0e95807f845Jesse Wilson // prevent further attempts to start handshake 91708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 918f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 920f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 92108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 92290ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 92508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) super.close(); 92608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 928f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 92908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 93008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 93358a44774b954fed596ee22307a231de783ea8121Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 93408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 93508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 93608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (writeLock) { 93708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (readLock) { 93808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 93908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // Shut down the SSL connection, per se. 94008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 94108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 942ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 943a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 944a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes this); 94508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 94686c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom } catch (IOException ignored) { 94708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 94886c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * Note that although close() can throw 94986c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * IOException, the RI does not throw if there 95086c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * is problem sending a "close notify" which 95186c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * can happen if the underlying socket is closed. 95208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 95306327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } finally { 95406327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom /* 95506327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * Even if the above call failed, it is still safe to free 95606327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * the native structs, and we need to do so lest we leak 95706327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom * memory. 95806327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom */ 95906327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom free(); 96006327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom 96106327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (socket != this) { 96206327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (autoClose && !socket.isClosed()) { 96306327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom socket.close(); 96406327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 96506327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } else { 96606327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom if (!super.isClosed()) { 96706327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom super.close(); 96806327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 96906327ec5e153c05a0e50df73093136d329038dafBrian Carlstrom } 97008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 976f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 977f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 978f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 979f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 980f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 981f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 982fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 983f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 98408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 9851990574e420184f3ad43400171f624dad44700d8Brian Carlstrom @Override protected void finalize() throws Throwable { 9861990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 9871990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 9881990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 9891990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 9901990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 9911990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 9921990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 9931990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 9941990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 9951990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 9961990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 9971990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 9981990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 9991990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 10001990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 10011990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 10021990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 1003f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 1004f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 1005f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 10061990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 10071990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 10081990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 10091990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 101008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 10110648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey 10120648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey @Override 10130648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 10140648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey if (socket == this) { 10150648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return super.getFileDescriptor$(); 10160648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } else { 10170648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey return socket.getFileDescriptor$(); 10180648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 10190648ecb2d61dbe9dcf30ca39c366efd20266bfb3Jeff Sharkey } 1020721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1021721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 1022721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Returns the protocol agreed upon by client and server, or null if no 1023721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocol was agreed upon. 1024721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1025721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public byte[] getNpnSelectedProtocol() { 1026263808a68e1538db41196065830107991e9f974aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 1027721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 1028721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson 1029721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson /** 1030721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * Sets the list of protocols this peer is interested in. If null no 1031721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * protocols will be used. 1032721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * 1033721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * @param npnProtocols from SSL_select_next_proto, "vector of 8-bit, length 1034721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * prefixed byte strings. The length byte itself is not included in the 1035721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * length. A byte string of length 0 is invalid. No byte string may be 1036721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson * truncated. 1037721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson */ 1038721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 1039721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson this.npnProtocols = npnProtocols; 1040721140f48732cec475e33af1e780fd325d1f8f6eJesse Wilson } 104108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 1042