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; 284f60362bb61f8199f3e97371eff96461fbacba68Kenny Rootimport java.security.InvalidKeyException; 296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey; 306df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom; 3112cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 35a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 366c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.HashSet; 376c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.Set; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException; 412915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstromimport javax.net.ssl.SSLHandshakeException; 42b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstromimport javax.net.ssl.SSLPeerUnverifiedException; 43aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.SSLProtocolException; 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 45f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager; 46059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 47615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport static libcore.io.OsConstants.*; 48615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.ErrnoException; 49615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.Libcore; 50638000042da777f6d628d88dadde957c52597710Brian Carlstromimport libcore.io.Streams; 51615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.StructTimeval; 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 53adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include: 574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul> 584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout 594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets 604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication 614559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul> 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 63ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl 64ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom extends javax.net.ssl.SSLSocket 656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 66df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom 678acd6134dc84b387608746fbf2054c6d7dcd4f52Joel Dice private long sslNativePointer; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream is; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream os; 70adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Object handshakeLock = new Object(); 71ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object readLock = new Object(); 72ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object writeLock = new Object(); 736812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private SSLParametersImpl sslParameters; 7425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson private byte[] npnProtocols; 75d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root private byte[] alpnProtocols; 76bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 77bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 784559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean useSessionTickets; 794559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String hostname; 80de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** Whether the TLS Channel ID extension is enabled. This field is server-side only. */ 81de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin private boolean channelIdEnabled; 82de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** Private key for the TLS Channel ID extension. This field is client-side only. */ 834f60362bb61f8199f3e97371eff96461fbacba68Kenny Root private OpenSSLKey channelIdPrivateKey; 84adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 85df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final Socket socket; 86adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 87adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 8812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 92bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 93bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 94bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 95bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 96bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 97bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 100a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom /** 101a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 102a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * write for non-wrapped sockets. Note that 103a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 104a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 105a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom */ 106615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int readTimeoutMilliseconds = 0; 107615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int writeTimeoutMilliseconds = 0; 108a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 109a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 110a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 111a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1136812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 114df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 115ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 116adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 117adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1186812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 119bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1207695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 121df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 1227695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites); 123bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 124bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 1256812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 126df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 128df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 129ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1326812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 133df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 135df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 136ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1400c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1410c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1420c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 144df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 145ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1490c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1500c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 152df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 153ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1570c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1580c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * OpenSSLSocketImplWrapper constructor. 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 1616812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 163a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 164a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 166ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 167a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 168a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // this.timeout is not set intentionally. 169a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 170a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // to wrapped socket 171ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 172ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 173ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 174ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 175ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 176ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1776812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 178bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 1793d74b4bec8543e6e3f89eafe3afe0925f3a69f01Brian Carlstrom NativeCrypto.getDefaultProtocols(), 1807695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom NativeCrypto.getDefaultCipherSuites()); 181ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 182ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 183ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 184bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 185bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 186ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1876812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters, 188bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1897695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 190bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 191bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 192bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 193adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 194adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 198bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 19927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson String hostName = getPeerHostName(); 20027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson int port = getPeerPort(); 20127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (hostName == null) { 202adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 203adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 20427c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 2059acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2069acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2079acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2089acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2099acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2109acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2119acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2129acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2139acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2149acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2159acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2169acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2179acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2189acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2199acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2209acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2229acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2239acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2269acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2289acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2299acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2309acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2319acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2326df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2339acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 234adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 235adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom private void checkOpen() throws SocketException { 2375f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom if (isClosed()) { 2385f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom throw new SocketException("Socket is closed"); 2395f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2405f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2415f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom 2425f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom /** 243679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 244679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 245679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 246679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * verified if the correspondent property in java.Security is set. All 247679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 248bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 249679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson @Override public synchronized void startHandshake() throws IOException { 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 25112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 253adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 254adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 255adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 256adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 257adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 258adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 2606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 2616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 2626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 2636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 2646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 2656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 2666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 2676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2686df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 2696df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2708acd6134dc84b387608746fbf2054c6d7dcd4f52Joel Dice final long sslCtxNativePointer = (client) ? 2716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 2726df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 2736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 274f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this.sslNativePointer = 0; 275f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean exception = true; 276f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 277f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 278f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 2796df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 28025977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson if (npnProtocols != null) { 28125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 28225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 28325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 284d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root if (client && alpnProtocols != null) { 285d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root NativeCrypto.SSL_CTX_set_alpn_protos(sslCtxNativePointer, alpnProtocols); 286d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root } 287d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root 288f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup server certificates and private keys. 289f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // clients will receive a call back to request certificates. 290f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!client) { 2916c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 2926c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 293ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 294ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom continue; 295ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom } 2964ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 2976c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom if (keyType != null) { 2986c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom keyTypes.add(keyType); 2996c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3006c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 3016c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String keyType : keyTypes) { 302f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 303f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 304f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom null, 305f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this)); 306f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 307f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException(e); 308f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 309ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3106df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3116df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 312f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 313f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 314f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (useSessionTickets) { 315f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 316f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 317f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (hostname != null) { 318f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 319f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 320bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 321f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 322f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 323f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 324f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enableSessionCreation); 325bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 326bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 327f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom AbstractSessionContext sessionContext; 328b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom OpenSSLSessionImpl sessionToReuse; 329f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 330f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // look for client session to reuse 331f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 332f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = clientSessionContext; 333b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse = getCachedClientSession(clientSessionContext); 334b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom if (sessionToReuse != null) { 335f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 336b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse.sslSessionNativePointer); 337f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 338ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 339f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 340b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom sessionToReuse = null; 341ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 342059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 343f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup peer certificate verification 344f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 345f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // TODO support for anonymous cipher would require us to 346f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // conditionally use SSL_VERIFY_NONE 347f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 348f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // needing client auth takes priority... 3490c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson boolean certRequested; 350f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 351f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 352f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 353f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 354f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 355f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... over just wanting it... 356f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 357f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 358f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 359f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 360f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 361f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 362f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = false; 363f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 364f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 365f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (certRequested) { 366f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 367f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 368f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (issuers != null && issuers.length != 0) { 369f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[][] issuersBytes; 370f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 371d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root issuersBytes = encodeIssuerX509Principals(issuers); 372f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 373f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException("Problem encoding principals", e); 374f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 375f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 376ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 377ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 378ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 379ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 380f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Temporarily use a different timeout for the handshake process 381615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 382615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 383f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 384f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 385615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 386f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 387bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 388de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin // TLS Channel ID 3894f60362bb61f8199f3e97371eff96461fbacba68Kenny Root if (channelIdEnabled) { 3904f60362bb61f8199f3e97371eff96461fbacba68Kenny Root if (client) { 3914f60362bb61f8199f3e97371eff96461fbacba68Kenny Root // Client-side TLS Channel ID 3924f60362bb61f8199f3e97371eff96461fbacba68Kenny Root if (channelIdPrivateKey == null) { 3934f60362bb61f8199f3e97371eff96461fbacba68Kenny Root throw new SSLHandshakeException("Invalid TLS channel ID key specified"); 3944f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } 3954f60362bb61f8199f3e97371eff96461fbacba68Kenny Root NativeCrypto.SSL_set1_tls_channel_id(sslNativePointer, 3964f60362bb61f8199f3e97371eff96461fbacba68Kenny Root channelIdPrivateKey.getPkeyContext()); 3974f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } else { 3984f60362bb61f8199f3e97371eff96461fbacba68Kenny Root // Server-side TLS Channel ID 399de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin NativeCrypto.SSL_enable_tls_channel_id(sslNativePointer); 400de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 401de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 402de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 403f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int sslSessionNativePointer; 404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 4055d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 406d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols, 407d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root client ? null : alpnProtocols); 408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateException e) { 40954c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 41054c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom wrapper.initCause(e); 41154c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom throw wrapper; 412bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 413f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 414b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom if (sessionToReuse != null && Arrays.equals(sessionToReuse.getId(), sessionId)) { 415b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom this.sslSession = sessionToReuse; 416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 417f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 418f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 419f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 420f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 422f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 423f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] localCertificates 424f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 425f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] peerCertificates 426f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 427b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom this.sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 42827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 429f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 430f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 431f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext.putSession(sslSession); 432f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 433ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 434f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 435f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Restore the original timeout now that the handshake is complete 436f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 437615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 438615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 4399d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 440adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 441f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 442f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 443f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom notifyHandshakeCompletedListeners(); 444f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 445ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 446f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom exception = false; 447aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } catch (SSLProtocolException e) { 448aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom throw new SSLHandshakeException(e); 449f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } finally { 4508a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom // on exceptional exit, treat the socket as closed 451f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (exception) { 4528a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom close(); 453f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 454adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 455df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 456d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root 457d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root private static byte[][] encodeIssuerX509Principals(X509Certificate[] certificates) 458d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root throws CertificateEncodingException { 459d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root byte[][] principalBytes = new byte[certificates.length][]; 460d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root for (int i = 0; i < certificates.length; i++) { 461d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root principalBytes[i] = certificates[i].getIssuerX500Principal().getEncoded(); 462d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root } 463d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root return principalBytes; 464d2cbcf1c2e2169d6454ede8ac7d1cfc73860b9aeKenny Root } 465adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4666d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra String getPeerHostName() { 467f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (wrappedHost != null) { 468f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return wrappedHost; 469f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 470f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom InetAddress inetAddress = super.getInetAddress(); 471f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (inetAddress != null) { 472f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return inetAddress.getHostName(); 473f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 474f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return null; 47527c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 47627c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 4776d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra int getPeerPort() { 47827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 47927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 48027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 481df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom /** 482df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * Return a possibly null array of X509Certificates given the 483df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * possibly null array of DER encoded bytes. 484df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom */ 485b88ab0efb05475fa9d4e2a06175e95e88f507cffBrian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) throws IOException { 486df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (certificatesBytes == null) { 487df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 488df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 489df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 490df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 49138375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Root certificates[i] = OpenSSLX509Certificate.fromX509Der(certificatesBytes[i]); 492df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 493df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return certificates; 494bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 495adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 496ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 4976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 4986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 4996df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 501aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (privateKey == null) { 502aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 503aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 5046df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 505aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (certificates == null) { 506aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 507aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 508aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom 50980546e159b0491667acbfe53ef3ea9b0962f070dBrian Carlstrom // Note that OpenSSL says to use SSL_use_certificate before SSL_use_PrivateKey. 51080546e159b0491667acbfe53ef3ea9b0962f070dBrian Carlstrom 51180546e159b0491667acbfe53ef3ea9b0962f070dBrian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 51280546e159b0491667acbfe53ef3ea9b0962f070dBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 51380546e159b0491667acbfe53ef3ea9b0962f070dBrian Carlstrom 5144f60362bb61f8199f3e97371eff96461fbacba68Kenny Root try { 5154f60362bb61f8199f3e97371eff96461fbacba68Kenny Root final OpenSSLKey key = OpenSSLKey.fromPrivateKey(privateKey); 5164f60362bb61f8199f3e97371eff96461fbacba68Kenny Root NativeCrypto.SSL_use_PrivateKey(sslNativePointer, key.getPkeyContext()); 5174f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } catch (InvalidKeyException e) { 5184f60362bb61f8199f3e97371eff96461fbacba68Kenny Root throw new SSLException(e); 51941e34229c07e8d05090560ff80558fa222623769Kenny Root } 52041e34229c07e8d05090560ff80558fa222623769Kenny Root 5216df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 5226df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 5236df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 5246df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5256df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5260c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 527059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 528ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 529059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 530059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 531059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 5324ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 533059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 534059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 535059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 536059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 537059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 538059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 539059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 540059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 541059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 542059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 543059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 544059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 5456df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5466df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5470c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 548bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 549bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 550adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 551bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 552bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5530c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // later read operation. That means we do not need to fix up 554bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 555bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 556bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 557bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 558bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 559bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 560adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 561bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 562bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 563bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 564bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 566bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 567bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 568adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 569bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 570bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 571bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 572bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 573bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 574bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 575bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 576bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 577bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 578bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 579bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 580bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 581bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 582bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 583e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 584e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 585e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 586e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 587e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 588e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 589e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 590bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 591bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 592bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 593adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 594adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5950c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5960c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 5976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 599e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 600e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 601e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 602bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 603bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 60438375a4d0b3d34e2babbd2f6a013976c7c439696Kenny Root peerCertificateChain[i] = OpenSSLX509Certificate.fromX509Der(bytes[i]); 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 606bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 607bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 6086d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra X509TrustManager x509tm = sslParameters.getTrustManager(); 6096d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra if (x509tm instanceof TrustManagerImpl) { 6106d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra TrustManagerImpl tm = (TrustManagerImpl) x509tm; 6116d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra tm.checkServerTrusted(peerCertificateChain, authMethod, wrappedHost); 6126d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } else { 6136d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra x509tm.checkServerTrusted(peerCertificateChain, authMethod); 6146d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } 615bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 6164ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 6176df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 6184ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom authType); 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 620bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 621bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 622bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 623bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 6248c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom throw new CertificateException(e); 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6280c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public InputStream getInputStream() throws IOException { 6295f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 630ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 631adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 634adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6390c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public OutputStream getOutputStream() throws IOException { 6405f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 641ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 644adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 646adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 650bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 653adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 654adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 655adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 656adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 657679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 658679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 659adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 660adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 661679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 662adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 663adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6714559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 673638000042da777f6d628d88dadde957c52597710Brian Carlstrom return Streams.readSingleByte(this); 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 675adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 676adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 677adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 679adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6804559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 681a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 6825900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 683ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 68412e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 685a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 686a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 68712e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return 0; 68812e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 6895d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 6905d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 695adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 696adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 697adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 698adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 699adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 700adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 701adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 702679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 703679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 704ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 705adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 706679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 711adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 712adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 714638000042da777f6d628d88dadde957c52597710Brian Carlstrom public void write(int oneByte) throws IOException { 715638000042da777f6d628d88dadde957c52597710Brian Carlstrom Streams.writeSingleByte(this, oneByte); 716adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 717adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 718adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 719adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 7224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 723a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 7245900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 725ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 72612e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 727a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 728a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 72912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return; 73012e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 7315d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 732615225a35dbd838210270b282d1196deff643b51Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 735adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7380c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public SSLSession getSession() { 739df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (sslSession == null) { 740df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 741679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson startHandshake(); 742df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 743df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // return an invalid session with 744df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 745da5b7116b58795b169961cbd63c2b21bac741d9aKenny Root return SSLSessionImpl.getNullSession(); 746df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 750adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7510c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void addHandshakeCompletedListener( 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 754adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 7570c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 758adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 759adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7620c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void removeHandshakeCompletedListener( 763adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 766adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 767adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 770adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 771adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 774adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 775adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7770c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getEnableSessionCreation() { 778adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 779adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7810c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 783adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 784adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7850c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedCipherSuites() { 786ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 787adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 788adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7890c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledCipherSuites() { 790bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 791adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 792adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7930c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 794bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 795adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 796adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7970c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedProtocols() { 798ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 799adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 800adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8010c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledProtocols() { 802bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 804adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8050c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 806bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 807adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 8104559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables session ticket support. 8114559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8124559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param useSessionTickets True to enable session tickets 8134559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8144559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 8154559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.useSessionTickets = useSessionTickets; 8164559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8174559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8184559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 8194559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables Server Name Indication 8204559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 8214559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 8224559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 8234559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setHostname(String hostname) { 8244559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.hostname = hostname; 8254559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 8264559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 827de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 828de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Enables/disables TLS Channel ID for this server socket. 829de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 830de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 831de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 832de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has already 833de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * started. 834de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 835de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 836de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin public void setChannelIdEnabled(boolean enabled) { 837de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (getUseClientMode()) { 838de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Client mode"); 839de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 840de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (handshakeStarted) { 841de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 842de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Could not enable/disable Channel ID after the initial handshake has" 843de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin + " begun."); 844de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 845de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin this.channelIdEnabled = enabled; 846de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 847de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 848de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 849de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 850de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * handshake completes. 851de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 852de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @return channel ID or {@code null} if not available. 853de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 854de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a client socket or if the handshake has not yet 855de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * completed. 856de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws SSLException if channel ID is available but could not be obtained. 857de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 858de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin public byte[] getChannelId() throws SSLException { 859de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (getUseClientMode()) { 860de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Client mode"); 861de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 862de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (!handshakeCompleted) { 863de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 864de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Channel ID is only available after handshake completes"); 865de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 866de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 867de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 868de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 869de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin /** 870de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 871de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 872de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * <p>This method needs to be invoked before the handshake starts. 873de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 874de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 875c17bdfa469de6c48f16e454611caae3aaa82cc9dAlex Klyubin * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 876de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 877de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * 878de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * @throws IllegalStateException if this is a server socket or if the handshake has already 879de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin * started. 880de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin */ 881c17bdfa469de6c48f16e454611caae3aaa82cc9dAlex Klyubin public void setChannelIdPrivateKey(PrivateKey privateKey) { 882de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (!getUseClientMode()) { 883de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException("Server mode"); 884de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 885de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin if (handshakeStarted) { 886de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin throw new IllegalStateException( 887de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin "Could not change Channel ID private key after the initial handshake has" 888de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin + " begun."); 889de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 8904f60362bb61f8199f3e97371eff96461fbacba68Kenny Root if (privateKey == null) { 8914f60362bb61f8199f3e97371eff96461fbacba68Kenny Root this.channelIdEnabled = false; 8924f60362bb61f8199f3e97371eff96461fbacba68Kenny Root this.channelIdPrivateKey = null; 8934f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } else { 8944f60362bb61f8199f3e97371eff96461fbacba68Kenny Root this.channelIdEnabled = true; 8954f60362bb61f8199f3e97371eff96461fbacba68Kenny Root try { 8964f60362bb61f8199f3e97371eff96461fbacba68Kenny Root this.channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey); 8974f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } catch (InvalidKeyException e) { 8984f60362bb61f8199f3e97371eff96461fbacba68Kenny Root // Will have error in startHandshake 8994f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } 9004f60362bb61f8199f3e97371eff96461fbacba68Kenny Root } 901de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin } 902de30700ecd96af43e2f3ee2e03f398896f5bb1e9Alex Klyubin 9030c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getUseClientMode() { 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 906adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9070c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setUseClientMode(boolean mode) { 908adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 9100c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson "Could not change the mode after the initial handshake has begun."); 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 912adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 913adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 914adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9150c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getWantClientAuth() { 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 917adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 918adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9190c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getNeedClientAuth() { 920adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 921adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 922adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9230c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setNeedClientAuth(boolean need) { 924adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 925adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 926adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9270c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setWantClientAuth(boolean want) { 928adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 929adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 930adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9310c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void sendUrgentData(int data) throws IOException { 9320c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 933adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9350c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 9360c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 939615225a35dbd838210270b282d1196deff643b51Brian Carlstrom @Override public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 940615225a35dbd838210270b282d1196deff643b51Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 941615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 942a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom } 943a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 9440c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public int getSoTimeout() throws SocketException { 945615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return readTimeoutMilliseconds; 946615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 947615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 948615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 949615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 950615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 951615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 952615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 953615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 954615225a35dbd838210270b282d1196deff643b51Brian Carlstrom StructTimeval tv = StructTimeval.fromMillis(writeTimeoutMilliseconds); 955615225a35dbd838210270b282d1196deff643b51Brian Carlstrom try { 956615225a35dbd838210270b282d1196deff643b51Brian Carlstrom Libcore.os.setsockoptTimeval(getFileDescriptor$(), SOL_SOCKET, SO_SNDTIMEO, tv); 957615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } catch (ErrnoException errnoException) { 958615225a35dbd838210270b282d1196deff643b51Brian Carlstrom throw errnoException.rethrowAsSocketException(); 959615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 960615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 961615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 962615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 963615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 964615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 965615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 966615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return writeTimeoutMilliseconds; 967adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 968adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 9699d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 9709d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 9719d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 9729d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 973615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 974615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 9759d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 9769d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 9770c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void close() throws IOException { 9780c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 979adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 980adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 981adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 9820c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // prevent further attempts to start handshake 983adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 984ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 985adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 986ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 987adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 988df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 989adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 990adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 991adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 992adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 993adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 994ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 995adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 996adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 997adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 998adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 999adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 1000adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1001783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom // Interrupt any outstanding reads or writes before taking the writeLock and readLock 1002783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 1003df9f5967a3b8dc2f61183d155791393b67980511Brian Carlstrom 1004783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (writeLock) { 1005783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (readLock) { 1006adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 1007adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 10095900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 10105d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 10115d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes this); 1012adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 10131c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom } catch (IOException ignored) { 1014adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 10151c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * Note that although close() can throw 10161c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * IOException, the RI does not throw if there 10171c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * is problem sending a "close notify" which 10181c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * can happen if the underlying socket is closed. 1019adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 1020d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } finally { 1021d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom /* 1022d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * Even if the above call failed, it is still safe to free 1023d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * the native structs, and we need to do so lest we leak 1024d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * memory. 1025d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom */ 1026d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom free(); 1027d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom 1028d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (socket != this) { 1029d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (autoClose && !socket.isClosed()) { 1030d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom socket.close(); 1031d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1032d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } else { 1033d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (!super.isClosed()) { 1034d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom super.close(); 1035d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1036d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 1037adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1038adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1039adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1040adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1041adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 1042adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1043ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 1044ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 1045ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 1046ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1047ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 1048ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 1049f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 1050ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 1051adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1052e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 1053e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 1054e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom /* 1055e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * Just worry about our own state. Notably we do not try and 1056e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * close anything. The SocketImpl, either our own 1057e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 1058e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 1059e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * if you want to do that, properly close the socket yourself. 1060e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * 1061e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 1062e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 1063e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * finalizer runs first and closes the socket. However, in the 1064e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 1065e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 1066e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * underlying socket BIOs still have the old file descriptor 1067e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * and will write the close notify to some unsuspecting 1068e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * reader. 1069e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom */ 107012f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 107112f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 107212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 1073e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom free(); 1074e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 1075e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 1076e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 1077adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 10783267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey 10793267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey @Override 10803267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 10813267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey if (socket == this) { 10823267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return super.getFileDescriptor$(); 10833267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } else { 10843267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return socket.getFileDescriptor$(); 10853267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 10863267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 108725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 108825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 108925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Returns the protocol agreed upon by client and server, or null if no 109025977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocol was agreed upon. 109125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 109225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public byte[] getNpnSelectedProtocol() { 1093600dc4949de6bf5608e5f5a5214cde59299b683aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 109425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 109525977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 109625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 1097d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * Returns the protocol agreed upon by client and server, or {@code null} if 1098d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * no protocol was agreed upon. 1099d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root */ 1100d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root public byte[] getAlpnSelectedProtocol() { 1101d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 1102d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root } 1103d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root 1104d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root /** 110525977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Sets the list of protocols this peer is interested in. If null no 110625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocols will be used. 110725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * 11081982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 11091982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 11101982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * strings. The length byte itself is not included in the length. A byte 11111982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 111225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 111325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 11141982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 11151982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 11161982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson } 111725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson this.npnProtocols = npnProtocols; 111825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 1119d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root 1120d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root /** 1121d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * Sets the list of protocols this peer is interested in. If the list is 1122d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * {@code null}, no protocols will be used. 1123d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * 1124d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * @param alpnProtocols a non-empty array of protocol names. From 1125d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1126d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * strings. The length byte itself is not included in the length. 1127d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * A byte string of length 0 is invalid. No byte string may be 1128d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root * truncated.". 1129d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root */ 1130d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root public void setAlpnProtocols(byte[] alpnProtocols) { 1131d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root if (alpnProtocols != null && alpnProtocols.length == 0) { 1132d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root throw new IllegalArgumentException("alpnProtocols.length == 0"); 1133d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root } 1134d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root this.alpnProtocols = alpnProtocols; 1135d10b61eeabd2bace2deac2d2352c0de29c3c6bf6Kenny Root } 1136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1137