OpenSSLSocketImpl.java revision a6d7bdeb041f42efd0cb441dea270b07debde421
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; 2190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstromimport 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; 37f7923f6b146ae1a750fb733cf03f9db27e68b5dacrazybobimport java.util.concurrent.atomic.AtomicInteger; 3808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport java.util.logging.Logger; 3908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 4008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 4108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLException; 42edc307bd5a7cf750852b9083ba203ba1c24fcdaeBrian Carlstromimport javax.net.ssl.SSLHandshakeException; 4308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Projectimport javax.net.ssl.SSLSession; 44fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstromimport javax.net.ssl.X509TrustManager; 4598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstromimport javax.security.auth.x500.X500Principal; 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> 5108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 52f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * later, for example in the package.html or a separate reference document. 530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <p> 540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * Extensions to SSLSocket include: 550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <ul> 560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>handshake timeout 570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>compression methods 580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>session tickets 590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * <li>Server Name Indication 600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * </ul> 6108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 62f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrompublic class OpenSSLSocketImpl 63f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom extends javax.net.ssl.SSLSocket 6498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 6590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom 66f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private int sslNativePointer; 6708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private InputStream is; 6808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OutputStream os; 6908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private final Object handshakeLock = new Object(); 70f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object readLock = new Object(); 71f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private final Object writeLock = new Object(); 72cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private SSLParametersImpl sslParameters; 732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledProtocols; 742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private String[] enabledCipherSuites; 750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private String[] enabledCompressionMethods; 760b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private boolean useSessionTickets; 770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom private String hostname; 7808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private OpenSSLSessionImpl sslSession; 7990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private final Socket socket; 8008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean autoClose; 8108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private boolean handshakeStarted = false; 82f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom private final CloseGuard guard = CloseGuard.get(); 832828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 842828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 852828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Not set to true until the update from native that tells us the 862828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 872828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * before the handshake is completely done due to 882828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * handshake_cutthrough support. 892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 902828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private boolean handshakeCompleted = false; 912828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 9208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 9372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 9472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom /** 9572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 9672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * write for non-wrapped sockets. Note that 9772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 9872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 9972721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom */ 10072721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int timeoutMilliseconds = 0; 10172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 10272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 1036e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private String wrappedHost; 1046e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom private int wrappedPort; 10508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 10608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 10708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Class constructor with 1 parameter 10808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 10908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param sslParameters Parameters for the SSL 11008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * context 11108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 11208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 113cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 11490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 115f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 11608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 11708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 11808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 1192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Create an OpenSSLSocketImpl from an OpenSSLServerSocketImpl 1202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * 1212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @param sslParameters Parameters for the SSL 1222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * context 1232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @throws IOException if network fails 1242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 125cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 1262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 1270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCipherSuites, 1280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 12990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 1300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods); 1312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 1322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 1332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 13408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Class constructor with 3 parameters 13508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 13608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 13708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws java.net.UnknownHostException host not defined 13808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 139cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 14090ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 14108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port); 14290ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 143f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 14408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 14508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 14608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 14708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Class constructor with 3 parameters: 1st is InetAddress 14808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 14908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 15008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws java.net.UnknownHostException host not defined 15108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 152cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 15390ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 15408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port); 15590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 156f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 15708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 15808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 15908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 16008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 16108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Class constructor with 5 parameters: 1st is host 16208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 16308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 16408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws java.net.UnknownHostException host not defined 16508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 166c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, 167c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 168cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom SSLParametersImpl sslParameters) 16990ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 17008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(host, port, clientAddress, clientPort); 17190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 172f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 17308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 17408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 17508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 17608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Class constructor with 5 parameters: 1st is InetAddress 17708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 17808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 17908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws java.net.UnknownHostException host not defined 18008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 18108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 182c7eac25a7d55812eaaecd8a8a5cdaac3a28b2bf5Brian Carlstrom InetAddress clientAddress, int clientPort, 183cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom SSLParametersImpl sslParameters) 18490ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom throws IOException { 18508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super(address, port, clientAddress, clientPort); 18690ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom this.socket = this; 187f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 18808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 18908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 19008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 19108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Constructor with 5 parameters: 1st is socket. Enhances an existing socket 1926e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom * with SSL functionality. Invoked via OpenSSLSocketImplWrapper constructor. 19308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 19408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IOException if network fails 19508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 19608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 197cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 19808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.socket = socket; 1996e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedHost = host; 2006e0361de414915ae9929f55f6a8e0266a67506efBrian Carlstrom this.wrappedPort = port; 20108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project this.autoClose = autoClose; 202f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom init(sslParameters); 20372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 20472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // this.timeout is not set intentionally. 20572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 20672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom // to wrapped socket 207f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 208f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 209f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 210f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * Initialize the SSL socket and set the certificates for the 211f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * future handshaking. 212f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 213cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 2142828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom init(sslParameters, 2152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom NativeCrypto.getSupportedProtocols(), 2160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom NativeCrypto.getDefaultCipherSuites(), 2170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom NativeCrypto.getDefaultCompressionMethods()); 218f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 219f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 220f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom /** 2212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Initialize the SSL socket and set the certificates for the 2222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * future handshaking. 223f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom */ 224cbbd49c29da3e87cb7775ba789a0211cba0b909fBrian Carlstrom private void init(SSLParametersImpl sslParameters, 2252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom String[] enabledProtocols, 2260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCipherSuites, 2270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 2282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.sslParameters = sslParameters; 2292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledProtocols = enabledProtocols; 2302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 2310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.enabledCompressionMethods = enabledCompressionMethods; 23208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 23308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 23408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 23508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Gets the suitable session reference from the session cache container. 23608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 23708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return OpenSSLSessionImpl 23808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 2392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 24008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (super.getInetAddress() == null || 24108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostAddress() == null || 24208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostName() == null) { 24308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return null; 24408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 24561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession( 24608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getInetAddress().getHostName(), 24708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.getPort()); 24861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (session == null) { 24961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 25061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 25161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 25261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String protocol = session.getProtocol(); 25361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean protocolFound = false; 25461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 25561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (protocol.equals(enabledProtocol)) { 25661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom protocolFound = true; 25761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 25861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 25961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 26061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!protocolFound) { 26161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 26261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 26361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom 26461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom String cipherSuite = session.getCipherSuite(); 26561b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom boolean cipherSuiteFound = false; 26661b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 26761b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 26861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom cipherSuiteFound = true; 26961b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom break; 27061b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 27161b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 27261b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom if (!cipherSuiteFound) { 27361b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return null; 27461b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom } 27598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 2760b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom String compressionMethod = session.getCompressionMethod(); 2770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom boolean compressionMethodFound = false; 2780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom for (String enabledCompressionMethod : enabledCompressionMethods) { 2790b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom if (compressionMethod.equals(enabledCompressionMethod)) { 2800b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom compressionMethodFound = true; 2810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom break; 2820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2830b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2840b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom if (!compressionMethodFound) { 2850b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return null; 2860b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 2870b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 28861b2ada13329b7d1698f6c706b31077a67fbac2dBrian Carlstrom return session; 28908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 29008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 29108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 29208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Ensures that logger is lazily loaded. The outer class seems to load 29308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * before logging is ready. 29408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 29508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project static class LoggerHolder { 296f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom static final Logger logger = Logger.getLogger(OpenSSLSocketImpl.class.getName()); 29708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 29808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 29908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 30008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Starts a TLS/SSL handshake on this connection using some native methods 30108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * from the OpenSSL library. It can negotiate new encryption keys, change 30208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * cipher suites, or initiate a new session. The certificate chain is 30308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * verified if the correspondent property in java.Security is set. All 304f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * listeners are notified at the end of the TLS/SSL handshake. 30508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 30608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> if network fails 30708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 3080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 3092828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void startHandshake() throws IOException { 3102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom startHandshake(true); 3112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 3122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 3132828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 314a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom * Checks whether the socket is closed, and throws an exception. 315a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom * 316a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom * @throws SocketException 317a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom * if the socket is closed. 318a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom */ 319a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom private void checkOpen() throws SocketException { 320a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom if (isClosed()) { 321a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom throw new SocketException("Socket is closed"); 322a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 323a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom } 324a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom 325a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom /** 3262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * Perform the handshake 3272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @param full If true, disable handshake cutthrough for a fully synchronous handshake 3282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 3292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public synchronized void startHandshake(boolean full) throws IOException { 33008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 3317b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 33208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 33308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 33408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 33508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 33608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 33708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 33808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 33998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 34098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 34198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 34298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (secureRandom == null) { 34398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 34498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } else { 34598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 34698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 34798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 34898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 34998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 35098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom final int sslCtxNativePointer = (client) ? 35198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 35298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 35398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 354fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this.sslNativePointer = 0; 355fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean exception = true; 356fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 357fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 358fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.open("close"); 35998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 360fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup server certificates and private keys. 361fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // clients will receive a call back to request certificates. 362fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!client) { 363d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 364d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 365aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 366aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom continue; 367aeb3b48a69c2294ca657acd3e8b94c9879d78b61Brian Carlstrom } 368ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 369d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom if (keyType != null) { 370d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom keyTypes.add(keyType); 371d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 372d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom } 373d5eeb213edc60ad4c33f1cec353899ab0957dd25Brian Carlstrom for (String keyType : keyTypes) { 374fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 375fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 376fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom null, 377fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom this)); 378fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 379fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException(e); 380fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 381f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 38298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 38398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 384fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 385fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 386fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (enabledCompressionMethods.length != 0) { 387fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.setEnabledCompressionMethods(sslNativePointer, 388fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enabledCompressionMethods); 389fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 390fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (useSessionTickets) { 391fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 392fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 393fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (hostname != null) { 394fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 395fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 3962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 397fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 398fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 399fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 400fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom enableSessionCreation); 4012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 4022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 403fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom AbstractSessionContext sessionContext; 404fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom OpenSSLSessionImpl session; 405fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 406fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // look for client session to reuse 407fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 408fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = clientSessionContext; 409fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom session = getCachedClientSession(clientSessionContext); 410fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (session != null) { 411fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 412fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom session.sslSessionNativePointer); 413fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 414f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } else { 415fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 416fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom session = null; 417f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 41898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 419fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // setup peer certificate verification 420fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client) { 421fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // TODO support for anonymous cipher would require us to 422fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // conditionally use SSL_VERIFY_NONE 423fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 424fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // needing client auth takes priority... 425fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom boolean certRequested = false; 426fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 427fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 428fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 429fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 430fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 431fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... over just wanting it... 432fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 433fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 434fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 435fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = true; 436fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 437fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 438fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom certRequested = false; 439fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 440fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 441fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (certRequested) { 442fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 443fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 444fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (issuers != null && issuers.length != 0) { 445fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[][] issuersBytes; 446fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 447fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 448fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateEncodingException e) { 449fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IOException("Problem encoding principals", e); 450fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 451fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 452f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 453f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 454f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom } 455f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 456fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (client && full) { 457fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 458fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 459fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 460fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 461f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 462fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Temporarily use a different timeout for the handshake process 463fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int savedTimeoutMilliseconds = getSoTimeout(); 464fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 465fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 466fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 4672828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 468fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom int sslSessionNativePointer; 469fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom try { 470a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 471a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes socket.getFileDescriptor$(), this, getSoTimeout(), client); 472fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } catch (CertificateException e) { 473d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 474d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom wrapper.initCause(e); 475d16f39c2d50864d40774c838e305c9510445bfe3Brian Carlstrom throw wrapper; 4762828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 477fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 478fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 479fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (sslSession != null) { 480fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 481fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom LoggerHolder.logger.fine("Reused cached session for " 482fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom + getInetAddress() + "."); 483fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 484fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 485fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (!enableSessionCreation) { 486fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 487fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 488fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 489fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] localCertificates 490fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 491fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom X509Certificate[] peerCertificates 492fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 493fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (wrappedHost == null) { 494fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 495fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom localCertificates, peerCertificates, 496fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom super.getInetAddress().getHostName(), 497fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom super.getPort(), sessionContext); 498fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } else { 499fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, 500fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom localCertificates, peerCertificates, 501fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom wrappedHost, wrappedPort, 502fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext); 503fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 504fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 505fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 506fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom sessionContext.putSession(sslSession); 507fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 508fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom LoggerHolder.logger.fine("Created new session for " 509fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom + getInetAddress().getHostName() + "."); 510f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 511fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom 512fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // Restore the original timeout now that the handshake is complete 513fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 514fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom setSoTimeout(savedTimeoutMilliseconds); 515331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 51608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 517fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 518fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (handshakeCompleted) { 519fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom notifyHandshakeCompletedListeners(); 520fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 521f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 522fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom exception = false; 523fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } finally { 524aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom // on exceptional exit, treat the socket as closed 525fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom if (exception) { 526aef0b218983e04bc05ffb5746b4f452725f704b7Brian Carlstrom close(); 527fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom } 52808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 529e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 53008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 531e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom /** 532e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * Return a possibly null array of X509Certificates given the 533e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom * possibly null array of DER encoded bytes. 534e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom */ 53590ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 536e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (certificatesBytes == null) { 537e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 538e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 539e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 540e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 541e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 542e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 543e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 544e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return null; 545e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 546e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 547e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return certificates; 5482828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 54908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 550f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 55198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom if (alias == null) { 55298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom return; 55398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 55498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 55598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 5561f42e0a4d7d28b8fc20833e0be05ad17dcfa8ea0Brian Carlstrom byte[] privateKeyBytes = privateKey.getEncoded(); 55798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 55898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 55998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 560f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 56198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 56298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 56398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // checks the last installed private key and certificate, 56498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom // so need to do this once per loop iteration 56598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 56698ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 56798ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 56898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom /** 56998ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 57098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom * invoked via JNI from client_cert_cb 57198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom */ 57298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 573f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom throws CertificateEncodingException, SSLException { 57498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 57598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 57698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 577ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 57898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 57998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom 58098a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom X500Principal[] issuers; 58198a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom if (asn1DerEncodedPrincipals == null) { 58298a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = null; 58398a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } else { 58498a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 58598a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 58698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 58798a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 58898a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom } 58998a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 59098ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom } 59198ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom 59208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 59398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 5942828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * invoked via JNI from info_callback 59508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 5962828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom public void handshakeCompleted() { 5972828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom handshakeCompleted = true; 59808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 5992828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // If sslSession is null, the handshake was completed during 6002828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 6012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // later read operation. That means we do not need to fixup 6022828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // the SSLSession and session cache or notify 6032828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // HandshakeCompletedListeners, it will be done in 6042828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // startHandshake. 6052828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (sslSession == null) { 6062828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return; 6072828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 60808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 6092828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // reset session id from the native pointer and update the 6102828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // appropriate cache. 6112828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom sslSession.resetId(); 6122828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom AbstractSessionContext sessionContext = 6132828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom (sslParameters.getUseClientMode()) 6142828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom ? sslParameters.getClientSessionContext() 6152828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom : sslParameters.getServerSessionContext(); 61608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sessionContext.putSession(sslSession); 6172828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 6182828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // let listeners know we are finally done 6192828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom notifyHandshakeCompletedListeners(); 6202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 6212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 6222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom private void notifyHandshakeCompletedListeners() { 6232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 6242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // notify the listeners 6252828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom HandshakeCompletedEvent event = 6262828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 6272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 6282828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom try { 6292828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom listener.handshakeCompleted(event); 6302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (RuntimeException e) { 631371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // The RI runs the handlers in a separate thread, 632371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // which we do not. But we try to preserve their 633371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // behavior of logging a problem and not killing 634371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // the handshaking thread just because a listener 635371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom // has a problem. 636371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom Thread thread = Thread.currentThread(); 637371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 6382828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 6392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 6402828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } 64108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 64208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 64308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 64498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom * Implementation of NativeCrypto.SSLHandshakeCallbacks 645f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * 64698a43fda08c8dae8b308fb91756fb121ec1c8ac2Brian Carlstrom * @param bytes An array of ASN.1 DER encoded certficates 6472828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @param authMethod auth algorithm name 64808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 6492828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * @throws CertificateException if the certificate is untrusted 65008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 65108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @SuppressWarnings("unused") 65298ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom public void verifyCertificateChain(byte[][] bytes, String authMethod) 65398ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom throws CertificateException { 65408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 655371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom if (bytes == null || bytes.length == 0) { 656371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom throw new SSLException("Peer sent no certificate"); 657371c4e83bab807ee4fd7ffab9d36a5f31a55dc46Brian Carlstrom } 6582828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 6592828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 6606e24f16869f652c340bb973069ec5fec21317137Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 66108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6622828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 6632828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom if (client) { 66498ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 66598ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom authMethod); 6662828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } else { 667ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 66898ec0ef4090e2e7a2f98a9171140e549e2220cacBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 669ea8732bc2631141874302bc25ee2795a89f4922fBrian Carlstrom authType); 67008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 6712828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom 6722828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (CertificateException e) { 6732828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw e; 6742828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom } catch (Exception e) { 6752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw new RuntimeException(e); 67608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 67808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 67908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 68008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Returns an input stream for this SSL socket using native calls to the 68108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * OpenSSL library. 68208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 68308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return: an input stream for reading bytes from this socket. 68408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws: <code>IOException</code> if an I/O error occurs when creating 68508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * the input stream, the socket is closed, the socket is not 68608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * connected, or the socket input has been shutdown. 68708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 6880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 68908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public InputStream getInputStream() throws IOException { 690a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 691f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 69208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (is == null) { 69308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project is = new SSLInputStream(); 69408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 69608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return is; 69708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 69908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 70008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 70108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Returns an output stream for this SSL socket using native calls to the 70208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * OpenSSL library. 70308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 70408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return an output stream for writing bytes to this socket. 70508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> if an I/O error occurs when creating 70608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * the output stream, or no connection to the socket exists. 70708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 70908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public OutputStream getOutputStream() throws IOException { 710a2770d6e45dd961b24543ffbde7fa41bd548e7e8Brian Carlstrom checkOpen(); 711f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (this) { 71208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (os == null) { 71308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project os = new SSLOutputStream(); 71408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 71608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return os; 71708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 71908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7202828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 7212828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * This method is not supported for this SSLSocket implementation 7222828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * because reading from an SSLSocket may involve writing to the 7232828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * network. 7242828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 7250b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 72608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void shutdownInput() throws IOException { 7272828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw new UnsupportedOperationException(); 72808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 72908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 7302828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom /** 7312828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * This method is not supported for this SSLSocket implementation 7322828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * because writing to an SSLSocket may involve reading from the 7332828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom * network. 7342828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom */ 7350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 73608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void shutdownOutput() throws IOException { 7372828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom throw new UnsupportedOperationException(); 73808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 73908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 74008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 74108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides input data stream functionality 74208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 74308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * read data received via SSL protocol. 74408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 74508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLInputStream extends InputStream { 74608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLInputStream() throws IOException { 74708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 74808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 74908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * SSLInputStream object will be created. 75008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7512828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 75208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 75308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 75408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 75508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 75608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * this operation can block until the data will be 75708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * available. 75808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return read value. 75908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> 76008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7610b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 76208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public int read() throws IOException { 763ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 764f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 7657b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 766a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read_byte(sslNativePointer, socket.getFileDescriptor$(), 767a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, getSoTimeout()); 76808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 76908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 77008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 77108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 77208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 77308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 77408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 7750b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 77697e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 777ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 778f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (readLock) { 7797b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 78097e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 78197e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 7827b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return 0; 7837b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 784a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 785a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 78608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 78908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 79008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 79108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This inner class provides output data stream functionality 79208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * for the OpenSSL native implementation. It is used to 79308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * write data according to the encryption parameters given in SSL context. 79408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 79508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project private class SSLOutputStream extends OutputStream { 79608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project SSLOutputStream() throws IOException { 79708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 79808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* Note: When startHandshake() throws an exception, no 799f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * SSLOutputStream object will be created. 80008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8012828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 80208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 80308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 80408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 80508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 80608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(int) 80708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 80908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void write(int b) throws IOException { 810ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 811f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 8127b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 813a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write_byte(sslNativePointer, socket.getFileDescriptor$(), 814a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, b); 81508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 81708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 81808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 81908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Method acts as described in spec for superclass. 82008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 82108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 82397e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 824ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 825f52606090f0f7160c2c7a85069959c1124151d79Brian Carlstrom synchronized (writeLock) { 8267b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom checkOpen(); 82797e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 82897e840f13f356fa77f9bf915e4b489df1feb4d80Elliott Hughes if (byteCount == 0) { 8297b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom return; 8307b155011296152295a987bc78f8dc7a3c5cc6ffbBrian Carlstrom } 831a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 832a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount); 83308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 83608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 83708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 83808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 83908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The SSL session used by this connection is returned. The SSL session 84008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * determines which cipher suite should be used by all connections within 84108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * that session and which identities have the session's client and server. 84208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method starts the SSL handshake. 84308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return the SSLSession. 84408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> if the handshake fails 84508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 84708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public SSLSession getSession() { 848e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom if (sslSession == null) { 849e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom try { 850e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom startHandshake(true); 851e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } catch (IOException e) { 852e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // return an invalid session with 853e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 854e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 855e247367fbd5d5b0451c3b3e61e6dba37f27d49e1Brian Carlstrom } 85608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 85708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslSession; 85808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 85908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 86008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 86108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Registers a listener to be notified that a SSL handshake 86208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * was successfully completed on this connection. 86308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IllegalArgumentException</code> if listener is null. 86408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8650b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 86608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void addHandshakeCompletedListener( 86708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 86808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 86908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 87008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 87208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners = new ArrayList(); 87308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project listeners.add(listener); 87508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 87608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 87708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 87808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The method removes a registered listener. 87908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IllegalArgumentException if listener is null or not registered 88008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 8810b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 88208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void removeHandshakeCompletedListener( 88308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project HandshakeCompletedListener listener) { 88408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listener == null) { 88508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 88608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 88708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (listeners == null) { 88808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 88908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 89008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 89108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!listeners.remove(listener)) { 89208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 89308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Provided listener is not registered"); 89408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 89508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 89608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 89708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 89808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Returns true if new SSL sessions may be established by this socket. 89908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 90008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return true if the session may be created; false if a session already 90108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * exists and must be resumed. 90208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 90408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public boolean getEnableSessionCreation() { 90508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getEnableSessionCreation(); 90608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 90708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 90808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 90908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Set a flag for the socket to inhibit or to allow the creation of a new 91008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * SSL sessions. If the flag is set to false, and there are no actual 91108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * sessions to resume, then there will be no successful handshaking. 91208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 91308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param flag true if session may be created; false 91408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * if a session already exists and must be resumed. 91508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 91708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void setEnableSessionCreation(boolean flag) { 91808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setEnableSessionCreation(flag); 91908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 92008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 92108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 92208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The names of the cipher suites which could be used by the SSL connection 92308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * are returned. 92408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return an array of cipher suite names 92508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 92708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public String[] getSupportedCipherSuites() { 928f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 92908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 93008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 93108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 93208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The names of the cipher suites that are in use in the actual the SSL 93308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * connection are returned. 93408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 93508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return an array of cipher suite names 93608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 93808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public String[] getEnabledCipherSuites() { 9392828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledCipherSuites.clone(); 94008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 94108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 94208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 94308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method enables the cipher suites listed by 94408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * getSupportedCipherSuites(). 94508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 94608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param suites names of all the cipher suites to 94708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * put on use 94808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IllegalArgumentException when one or more of the 94908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * ciphers in array suites are not supported, or when the array 95008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * is null. 95108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 95308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void setEnabledCipherSuites(String[] suites) { 9542828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 95508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 95608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 95708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 95808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The names of the protocols' versions that may be used on this SSL 95908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * connection. 96008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return an array of protocols names 96108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 9620b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 96308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public String[] getSupportedProtocols() { 964f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 96508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 96608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 96708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 96808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * The names of the protocols' versions that are in use on this SSL 96908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * connection. 970f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * 97108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return an array of protocols names 97208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 97308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 97408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public String[] getEnabledProtocols() { 9752828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom return enabledProtocols.clone(); 97608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 97708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 97808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 97908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method enables the protocols' versions listed by 98008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * getSupportedProtocols(). 981f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * 9820b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param protocols The names of all the protocols to allow 983f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom * 98408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IllegalArgumentException when one or more of the names in the 98508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * array are not supported, or when the array is null. 98608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 98708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project @Override 9880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setEnabledProtocols(String[] protocols) { 9892828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 99008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 99108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 99208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 9930b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods that may be used on this SSL 9940b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * connection. 9950b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 9960b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 9970b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getSupportedCompressionMethods() { 9980b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return NativeCrypto.getSupportedCompressionMethods(); 9990b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10000b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10010b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10020b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * The names of the compression methods versions that are in use 10030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * on this SSL connection. 10040b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10050b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return an array of compression methods 10060b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10070b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String[] getEnabledCompressionMethods() { 10080b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return enabledCompressionMethods.clone(); 10090b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10100b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10110b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10120b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables the compression method listed by 10130b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * getSupportedCompressionMethods(). 10140b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param methods The names of all the compression methods to allow 10160b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10170b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @throws IllegalArgumentException when one or more of the names in the 10180b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * array are not supported, or when the array is null. 10190b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10200b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setEnabledCompressionMethods (String[] methods) { 10210b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 10220b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10230b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10240b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10250b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables session ticket support. 10260b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10270b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param useSessionTickets True to enable session tickets 10280b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10290b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 10300b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.useSessionTickets = useSessionTickets; 10310b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10320b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10330b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10340b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method gives true back if the SSL socket is set to client mode. 10350b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10360b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return true if the socket should do the handshaking as client. 10370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10380b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public boolean getUseSessionTickets() { 10390b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return useSessionTickets; 10400b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10410b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10420b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10430b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method enables Server Name Indication 10440b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10450b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 10460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10470b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setHostname(String hostname) { 10480b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom this.hostname = hostname; 10490b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10500b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10510b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 10520b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * This method returns the current SNI hostname 10530b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * 10540b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom * @return a host name if SNI is enabled, or null otherwise 10550b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom */ 10560b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public String getHostname() { 10570b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom return hostname; 10580b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom } 10590b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom 10600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom /** 106108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method gives true back if the SSL socket is set to client mode. 106208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 106308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return true if the socket should do the handshaking as client. 106408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 106508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public boolean getUseClientMode() { 106608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getUseClientMode(); 106708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 106808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 106908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 107008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method set the actual SSL socket to client mode. 107108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 107208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param mode true if the socket starts in client 107308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * mode 107408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws IllegalArgumentException if mode changes during 107508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * handshake. 107608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 10770b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 10780b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom public void setUseClientMode(boolean mode) { 107908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 108008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new IllegalArgumentException( 108108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Could not change the mode after the initial handshake has begun."); 108208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 108308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setUseClientMode(mode); 108408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 108508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 108608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 108708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Returns true if the SSL socket requests client's authentication. Relevant 108808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * only for server sockets! 108908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 109008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return true if client authentication is desired, false if not. 109108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 10920b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 109308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public boolean getWantClientAuth() { 109408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getWantClientAuth(); 109508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 109608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 109708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 109808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Returns true if the SSL socket needs client's authentication. Relevant 109908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * only for server sockets! 110008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 110108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @return true if client authentication is desired, false if not. 110208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11030b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 110408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public boolean getNeedClientAuth() { 110508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return sslParameters.getNeedClientAuth(); 110608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 110708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 110808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 110908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 111008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * server sockets! 111108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 111208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param need true if client authentication is 111308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * desired, false if not. 111408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11150b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 111608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void setNeedClientAuth(boolean need) { 111708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setNeedClientAuth(need); 111808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 111908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 112008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 112108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Sets the SSL socket to use client's authentication. Relevant only for 112208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * server sockets! Notice that in contrast to setNeedClientAuth(..) this 112308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * method will continue the negotiation if the client decide not to send 112408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * authentication credentials. 112508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 112608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param want true if client authentication is 112708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * desired, false if not. 112808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11290b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 113008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void setWantClientAuth(boolean want) { 113108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project sslParameters.setWantClientAuth(want); 113208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 113308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 113408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 113508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method is not supported for SSLSocket implementation. 113608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11370b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 113808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void sendUrgentData(int data) throws IOException { 113908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new SocketException( 114008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Method sendUrgentData() is not supported."); 114108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 114208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 114308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 114408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * This method is not supported for SSLSocket implementation. 114508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11460b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 114708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void setOOBInline(boolean on) throws SocketException { 114808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project throw new SocketException( 114908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project "Methods sendUrgentData, setOOBInline are not supported."); 115008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 115108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 115208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 115308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Set the read timeout on this socket. The SO_TIMEOUT option, is specified 115408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * in milliseconds. The read operation will block indefinitely for a zero 115508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * value. 115608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 115708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @param timeout the read timeout value 115808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws SocketException if an error occurs setting the option 115908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11600b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 116172721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom public void setSoTimeout(int timeoutMilliseconds) throws SocketException { 116272721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom super.setSoTimeout(timeoutMilliseconds); 116372721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.timeoutMilliseconds = timeoutMilliseconds; 116472721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom } 116572721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom 116672721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom @Override 116772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom public int getSoTimeout() throws SocketException { 116872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom return timeoutMilliseconds; 116908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 117008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1171331900211d05cd282141a3a50cb1db626f418b2cDan Egnor /** 1172331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * Set the handshake timeout on this socket. This timeout is specified in 1173331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * milliseconds and will be used only during the handshake process. 1174331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * 1175331900211d05cd282141a3a50cb1db626f418b2cDan Egnor * @param timeout the handshake timeout value 1176331900211d05cd282141a3a50cb1db626f418b2cDan Egnor */ 117772721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException { 117872721fe761a086800a0e119bf6766d6c1ead0d94Brian Carlstrom this.handshakeTimeoutMilliseconds = timeoutMilliseconds; 1179331900211d05cd282141a3a50cb1db626f418b2cDan Egnor } 1180331900211d05cd282141a3a50cb1db626f418b2cDan Egnor 118108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /** 118208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Closes the SSL socket. Once closed, a socket is not available for further 118308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * use anymore under any circumstance. A new socket must be created. 118408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * 118508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * @throws <code>IOException</code> if an I/O error happens during the 118608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * socket's closure. 118708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 11880b26b4367f0af550809c12ecea934723f16e7393Brian Carlstrom @Override 118908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project public void close() throws IOException { 119008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // TODO: Close SSL sockets using a background thread so they close 119108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // gracefully. 119208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 119308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (handshakeLock) { 119408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!handshakeStarted) { 11952828ed800862c0ed2cf2116cb986d6bf209e4f58Brian Carlstrom // prevent further attemps to start handshake 119608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project handshakeStarted = true; 1197f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 119808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 1199f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 120008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 120190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 120208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 120308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 120408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) super.close(); 120508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 120608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 1207f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom 120808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project return; 120908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 121008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 121108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 121258a44774b954fed596ee22307a231de783ea8121Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 121308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 121408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (this) { 121508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (writeLock) { 121608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project synchronized (readLock) { 121708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 121808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project // Shut down the SSL connection, per se. 121908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project try { 122008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (handshakeStarted) { 1221ed2760e0dea39695b164af6d07ea9860e7c1fa49Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 1222a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 1223a6d7bdeb041f42efd0cb441dea270b07debde421Elliott Hughes this); 122408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 122586c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom } catch (IOException ignored) { 122608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 122786c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * Note that although close() can throw 122886c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * IOException, the RI does not throw if there 122986c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * is problem sending a "close notify" which 123086c4c40d26570c38297cb78c47f437f79ca583b4Brian Carlstrom * can happen if the underlying socket is closed. 123108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 123208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 123308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 123408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project /* 123508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * Even if the above call failed, it is still safe to free 123608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * the native structs, and we need to do so lest we leak 123708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project * memory. 123808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project */ 1239f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom free(); 124008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 124190ed0ad55227df7a127054b25a43dbb6f6265a4bBrian Carlstrom if (socket != this) { 124208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (autoClose && !socket.isClosed()) 124308ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project socket.close(); 124408ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } else { 124508ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project if (!super.isClosed()) 124608ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project super.close(); 124708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 124808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 124908ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 125008ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 125108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 125208ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 1253f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom private void free() { 1254f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom if (sslNativePointer == 0) { 1255f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom return; 1256f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 1257f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1258f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom sslNativePointer = 0; 1259fce103dcb8270a7a4daa08c975e7e0bddf4ec67eBrian Carlstrom guard.close(); 1260f0c622f8ceb1fa261b67e3b8654f58254a12729cBrian Carlstrom } 126108ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project 12621990574e420184f3ad43400171f624dad44700d8Brian Carlstrom @Override protected void finalize() throws Throwable { 12631990574e420184f3ad43400171f624dad44700d8Brian Carlstrom try { 12641990574e420184f3ad43400171f624dad44700d8Brian Carlstrom /* 12651990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * Just worry about our own state. Notably we do not try and 12661990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * close anything. The SocketImpl, either our own 12671990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 12681990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 12691990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * if you want to do that, properly close the socket yourself. 12701990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * 12711990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 12721990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 12731990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * finalizer runs first and closes the socket. However, in the 12741990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 12751990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 12761990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * underlying socket BIOs still have the old file descriptor 12771990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * and will write the close notify to some unsuspecting 12781990574e420184f3ad43400171f624dad44700d8Brian Carlstrom * reader. 12791990574e420184f3ad43400171f624dad44700d8Brian Carlstrom */ 1280f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom if (guard != null) { 1281f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom guard.warnIfOpen(); 1282f014c05bd5f8dbda1f5774755aefe54d546a297bBrian Carlstrom } 12831990574e420184f3ad43400171f624dad44700d8Brian Carlstrom free(); 12841990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } finally { 12851990574e420184f3ad43400171f624dad44700d8Brian Carlstrom super.finalize(); 12861990574e420184f3ad43400171f624dad44700d8Brian Carlstrom } 128708ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project } 128808ecc8c0f00f1a7f2258c569187e36606ed73045The Android Open Source Project} 1289