OpenSSLSocketImpl.java revision f52b35a5bc22f53b663ea22954135b69f8636bf4
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrickimport dalvik.system.BlockGuard; 20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 213267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkeyimport java.io.FileDescriptor; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 286df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey; 296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom; 3012cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 34a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 356c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.HashSet; 366c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.Set; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException; 402915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstromimport javax.net.ssl.SSLHandshakeException; 41aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.SSLProtocolException; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 43f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager; 44059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 45638000042da777f6d628d88dadde957c52597710Brian Carlstromimport libcore.io.Streams; 46adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 494559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 504559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This class only supports SSLv3 and TLSv1. This should be documented elsewhere 52ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * later, for example in the package.html or a separate reference document. 534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include: 554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul> 564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout 574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>compression methods 584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets 594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication 604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul> 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 62ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl 63ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom extends javax.net.ssl.SSLSocket 646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 65df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom 66ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private int sslNativePointer; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream is; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream os; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Object handshakeLock = new Object(); 70ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object readLock = new Object(); 71ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object writeLock = new Object(); 726812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private SSLParametersImpl sslParameters; 73bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String[] enabledCompressionMethods; 764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean useSessionTickets; 774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String hostname; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 79df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final Socket socket; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 8212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 83bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 84bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 85bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 86bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 93a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 94a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom /** 95a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 96a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * write for non-wrapped sockets. Note that 97a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 98a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom */ 100a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int timeoutMilliseconds = 0; 101a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 102a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 103a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 104a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1066812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 107df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 108ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 109adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1116812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 112bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCipherSuites, 1144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 115df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 1164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites, enabledCompressionMethods); 117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 118bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 1196812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 120df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 122df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 123ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1266812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 127df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 129df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 130ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1340c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1360c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 138df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 139ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1430c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1440c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 146df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 147ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1510c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1520c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * OpenSSLSocketImplWrapper constructor. 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 1556812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 157a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 158a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 160ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 161a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 162a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // this.timeout is not set intentionally. 163a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 164a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // to wrapped socket 165ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 166ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 167ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 168ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 169ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 170ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1716812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 172bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 173bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom NativeCrypto.getSupportedProtocols(), 1744559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom NativeCrypto.getDefaultCipherSuites(), 1754559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom NativeCrypto.getDefaultCompressionMethods()); 176ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 177ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 178ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 179bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 180bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 181ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1826812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters, 183bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1844559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCipherSuites, 1854559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String[] enabledCompressionMethods) throws IOException { 186bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 187bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 188bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 1894559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.enabledCompressionMethods = enabledCompressionMethods; 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 195bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 19627c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson String hostName = getPeerHostName(); 19727c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson int port = getPeerPort(); 19827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (hostName == null) { 199adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 20127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 2029acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2039acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2049acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2059acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2069acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2079acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2089acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2099acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2109acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2119acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2129acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2139acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2149acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2159acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2169acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2179acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2189acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2199acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2209acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2229acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2239acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2269acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2289acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom String compressionMethod = session.getCompressionMethod(); 23127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (!compressionMethod.equals(NativeCrypto.SUPPORTED_COMPRESSION_METHOD_NULL)) { 23227c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson boolean compressionMethodFound = false; 23327c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson for (String enabledCompressionMethod : enabledCompressionMethods) { 23427c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (compressionMethod.equals(enabledCompressionMethod)) { 23527c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson compressionMethodFound = true; 23627c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson break; 23727c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 23827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 23927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (!compressionMethodFound) { 24027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson return null; 2414559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 2424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 2434559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 2449acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 245adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Starts a TLS/SSL handshake on this connection using some native methods 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * from the OpenSSL library. It can negotiate new encryption keys, change 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * cipher suites, or initiate a new session. The certificate chain is 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * verified if the correspondent property in java.Security is set. All 252ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * listeners are notified at the end of the TLS/SSL handshake. 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 2544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 255bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void startHandshake() throws IOException { 256bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom startHandshake(true); 257bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 258bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 2595f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom private void checkOpen() throws SocketException { 2605f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom if (isClosed()) { 2615f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom throw new SocketException("Socket is closed"); 2625f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2635f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2645f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom 2655f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom /** 266bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Perform the handshake 2670c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * 268bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * @param full If true, disable handshake cutthrough for a fully synchronous handshake 269bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 270bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public synchronized void startHandshake(boolean full) throws IOException { 271adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 27212e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 273adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 274adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 275adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 276adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 277adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 278adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 279adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2806df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 2816df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 2826df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 2836df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 2846df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 2856df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 2866df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 2876df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 2886df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2896df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 2906df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2916df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int sslCtxNativePointer = (client) ? 2926df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 2936df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 2946df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 295f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this.sslNativePointer = 0; 296f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean exception = true; 297f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 298f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 299f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 3006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 301f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup server certificates and private keys. 302f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // clients will receive a call back to request certificates. 303f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!client) { 3046c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 3056c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 306ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 307ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom continue; 308ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom } 3094ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 3106c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom if (keyType != null) { 3116c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom keyTypes.add(keyType); 3126c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3136c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3146c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String keyType : keyTypes) { 315f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 316f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 317f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom null, 318f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this)); 319f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 320f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException(e); 321f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 322ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3236df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3246df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 325f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 326f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 327f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (enabledCompressionMethods.length != 0) { 328f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCompressionMethods(sslNativePointer, 329f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enabledCompressionMethods); 330f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 331f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (useSessionTickets) { 332f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 333f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 334f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (hostname != null) { 335f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 336f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 337bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 338f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 339f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 340f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 341f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enableSessionCreation); 342bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 343bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 344f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom AbstractSessionContext sessionContext; 345f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 346f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // look for client session to reuse 347f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 348f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = clientSessionContext; 3490c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson OpenSSLSessionImpl session = getCachedClientSession(clientSessionContext); 350f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (session != null) { 351f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 352f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom session.sslSessionNativePointer); 353f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 354ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 355f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 356ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 357059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 358f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup peer certificate verification 359f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 360f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // TODO support for anonymous cipher would require us to 361f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // conditionally use SSL_VERIFY_NONE 362f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 363f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // needing client auth takes priority... 3640c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson boolean certRequested; 365f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 366f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 367f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 368f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 369f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 370f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... over just wanting it... 371f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 372f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 373f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 374f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 375f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 376f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 377f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = false; 378f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 379f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 380f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (certRequested) { 381f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 382f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 383f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (issuers != null && issuers.length != 0) { 384f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[][] issuersBytes; 385f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 386f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 387f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 388f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException("Problem encoding principals", e); 389f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 390f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 391ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 392ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 393ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 394ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 395f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client && full) { 396f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // we want to do a full synchronous handshake, so turn off cutthrough 397f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_mode(sslNativePointer, 398f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 399f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 400ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 401f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Temporarily use a different timeout for the handshake process 402f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int savedTimeoutMilliseconds = getSoTimeout(); 403f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 405f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 406bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 407f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int sslSessionNativePointer; 408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 4095d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 4105d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes socket.getFileDescriptor$(), this, getSoTimeout(), client); 411f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateException e) { 41254c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 41354c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom wrapper.initCause(e); 41454c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom throw wrapper; 415bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 417f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 418f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslSession != null) { 419f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 420f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 422f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 423f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 424f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 425f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 426f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] localCertificates 427f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 428f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] peerCertificates 429f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 43027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 43127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 432f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 433f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 434f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext.putSession(sslSession); 435f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 436ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 437f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 438f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Restore the original timeout now that the handshake is complete 439f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 440f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(savedTimeoutMilliseconds); 4419d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 442adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 443f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 444f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 445f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom notifyHandshakeCompletedListeners(); 446f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 447ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 448f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom exception = false; 449aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } catch (SSLProtocolException e) { 450aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom throw new SSLHandshakeException(e); 451f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } finally { 4528a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom // on exceptional exit, treat the socket as closed 453f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (exception) { 4548a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom close(); 455f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 457df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 458adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 45927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson private String getPeerHostName() { 460f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (wrappedHost != null) { 461f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return wrappedHost; 462f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 463f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom InetAddress inetAddress = super.getInetAddress(); 464f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (inetAddress != null) { 465f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return inetAddress.getHostName(); 466f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 467f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return null; 46827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 46927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 47027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson private int getPeerPort() { 47127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 47227c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 47327c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 474df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom /** 475df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * Return a possibly null array of X509Certificates given the 476df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * possibly null array of DER encoded bytes. 477df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom */ 478df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 479df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (certificatesBytes == null) { 480df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 481df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 482df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 483df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 484df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 485df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 486df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 487df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 488df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 489df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 490df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return certificates; 491bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 492adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 493ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 4946df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 4956df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 4966df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 498aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (privateKey == null) { 499aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 500aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 5016df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 502aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (certificates == null) { 503aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 504aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 505aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom 506aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom byte[] privateKeyBytes = privateKey.getEncoded(); 507ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 508aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 5096df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 5106df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5116df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 5126df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 5136df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 5146df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5156df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5160c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 517059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 518ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 519059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 520059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 521059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 5224ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 523059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 524059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 525059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 526059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 527059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 528059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 529059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 530059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 531059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 532059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 533059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 534059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 5356df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5366df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5370c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 538bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 539bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 540adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 541bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 542bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5430c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // later read operation. That means we do not need to fix up 544bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 545bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 546bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 547bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 548bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 549bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 551bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 552bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 553bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 554bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 555bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 556bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 557bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 558adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 559bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 560bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 561bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 562bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 563bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 564bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 566bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 567bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 568bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 569bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 570bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 571bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 572bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 573e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 574e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 575e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 576e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 577e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 578e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 579e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 580bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 581bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 582bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 583adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 584adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5850c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5860c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 5876df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 588adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 589e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 590e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 591e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 592bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 593bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 594a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 595adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 596bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 597bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 5986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkServerTrusted(peerCertificateChain, 5996df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom authMethod); 600bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 6014ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 6026df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 6034ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom authType); 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 605bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 606bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 607bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 6081b3c5388d0fffde4392007eb1b0be011a5dfae82Brian Carlstrom } catch (RuntimeException e) { 6091b3c5388d0fffde4392007eb1b0be011a5dfae82Brian Carlstrom throw e; 610bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 611bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw new RuntimeException(e); 612adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 613adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 614adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6150c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public InputStream getInputStream() throws IOException { 6165f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 617ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6260c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public OutputStream getOutputStream() throws IOException { 6275f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 628ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 637bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 648bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 660638000042da777f6d628d88dadde957c52597710Brian Carlstrom return Streams.readSingleByte(this); 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6674559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 668a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 6695900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 670ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 67112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 672a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 673a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 67412e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return 0; 67512e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 6765d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 6775d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* Note: When startHandshake() throws an exception, no 691ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 693bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom OpenSSLSocketImpl.this.startHandshake(false); 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 701638000042da777f6d628d88dadde957c52597710Brian Carlstrom public void write(int oneByte) throws IOException { 702638000042da777f6d628d88dadde957c52597710Brian Carlstrom Streams.writeSingleByte(this, oneByte); 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 710a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 7115900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 712ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 71312e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 714a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 715a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 71612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return; 71712e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 7185d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 7195d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount); 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 724adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7250c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public SSLSession getSession() { 726df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (sslSession == null) { 727df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 728df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom startHandshake(true); 729df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 730df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // return an invalid session with 731df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 732df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 733df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7380c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void addHandshakeCompletedListener( 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 7440c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7490c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void removeHandshakeCompletedListener( 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7640c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getEnableSessionCreation() { 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7680c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7720c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedCipherSuites() { 773ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7760c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledCipherSuites() { 777bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7800c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 781bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7840c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedProtocols() { 785ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 786adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7880c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledProtocols() { 789bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 790adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7920c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 793bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 794adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 7974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * The names of the compression methods that may be used on this SSL 7984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * connection. 7994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return an array of compression methods 8004559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8014559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public String[] getSupportedCompressionMethods() { 8024559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return NativeCrypto.getSupportedCompressionMethods(); 8034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8044559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8064559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * The names of the compression methods versions that are in use 8074559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * on this SSL connection. 8084559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @return an array of compression methods 8104559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8114559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public String[] getEnabledCompressionMethods() { 8124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom return enabledCompressionMethods.clone(); 8134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8160c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * Enables compression methods listed by getSupportedCompressionMethods(). 8174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @throws IllegalArgumentException when one or more of the names in the 8194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * array are not supported, or when the array is null. 8204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8210c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson public void setEnabledCompressionMethods(String[] methods) { 8224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom enabledCompressionMethods = NativeCrypto.checkEnabledCompressionMethods(methods); 8234559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8244559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8264559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables session ticket support. 8274559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8284559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param useSessionTickets True to enable session tickets 8294559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8304559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8314559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.useSessionTickets = useSessionTickets; 8324559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8334559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8344559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8354559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables Server Name Indication 8364559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8374559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8384559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8394559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setHostname(String hostname) { 8404559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.hostname = hostname; 8414559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8424559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8430c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getUseClientMode() { 844adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 845adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 846adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8470c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setUseClientMode(boolean mode) { 848adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 849adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 8500c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson "Could not change the mode after the initial handshake has begun."); 851adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 852adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 853adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 854adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8550c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getWantClientAuth() { 856adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 857adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 858adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8590c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getNeedClientAuth() { 860adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 861adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 862adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8630c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setNeedClientAuth(boolean need) { 864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 866adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8670c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setWantClientAuth(boolean want) { 868adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 869adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 870adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8710c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void sendUrgentData(int data) throws IOException { 8720c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 873adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 874adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8750c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 8760c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8790c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setSoTimeout(int timeoutMilliseconds) throws SocketException { 880a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom super.setSoTimeout(timeoutMilliseconds); 881a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom this.timeoutMilliseconds = timeoutMilliseconds; 882a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom } 883a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 8840c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public int getSoTimeout() throws SocketException { 885a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom return timeoutMilliseconds; 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8889d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 8899d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 8909d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 8919d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 892a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom public void setHandshakeTimeout(int timeoutMilliseconds) throws SocketException { 893a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom this.handshakeTimeoutMilliseconds = timeoutMilliseconds; 8949d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 8959d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 8960c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void close() throws IOException { 8970c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 9010c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // prevent further attempts to start handshake 902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 903ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 905ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 907df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 913ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9183e24c53ecc31b840e51869c295785d5a2f8b31ebBrian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (writeLock) { 922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (readLock) { 923adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 9275900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 9285d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 9295d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes this); 930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9311c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom } catch (IOException ignored) { 932adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 9331c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * Note that although close() can throw 9341c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * IOException, the RI does not throw if there 9351c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * is problem sending a "close notify" which 9361c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * can happen if the underlying socket is closed. 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 938d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } finally { 939d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom /* 940d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * Even if the above call failed, it is still safe to free 941d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * the native structs, and we need to do so lest we leak 942d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * memory. 943d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom */ 944d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom free(); 945d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom 946d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (socket != this) { 947d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (autoClose && !socket.isClosed()) { 948d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom socket.close(); 949d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 950d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } else { 951d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (!super.isClosed()) { 952d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom super.close(); 953d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 954d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 955adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 956adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 957adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 958adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 959adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 960adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 961ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 962ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 963ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 964ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 965ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 966ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 967f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 968ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 970e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 971e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 972e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom /* 973e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * Just worry about our own state. Notably we do not try and 974e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * close anything. The SocketImpl, either our own 975e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 976e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 977e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * if you want to do that, properly close the socket yourself. 978e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * 979e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 980e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 981e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * finalizer runs first and closes the socket. However, in the 982e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 983e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 984e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * underlying socket BIOs still have the old file descriptor 985e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * and will write the close notify to some unsuspecting 986e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * reader. 987e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom */ 98812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 98912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 99012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 991e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom free(); 992e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 993e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 994e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9963267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey 9973267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey @Override 9983267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 9993267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey if (socket == this) { 10003267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return super.getFileDescriptor$(); 10013267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } else { 10023267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return socket.getFileDescriptor$(); 10033267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 10043267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 1005adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1006