OpenSSLSocketImpl.java revision d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9ae
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 1738375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Rootpackage org.conscrypt; 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; 41b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException; 42aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.SSLProtocolException; 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 44f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager; 45059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 46615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport static libcore.io.OsConstants.*; 47615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.ErrnoException; 48615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.Libcore; 49638000042da777f6d628d88dadde957c52597710Brian Carlstromimport libcore.io.Streams; 50615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.StructTimeval; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include: 564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul> 574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout 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 668acd6134dc84b387608746fbf2054c6d7dcd4f52Joel Dice private long 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; 7325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson private byte[] npnProtocols; 74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 75bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean useSessionTickets; 774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String hostname; 78de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** Whether the TLS Channel ID extension is enabled. This field is server-side only. */ 79de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin private boolean channelIdEnabled; 80de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** Private key for the TLS Channel ID extension. This field is client-side only. */ 81c17bdfa469de6c48f16e454611caae3aaa82cc9dAlex Klyubin private PrivateKey channelIdPrivateKey; 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 83df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final Socket socket; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 8612f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 92bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 93bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 94bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 95bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 97a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 98a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom /** 99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 100a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * write for non-wrapped sockets. Note that 101a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 102a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 103a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom */ 104615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int readTimeoutMilliseconds = 0; 105615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int writeTimeoutMilliseconds = 0; 106a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 107a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 108a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 109a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1116812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 112df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 113ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 114adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 115adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1166812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1187695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 119df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 1207695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites); 121bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 122bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 1236812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 124df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 126df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 127ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1306812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 131df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 133df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 134ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1380c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1390c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1400c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 142df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 143ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1470c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1480c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 150df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 151ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1550c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1560c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * OpenSSLSocketImplWrapper constructor. 157adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 1596812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 161a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 162a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 164ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 165a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 166a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // this.timeout is not set intentionally. 167a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 168a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // to wrapped socket 169ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 170ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 171ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 172ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 173ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 174ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1756812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 176bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 1773d74b4bec8543e6e3f89eafe3afe0925f3a69f01Brian Carlstrom NativeCrypto.getDefaultProtocols(), 1787695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom NativeCrypto.getDefaultCipherSuites()); 179ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 180ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 181ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 182bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 183bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 184ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1856812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters, 186bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1877695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 188bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 189bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 190bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 192adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 196bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 19727c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson String hostName = getPeerHostName(); 19827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson int port = getPeerPort(); 19927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (hostName == null) { 200adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 201adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 20227c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 2039acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2049acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2059acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2069acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2079acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2089acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2099acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2109acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2119acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2129acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2139acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2149acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2159acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2169acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2179acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2189acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2199acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2209acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2229acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2239acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2269acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2289acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2299acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2306df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2319acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 232adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 233adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2345f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom private void checkOpen() throws SocketException { 2355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom if (isClosed()) { 2365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom throw new SocketException("Socket is closed"); 2375f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2385f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2395f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom 2405f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom /** 241679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 242679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 243679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 244679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * verified if the correspondent property in java.Security is set. All 245679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 246bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 247679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson @Override public synchronized void startHandshake() throws IOException { 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 24912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 2586df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 2596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 2606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 2616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 2626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 2636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 2646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 2656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 2676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2688acd6134dc84b387608746fbf2054c6d7dcd4f52Joel Dice final long sslCtxNativePointer = (client) ? 2696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 2706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 2716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 272f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this.sslNativePointer = 0; 273f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean exception = true; 274f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 275f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 276f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 2776df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 27825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson if (npnProtocols != null) { 27925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 28025977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 28125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 282f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup server certificates and private keys. 283f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // clients will receive a call back to request certificates. 284f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!client) { 2856c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 2866c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 287ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 288ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom continue; 289ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom } 2904ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 2916c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom if (keyType != null) { 2926c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom keyTypes.add(keyType); 2936c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 2946c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 2956c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String keyType : keyTypes) { 296f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 297f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 298f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom null, 299f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this)); 300f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 301f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException(e); 302f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 303ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3046df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3056df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 306f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 307f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 308f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (useSessionTickets) { 309f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 310f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 311f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (hostname != null) { 312f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 313f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 314bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 315f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 316f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 317f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 318f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enableSessionCreation); 319bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 320bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 321f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom AbstractSessionContext sessionContext; 322b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom OpenSSLSessionImpl sessionToReuse; 323f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 324f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // look for client session to reuse 325f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 326f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = clientSessionContext; 327b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse = getCachedClientSession(clientSessionContext); 328b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom if (sessionToReuse != null) { 329f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 330b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse.sslSessionNativePointer); 331f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 332ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 333f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 334b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse = null; 335ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 336059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 337f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup peer certificate verification 338f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 339f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // TODO support for anonymous cipher would require us to 340f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // conditionally use SSL_VERIFY_NONE 341f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 342f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // needing client auth takes priority... 3430c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson boolean certRequested; 344f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 345f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 346f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 347f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 348f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 349f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... over just wanting it... 350f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 351f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 352f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 353f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 354f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 355f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 356f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = false; 357f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 358f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 359f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (certRequested) { 360f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 361f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 362f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (issuers != null && issuers.length != 0) { 363f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[][] issuersBytes; 364f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 365d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root issuersBytes = encodeIssuerX509Principals(issuers); 366f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 367f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException("Problem encoding principals", e); 368f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 369f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 370ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 371ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 372ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 373ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 374f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Temporarily use a different timeout for the handshake process 375615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 376615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 377f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 378f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 379615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 380f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 381bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 382de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin // TLS Channel ID 383de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (client) { 384de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin // Client-side TLS Channel ID 385de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (channelIdPrivateKey != null) { 386de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, channelIdPrivateKey); 387de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 388de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } else { 389de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin // Server-side TLS Channel ID 390de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (channelIdEnabled) { 391de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer); 392de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 393de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 394de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 395f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int sslSessionNativePointer; 396f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 3975d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 39825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols); 399f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateException e) { 40054c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 40154c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom wrapper.initCause(e); 40254c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom throw wrapper; 403bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 405b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom if (sessionToReuse != null && Arrays.equals(sessionToReuse.getId(), sessionId)) { 406b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom this.sslSession = sessionToReuse; 407f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 409f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 410f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 411f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 412f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 413f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 414f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] localCertificates 415f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] peerCertificates 417f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 418b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom this.sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 41927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 420f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 422f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext.putSession(sslSession); 423f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 424ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 425f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 426f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Restore the original timeout now that the handshake is complete 427f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 428615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 429615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 4309d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 431adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 432f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 433f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 434f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom notifyHandshakeCompletedListeners(); 435f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 436ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 437f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom exception = false; 438aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } catch (SSLProtocolException e) { 439aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom throw new SSLHandshakeException(e); 440f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } finally { 4418a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom // on exceptional exit, treat the socket as closed 442f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (exception) { 4438a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom close(); 444f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 445adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 446df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 447d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root 448d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root private static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates) 449d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root throws CertificateEncodingException { 450d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root byte[][] principalBytes = new byte[certificates.length][]; 451d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root for (int i = 0; i < certificates.length; i++) { 452d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded(); 453d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root } 454d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root return principalBytes; 455d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root } 456adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4576d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra String getPeerHostName() { 458f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (wrappedHost != null) { 459f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return wrappedHost; 460f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 461f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom InetAddress inetAddress = super.getInetAddress(); 462f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (inetAddress != null) { 463f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return inetAddress.getHostName(); 464f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 465f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return null; 46627c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 46727c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 4686d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra int getPeerPort() { 46927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 47027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 47127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 472df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom /** 473df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * Return a possibly null array of X509Certificates given the 474df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * possibly null array of DER encoded bytes. 475df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom */ 476b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) throws IOException { 477df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (certificatesBytes == null) { 478df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 479df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 480df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 481df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 48238375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Root certificates[i] = OpenSSLX509Certificate.fromX509Der(certificatesBytes[i]); 483df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 484df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return certificates; 485bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 486adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 487ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 4886df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 4896df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 4906df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4916df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 492aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (privateKey == null) { 493aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 494aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 4956df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 496aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (certificates == null) { 497aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 498aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 499aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom 5000731d6d00c5e30c05e035d3ae96327029d07a606Kenny Root if (privateKey instanceof OpenSSLKeyHolder) { 5010731d6d00c5e30c05e035d3ae96327029d07a606Kenny Root OpenSSLKey key = ((OpenSSLKeyHolder) privateKey).getOpenSSLKey(); 502c9acbf1c80d90952f7a4bce83e37c2540e42f6fcKenny Root NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext()); 50341e34229c07e8d05090560ff80558fa222623769Kenny Root } else if ("PKCS#8".equals(privateKey.getFormat())) { 50441e34229c07e8d05090560ff80558fa222623769Kenny Root byte[] privateKeyBytes = privateKey.getEncoded(); 50541e34229c07e8d05090560ff80558fa222623769Kenny Root NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 50641e34229c07e8d05090560ff80558fa222623769Kenny Root } else { 50741e34229c07e8d05090560ff80558fa222623769Kenny Root throw new SSLException("Unsupported PrivateKey format: " + privateKey.getFormat()); 50841e34229c07e8d05090560ff80558fa222623769Kenny Root } 50941e34229c07e8d05090560ff80558fa222623769Kenny Root 510ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 5116df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 5126df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5136df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 5146df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 5156df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 5166df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5176df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5180c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 519059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 520ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 521059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 522059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 523059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 5244ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 525059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 526059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 527059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 528059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 529059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 530059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 531059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 532059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 533059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 534059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 535059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 536059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 5376df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5386df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5390c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 540bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 541bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 542adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 543bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 544bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5450c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // later read operation. That means we do not need to fix up 546bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 547bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 548bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 549bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 550bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 551bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 552adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 553bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 554bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 555bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 556bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 557bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 558bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 559bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 561bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 562bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 563bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 564bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 566bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 567bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 568bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 569bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 570bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 571bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 572bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 573bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 574bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 575e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 576e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 577e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 578e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 579e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 580e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 581e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 582bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 583bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 584bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 585adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 586adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5870c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5880c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 5896df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 590adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 591e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 592e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 593e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 594bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 595bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 59638375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Root peerCertificateChain[i] = OpenSSLX509Certificate.fromX509Der(bytes[i]); 597adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 598bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 599bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 6006d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra X509TrustManager x509tm = sslParameters.getTrustManager(); 6016d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra if (x509tm instanceof TrustManagerImpl) { 6026d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra TrustManagerImpl tm = (TrustManagerImpl) x509tm; 6036d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra tm.checkServerTrusted(peerCertificateChain, authMethod, wrappedHost); 6046d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } else { 6056d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra x509tm.checkServerTrusted(peerCertificateChain, authMethod); 6066d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } 607bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 6084ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 6096df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 6104ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom authType); 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 612bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 613bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 614bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 615bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 6168c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom throw new CertificateException(e); 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6200c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public InputStream getInputStream() throws IOException { 6215f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 622ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 623adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 630adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6310c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public OutputStream getOutputStream() throws IOException { 6325f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 633ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 642bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 649679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 650679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 653679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 657adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 658adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 661adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6634559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 665638000042da777f6d628d88dadde957c52597710Brian Carlstrom return Streams.readSingleByte(this); 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6724559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 673a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 6745900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 675ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 67612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 677a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 678a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 67912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return 0; 68012e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 6815d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 6825d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 686adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 687adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 688adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 694679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 695679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 696ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 698679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 702adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 703adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 704adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 706638000042da777f6d628d88dadde957c52597710Brian Carlstrom public void write(int oneByte) throws IOException { 707638000042da777f6d628d88dadde957c52597710Brian Carlstrom Streams.writeSingleByte(this, oneByte); 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 713adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 715a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 7165900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 717ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 71812e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 719a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 720a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 72112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return; 72212e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 7235d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 724615225a35dbd838210270b282d1196deff643b51Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7300c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public SSLSession getSession() { 731df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (sslSession == null) { 732df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 733679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson startHandshake(); 734df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 735df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // return an invalid session with 736df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 737df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 738df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7430c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void addHandshakeCompletedListener( 744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 7490c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7540c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void removeHandshakeCompletedListener( 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 762adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7690c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getEnableSessionCreation() { 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7730c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7770c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedCipherSuites() { 778ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7810c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledCipherSuites() { 782bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7850c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 786bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7890c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedProtocols() { 790ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7930c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledProtocols() { 794bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7970c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 798bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 8024559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables session ticket support. 8034559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8044559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param useSessionTickets True to enable session tickets 8054559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8064559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8074559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.useSessionTickets = useSessionTickets; 8084559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8094559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8104559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8114559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables Server Name Indication 8124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setHostname(String hostname) { 8164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.hostname = hostname; 8174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 819de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 820de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Enables/disables TLS Channel ID for this server socket. 821de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 822de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 823de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 824de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has already 825de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * started. 826de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 827de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 828de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin public void setChannelIdEnabled(boolean enabled) { 829de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (getUseClientMode()) { 830de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Client mode"); 831de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 832de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (handshakeStarted) { 833de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 834de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Could not enable/disable Channel ID after the initial handshake has" 835de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin + " begun."); 836de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 837de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin this.channelIdEnabled = enabled; 838de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 839de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 840de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 841de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 842de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * handshake completes. 843de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 844de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @return channel ID or {@code null} if not available. 845de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 846de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has not yet 847de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * completed. 848de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws SSLException if channel ID is available but could not be obtained. 849de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 850de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin public byte[] getChannelId() throws SSLException { 851de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (getUseClientMode()) { 852de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Client mode"); 853de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 854de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (!handshakeCompleted) { 855de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 856de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Channel ID is only available after handshake completes"); 857de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 858de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 859de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 860de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 861de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 862de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 863de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 864de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 865de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 866de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 867c17bdfa469de6c48f16e454611caae3aaa82cc9dAlex Klyubin * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 868de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 869de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 870de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a server socket or if the handshake has already 871de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * started. 872de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 873c17bdfa469de6c48f16e454611caae3aaa82cc9dAlex Klyubin public void setChannelIdPrivateKey(PrivateKey privateKey) { 874de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (!getUseClientMode()) { 875de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Server mode"); 876de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 877de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (handshakeStarted) { 878de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 879de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Could not change Channel ID private key after the initial handshake has" 880de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin + " begun."); 881de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 882de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin this.channelIdPrivateKey = privateKey; 883de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 884de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 8850c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getUseClientMode() { 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8890c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setUseClientMode(boolean mode) { 890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 891adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 8920c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson "Could not change the mode after the initial handshake has begun."); 893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8970c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getWantClientAuth() { 898adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 899adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 900adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9010c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getNeedClientAuth() { 902adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9050c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setNeedClientAuth(boolean need) { 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 907adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9090c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setWantClientAuth(boolean want) { 910adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9130c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void sendUrgentData(int data) throws IOException { 9140c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 915adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9170c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 9180c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 919adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 921615225a35dbd838210270b282d1196deff643b51Brian Carlstrom @Override public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 922615225a35dbd838210270b282d1196deff643b51Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 923615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 924a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom } 925a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 9260c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public int getSoTimeout() throws SocketException { 927615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return readTimeoutMilliseconds; 928615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 929615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 930615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 931615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 932615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 933615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 934615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 935615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 936615225a35dbd838210270b282d1196deff643b51Brian Carlstrom StructTimeval tv = StructTimeval.fromMillis(writeTimeoutMilliseconds); 937615225a35dbd838210270b282d1196deff643b51Brian Carlstrom try { 938615225a35dbd838210270b282d1196deff643b51Brian Carlstrom Libcore.os.setsockoptTimeval(getFileDescriptor$(), SOL_SOCKET, SO_SNDTIMEO, tv); 939615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } catch (ErrnoException errnoException) { 940615225a35dbd838210270b282d1196deff643b51Brian Carlstrom throw errnoException.rethrowAsSocketException(); 941615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 942615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 943615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 944615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 945615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 946615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 947615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 948615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return writeTimeoutMilliseconds; 949adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 950adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9519d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 9529d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 9539d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 9549d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 955615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 956615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 9579d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 9589d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 9590c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void close() throws IOException { 9600c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 961adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 962adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 963adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 9640c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // prevent further attempts to start handshake 965adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 966ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 968ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 969adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 970df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 971adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 972adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 973adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 975adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 976ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 977adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 978adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 982adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 983783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom // Interrupt any outstanding reads or writes before taking the writeLock and readLock 984783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 985df9f5967a3b8dc2f61183d155791393b67980511Brian Carlstrom 986783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (writeLock) { 987783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (readLock) { 988adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 9915900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 9925d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 9935d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes this); 994adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9951c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom } catch (IOException ignored) { 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 9971c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * Note that although close() can throw 9981c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * IOException, the RI does not throw if there 9991c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * is problem sending a "close notify" which 10001c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * can happen if the underlying socket is closed. 1001adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1002d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } finally { 1003d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom /* 1004d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * Even if the above call failed, it is still safe to free 1005d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * the native structs, and we need to do so lest we leak 1006d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * memory. 1007d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom */ 1008d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom free(); 1009d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom 1010d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (socket != this) { 1011d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (autoClose && !socket.isClosed()) { 1012d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom socket.close(); 1013d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1014d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } else { 1015d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (!super.isClosed()) { 1016d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom super.close(); 1017d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1018d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1020adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1021adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1022adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1023adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1024adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1025ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 1026ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 1027ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 1028ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1029ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1030ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 1031f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 1032ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1033adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1034e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 1035e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 1036e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom /* 1037e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * Just worry about our own state. Notably we do not try and 1038e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * close anything. The SocketImpl, either our own 1039e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 1040e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 1041e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * if you want to do that, properly close the socket yourself. 1042e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * 1043e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 1044e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 1045e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * finalizer runs first and closes the socket. However, in the 1046e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 1047e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 1048e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * underlying socket BIOs still have the old file descriptor 1049e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * and will write the close notify to some unsuspecting 1050e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * reader. 1051e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom */ 105212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 105312f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 105412f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 1055e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom free(); 1056e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 1057e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 1058e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 1059adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 10603267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey 10613267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey @Override 10623267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 10633267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey if (socket == this) { 10643267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return super.getFileDescriptor$(); 10653267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } else { 10663267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return socket.getFileDescriptor$(); 10673267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 10683267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 106925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 107025977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 107125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Returns the protocol agreed upon by client and server, or null if no 107225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocol was agreed upon. 107325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 107425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public byte[] getNpnSelectedProtocol() { 1075600dc4949de6bf5608e5f5a5214cde59299b683aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 107625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 107725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 107825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 107925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Sets the list of protocols this peer is interested in. If null no 108025977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocols will be used. 108125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * 10821982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 10831982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 10841982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * strings. The length byte itself is not included in the length. A byte 10851982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 108625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 108725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 10881982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 10891982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 10901982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson } 109125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson this.npnProtocols = npnProtocols; 109225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 1093adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1094