OpenSSLSocketImpl.java revision 8c4a407e34de1b348316a9175bd1c0577c887181
1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License. 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage org.apache.harmony.xnet.provider.jsse; 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 195900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrickimport dalvik.system.BlockGuard; 20f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport dalvik.system.CloseGuard; 213267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkeyimport java.io.FileDescriptor; 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.IOException; 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.InputStream; 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.io.OutputStream; 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.InetAddress; 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.Socket; 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.net.SocketException; 286df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.PrivateKey; 296df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstromimport java.security.SecureRandom; 3012cd1f00c2fa1a7f37bf644cecdf7588bdc0b0a9Brian Carlstromimport java.security.cert.CertificateEncodingException; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.CertificateException; 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.security.cert.X509Certificate; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport java.util.ArrayList; 34a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 356c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.HashSet; 366c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstromimport java.util.Set; 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedEvent; 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.HandshakeCompletedListener; 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLException; 402915378e253f08e47fe5a9bfd026cd1ca7c6c351Brian Carlstromimport javax.net.ssl.SSLHandshakeException; 41aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstromimport javax.net.ssl.SSLProtocolException; 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport javax.net.ssl.SSLSession; 43f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstromimport javax.net.ssl.X509TrustManager; 44059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstromimport javax.security.auth.x500.X500Principal; 45615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport static libcore.io.OsConstants.*; 46615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.ErrnoException; 47615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.Libcore; 48638000042da777f6d628d88dadde957c52597710Brian Carlstromimport libcore.io.Streams; 49615225a35dbd838210270b282d1196deff643b51Brian Carlstromimport libcore.io.StructTimeval; 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectimport org.apache.harmony.security.provider.cert.X509CertImpl; 51adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 544559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <p> 554559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * Extensions to SSLSocket include: 564559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <ul> 574559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>handshake timeout 584559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>session tickets 594559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * <li>Server Name Indication 604559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * </ul> 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 62ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrompublic class OpenSSLSocketImpl 63ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom extends javax.net.ssl.SSLSocket 646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom implements NativeCrypto.SSLHandshakeCallbacks { 65df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom 66ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private int sslNativePointer; 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private InputStream is; 68adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OutputStream os; 69adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private final Object handshakeLock = new Object(); 70ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object readLock = new Object(); 71ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private final Object writeLock = new Object(); 726812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private SSLParametersImpl sslParameters; 7325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson private byte[] npnProtocols; 74bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledProtocols; 75bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private String[] enabledCipherSuites; 764559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private boolean useSessionTickets; 774559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom private String hostname; 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private OpenSSLSessionImpl sslSession; 79df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private final Socket socket; 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean autoClose; 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private boolean handshakeStarted = false; 8212f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom private final CloseGuard guard = CloseGuard.get(); 83bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 84bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 85bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Not set to true until the update from native that tells us the 86bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * full handshake is complete, since SSL_do_handshake can return 87bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * before the handshake is completely done due to 88bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * handshake_cutthrough support. 89bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 90bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private boolean handshakeCompleted = false; 91bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 92adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private ArrayList<HandshakeCompletedListener> listeners; 93a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 94a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom /** 95a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * Local cache of timeout to avoid getsockopt on every read and 96a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * write for non-wrapped sockets. Note that 97a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * OpenSSLSocketImplWrapper overrides setSoTimeout and 98a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom * getSoTimeout to delegate to the wrapped socket. 99a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom */ 100615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int readTimeoutMilliseconds = 0; 101615225a35dbd838210270b282d1196deff643b51Brian Carlstrom private int writeTimeoutMilliseconds = 0; 102a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 103a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 104a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private String wrappedHost; 105a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom private int wrappedPort; 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1076812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 108df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 109ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 110adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 111adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1126812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(SSLParametersImpl sslParameters, 113bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1147695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 115df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 1167695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom init(sslParameters, enabledProtocols, enabledCipherSuites); 117bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 118bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 1196812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 120df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port); 122df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 123ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1266812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 127df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom throws IOException { 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port); 129df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 130ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 1340c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom protected OpenSSLSocketImpl(String host, int port, 1350c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1360c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(host, port, clientAddress, clientPort); 138df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 139ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(InetAddress address, int port, 1430c131a2ca38465b7d1df4eaee63ac73ce4d5986dBrian Carlstrom InetAddress clientAddress, int clientPort, 1440c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson SSLParametersImpl sslParameters) throws IOException { 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project super(address, port, clientAddress, clientPort); 146df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom this.socket = this; 147ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 1510c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * Create an SSL socket that wraps another socket. Invoked by 1520c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson * OpenSSLSocketImplWrapper constructor. 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project protected OpenSSLSocketImpl(Socket socket, String host, int port, 1556812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 156adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.socket = socket; 157a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedHost = host; 158a653cca054f36de92bbef8498be3f0f01d9d6119Brian Carlstrom this.wrappedPort = port; 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project this.autoClose = autoClose; 160ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom init(sslParameters); 161a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 162a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // this.timeout is not set intentionally. 163a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 164a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom // to wrapped socket 165ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 166ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 167ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 168ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * Initialize the SSL socket and set the certificates for the 169ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * future handshaking. 170ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1716812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters) throws IOException { 172bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom init(sslParameters, 1733d74b4bec8543e6e3f89eafe3afe0925f3a69f01Brian Carlstrom NativeCrypto.getDefaultProtocols(), 1747695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom NativeCrypto.getDefaultCipherSuites()); 175ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 176ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 177ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom /** 178bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * Initialize the SSL socket and set the certificates for the 179bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom * future handshaking. 180ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom */ 1816812a2e8bb43d9a875633a9ba255d9882c63e327Brian Carlstrom private void init(SSLParametersImpl sslParameters, 182bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom String[] enabledProtocols, 1837695a9b3261bfee3a810e0829bd8082fe1fcb6a4Brian Carlstrom String[] enabledCipherSuites) throws IOException { 184bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.sslParameters = sslParameters; 185bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledProtocols = enabledProtocols; 186bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom this.enabledCipherSuites = enabledCipherSuites; 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Gets the suitable session reference from the session cache container. 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 192bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private OpenSSLSessionImpl getCachedClientSession(ClientSessionContext sessionContext) { 19327c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson String hostName = getPeerHostName(); 19427c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson int port = getPeerPort(); 19527c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson if (hostName == null) { 196adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return null; 197adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 19827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson OpenSSLSessionImpl session = (OpenSSLSessionImpl) sessionContext.getSession(hostName, port); 1999acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (session == null) { 2009acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2019acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2029acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2039acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String protocol = session.getProtocol(); 2049acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean protocolFound = false; 2059acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledProtocol : enabledProtocols) { 2069acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (protocol.equals(enabledProtocol)) { 2079acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom protocolFound = true; 2089acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2099acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2109acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2119acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!protocolFound) { 2129acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2139acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2149acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom 2159acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom String cipherSuite = session.getCipherSuite(); 2169acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom boolean cipherSuiteFound = false; 2179acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 2189acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (cipherSuite.equals(enabledCipherSuite)) { 2199acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom cipherSuiteFound = true; 2209acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom break; 2219acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2229acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2239acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom if (!cipherSuiteFound) { 2249acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return null; 2259acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom } 2266df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2279acacc36bafda869c6e9cc63786cdddd995ca96aBrian Carlstrom return session; 228adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 229adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2305f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom private void checkOpen() throws SocketException { 2315f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom if (isClosed()) { 2325f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom throw new SocketException("Socket is closed"); 2335f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2345f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom } 2355f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom 2365f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom /** 237679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Starts a TLS/SSL handshake on this connection using some native methods 238679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * from the OpenSSL library. It can negotiate new encryption keys, change 239679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * cipher suites, or initiate a new session. The certificate chain is 240679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * verified if the correspondent property in java.Security is set. All 241679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * listeners are notified at the end of the TLS/SSL handshake. 242bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom */ 243679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson @Override public synchronized void startHandshake() throws IOException { 244adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 24512e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 246adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 247adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 248adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 249adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 250adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 251adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 252adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 2536df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // note that this modifies the global seed, not something specific to the connection 2546df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 2556df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 2566df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (secureRandom == null) { 2576df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 2586df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } else { 2596df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 2606df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 2616df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2626df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final boolean client = sslParameters.getUseClientMode(); 2636df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 2646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom final int sslCtxNativePointer = (client) ? 2656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getClientSessionContext().sslCtxNativePointer : 2666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getServerSessionContext().sslCtxNativePointer; 2676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 268f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this.sslNativePointer = 0; 269f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean exception = true; 270f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 271f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 272f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.open("close"); 2736df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 27425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson if (npnProtocols != null) { 27525977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson NativeCrypto.SSL_CTX_enable_npn(sslCtxNativePointer); 27625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 27725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 278f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup server certificates and private keys. 279f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // clients will receive a call back to request certificates. 280f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!client) { 2816c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom Set<String> keyTypes = new HashSet<String>(); 2826c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String enabledCipherSuite : enabledCipherSuites) { 283ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom if (enabledCipherSuite.equals(NativeCrypto.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 284ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom continue; 285ffeba5dd766602f6e2be9caa9081744348a53c04Brian Carlstrom } 2864ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String keyType = CipherSuite.getByName(enabledCipherSuite).getServerKeyType(); 2876c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom if (keyType != null) { 2886c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom keyTypes.add(keyType); 2896c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 2906c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom } 2916c78b7b94c232063ec559436b48b33751373ecf1Brian Carlstrom for (String keyType : keyTypes) { 292f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 293f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseServerAlias(keyType, 294f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom null, 295f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom this)); 296f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 297f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException(e); 298f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 299ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 3006df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 3016df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 302f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledProtocols(sslNativePointer, enabledProtocols); 303f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.setEnabledCipherSuites(sslNativePointer, enabledCipherSuites); 304f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (useSessionTickets) { 305f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_clear_options(sslNativePointer, NativeCrypto.SSL_OP_NO_TICKET); 306f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 307f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (hostname != null) { 308f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_tlsext_host_name(sslNativePointer, hostname); 309f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 310bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 311f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom boolean enableSessionCreation = sslParameters.getEnableSessionCreation(); 312f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 313f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 314f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom enableSessionCreation); 315bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 316bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 317f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom AbstractSessionContext sessionContext; 318f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 319f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // look for client session to reuse 320f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom ClientSessionContext clientSessionContext = sslParameters.getClientSessionContext(); 321f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = clientSessionContext; 3220c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson OpenSSLSessionImpl session = getCachedClientSession(clientSessionContext); 323f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (session != null) { 324f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_session(sslNativePointer, 325f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom session.sslSessionNativePointer); 326f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 327ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } else { 328f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext = sslParameters.getServerSessionContext(); 329ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 330059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 331f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // setup peer certificate verification 332f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (client) { 333f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // TODO support for anonymous cipher would require us to 334f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // conditionally use SSL_VERIFY_NONE 335f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 336f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // needing client auth takes priority... 3370c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson boolean certRequested; 338f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslParameters.getNeedClientAuth()) { 339f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 340f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER 341f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 342f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 343f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... over just wanting it... 344f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else if (sslParameters.getWantClientAuth()) { 345f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_verify(sslNativePointer, 346f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_VERIFY_PEER); 347f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = true; 348f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // ... and it defaults properly so don't call SSL_set_verify in the common case. 349f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 350f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom certRequested = false; 351f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 352f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 353f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (certRequested) { 354f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509TrustManager trustManager = sslParameters.getTrustManager(); 355f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] issuers = trustManager.getAcceptedIssuers(); 356f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (issuers != null && issuers.length != 0) { 357f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[][] issuersBytes; 358f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 359f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom issuersBytes = NativeCrypto.encodeIssuerX509Principals(issuers); 360f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateEncodingException e) { 361f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IOException("Problem encoding principals", e); 362f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 363f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_set_client_CA_list(sslNativePointer, issuersBytes); 364ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 365ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 366ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom } 367ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 368f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Temporarily use a different timeout for the handshake process 369615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedReadTimeoutMilliseconds = getSoTimeout(); 370615225a35dbd838210270b282d1196deff643b51Brian Carlstrom int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 371f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 372f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom setSoTimeout(handshakeTimeoutMilliseconds); 373615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(handshakeTimeoutMilliseconds); 374f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 375bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 376f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom int sslSessionNativePointer; 377f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom try { 3785d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 37925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson socket.getFileDescriptor$(), this, getSoTimeout(), client, npnProtocols); 380f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } catch (CertificateException e) { 38154c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 38254c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom wrapper.initCause(e); 38354c8a07db3c2d1670c2867ba864d351cb30fecfaBrian Carlstrom throw wrapper; 384bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 385f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom byte[] sessionId = NativeCrypto.SSL_SESSION_session_id(sslSessionNativePointer); 386f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession = (OpenSSLSessionImpl) sessionContext.getSession(sessionId); 387f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (sslSession != null) { 388f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sslSession.lastAccessedTime = System.currentTimeMillis(); 389f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom NativeCrypto.SSL_SESSION_free(sslSessionNativePointer); 390f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } else { 391f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (!enableSessionCreation) { 392f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Should have been prevented by NativeCrypto.SSL_set_session_creation_enabled 393f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom throw new IllegalStateException("SSL Session may not be created"); 394f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 395f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] localCertificates 396f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_certificate(sslNativePointer)); 397f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom X509Certificate[] peerCertificates 398f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom = createCertChain(NativeCrypto.SSL_get_peer_cert_chain(sslNativePointer)); 39927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson sslSession = new OpenSSLSessionImpl(sslSessionNativePointer, localCertificates, 40027c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson peerCertificates, getPeerHostName(), getPeerPort(), sessionContext); 401f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, putSession later in handshakeCompleted() callback 402f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 403f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom sessionContext.putSession(sslSession); 404f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 405ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 406f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom 407f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // Restore the original timeout now that the handshake is complete 408f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeTimeoutMilliseconds >= 0) { 409615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoTimeout(savedReadTimeoutMilliseconds); 410615225a35dbd838210270b282d1196deff643b51Brian Carlstrom setSoWriteTimeout(savedWriteTimeoutMilliseconds); 4119d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 412adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 413f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 414f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (handshakeCompleted) { 415f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom notifyHandshakeCompletedListeners(); 416f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 417ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 418f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom exception = false; 419aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } catch (SSLProtocolException e) { 420aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom throw new SSLHandshakeException(e); 421f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } finally { 4228a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom // on exceptional exit, treat the socket as closed 423f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom if (exception) { 4248a720cceee7ce319d647738dfeda3f302879f370Brian Carlstrom close(); 425f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom } 426adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 427df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 428adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 4296d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra String getPeerHostName() { 430f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (wrappedHost != null) { 431f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return wrappedHost; 432f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 433f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom InetAddress inetAddress = super.getInetAddress(); 434f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom if (inetAddress != null) { 435f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return inetAddress.getHostName(); 436f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom } 437f52b35a5bc22f53b663ea22954135b69f8636bf4Brian Carlstrom return null; 43827c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 43927c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 4406d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra int getPeerPort() { 44127c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson return wrappedHost == null ? super.getPort() : wrappedPort; 44227c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson } 44327c744cc67c7b155bd2d47551205fb1720e7e196Jesse Wilson 444df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom /** 445df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * Return a possibly null array of X509Certificates given the 446df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom * possibly null array of DER encoded bytes. 447df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom */ 448df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom private static X509Certificate[] createCertChain(byte[][] certificatesBytes) { 449df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (certificatesBytes == null) { 450df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 451df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 452df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom X509Certificate[] certificates = new X509Certificate[certificatesBytes.length]; 453df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom for (int i = 0; i < certificatesBytes.length; i++) { 454df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 455df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom certificates[i] = new X509CertImpl(certificatesBytes[i]); 456df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 457df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return null; 458df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 459df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 460df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return certificates; 461bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 462adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 463ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom private void setCertificate(String alias) throws CertificateEncodingException, SSLException { 4646df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom if (alias == null) { 4656df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom return; 4666df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4676df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom PrivateKey privateKey = sslParameters.getKeyManager().getPrivateKey(alias); 468aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (privateKey == null) { 469aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 470aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 4716df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom X509Certificate[] certificates = sslParameters.getKeyManager().getCertificateChain(alias); 472aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom if (certificates == null) { 473aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom return; 474aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom } 475aba5e8c281fb9c6be23229246473fa0b433dd997Brian Carlstrom 47641e34229c07e8d05090560ff80558fa222623769Kenny Root if (privateKey instanceof OpenSSLRSAPrivateKey) { 47741e34229c07e8d05090560ff80558fa222623769Kenny Root OpenSSLRSAPrivateKey rsaKey = (OpenSSLRSAPrivateKey) privateKey; 47841e34229c07e8d05090560ff80558fa222623769Kenny Root OpenSSLKey key = rsaKey.getOpenSSLKey(); 47941e34229c07e8d05090560ff80558fa222623769Kenny Root NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext()); 48041e34229c07e8d05090560ff80558fa222623769Kenny Root } else if (privateKey instanceof OpenSSLDSAPrivateKey) { 48141e34229c07e8d05090560ff80558fa222623769Kenny Root OpenSSLDSAPrivateKey dsaKey = (OpenSSLDSAPrivateKey) privateKey; 48241e34229c07e8d05090560ff80558fa222623769Kenny Root OpenSSLKey key = dsaKey.getOpenSSLKey(); 48341e34229c07e8d05090560ff80558fa222623769Kenny Root NativeCrypto.SSL_use_OpenSSL_PrivateKey(sslNativePointer, key.getPkeyContext()); 48441e34229c07e8d05090560ff80558fa222623769Kenny Root } else if ("PKCS#8".equals(privateKey.getFormat())) { 48541e34229c07e8d05090560ff80558fa222623769Kenny Root byte[] privateKeyBytes = privateKey.getEncoded(); 48641e34229c07e8d05090560ff80558fa222623769Kenny Root NativeCrypto.SSL_use_PrivateKey(sslNativePointer, privateKeyBytes); 48741e34229c07e8d05090560ff80558fa222623769Kenny Root } else { 48841e34229c07e8d05090560ff80558fa222623769Kenny Root throw new SSLException("Unsupported PrivateKey format: " + privateKey.getFormat()); 48941e34229c07e8d05090560ff80558fa222623769Kenny Root } 49041e34229c07e8d05090560ff80558fa222623769Kenny Root 491ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom byte[][] certificateBytes = NativeCrypto.encodeCertificates(certificates); 4926df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_use_certificate(sslNativePointer, certificateBytes); 4936df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4946df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // checks the last installed private key and certificate, 4956df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom // so need to do this once per loop iteration 4966df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom NativeCrypto.SSL_check_private_key(sslNativePointer); 4976df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 4986df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 4990c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 500059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 501ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom throws CertificateEncodingException, SSLException { 502059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 503059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom String[] keyTypes = new String[keyTypeBytes.length]; 504059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < keyTypeBytes.length; i++) { 5054ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom keyTypes[i] = CipherSuite.getClientKeyType(keyTypeBytes[i]); 506059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 507059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom 508059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom X500Principal[] issuers; 509059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom if (asn1DerEncodedPrincipals == null) { 510059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = null; 511059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } else { 512059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers = new X500Principal[asn1DerEncodedPrincipals.length]; 513059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom for (int i = 0; i < asn1DerEncodedPrincipals.length; i++) { 514059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom issuers[i] = new X500Principal(asn1DerEncodedPrincipals[i]); 515059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 516059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom } 517059dbc04218144f985b20a228bbe98139d400d0cBrian Carlstrom setCertificate(sslParameters.getKeyManager().chooseClientAlias(keyTypes, issuers, this)); 5186df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom } 5196df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom 5200c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 521bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom public void handshakeCompleted() { 522bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom handshakeCompleted = true; 523adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 524bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // If sslSession is null, the handshake was completed during 525bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the call to NativeCrypto.SSL_do_handshake and not during a 5260c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // later read operation. That means we do not need to fix up 527bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // the SSLSession and session cache or notify 528bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // HandshakeCompletedListeners, it will be done in 529bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // startHandshake. 530bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (sslSession == null) { 531bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return; 532bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 533adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 534bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // reset session id from the native pointer and update the 535bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // appropriate cache. 536bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom sslSession.resetId(); 537bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom AbstractSessionContext sessionContext = 538bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom (sslParameters.getUseClientMode()) 539bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom ? sslParameters.getClientSessionContext() 540bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom : sslParameters.getServerSessionContext(); 541adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sessionContext.putSession(sslSession); 542bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 543bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // let listeners know we are finally done 544bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom notifyHandshakeCompletedListeners(); 545bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 546bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 547bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom private void notifyHandshakeCompletedListeners() { 548bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (listeners != null && !listeners.isEmpty()) { 549bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom // notify the listeners 550bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom HandshakeCompletedEvent event = 551bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom new HandshakeCompletedEvent(this, sslSession); 552bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (HandshakeCompletedListener listener : listeners) { 553bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom try { 554bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom listener.handshakeCompleted(event); 555bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (RuntimeException e) { 556e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // The RI runs the handlers in a separate thread, 557e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // which we do not. But we try to preserve their 558e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // behavior of logging a problem and not killing 559e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // the handshaking thread just because a listener 560e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom // has a problem. 561e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom Thread thread = Thread.currentThread(); 562e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 563bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 564bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 565bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } 566adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 567adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 5680c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 5690c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void verifyCertificateChain(byte[][] bytes, String authMethod) 5706df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom throws CertificateException { 571adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 572e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom if (bytes == null || bytes.length == 0) { 573e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom throw new SSLException("Peer sent no certificate"); 574e688a4123f165ed2905878e312b074b8c825d119Brian Carlstrom } 575bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom X509Certificate[] peerCertificateChain = new X509Certificate[bytes.length]; 576bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom for (int i = 0; i < bytes.length; i++) { 577a5c608e59f9d574ea4bc65e9dff44aae2f34fd26Brian Carlstrom peerCertificateChain[i] = new X509CertImpl(bytes[i]); 578adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 579bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom boolean client = sslParameters.getUseClientMode(); 580bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom if (client) { 5816d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra X509TrustManager x509tm = sslParameters.getTrustManager(); 5826d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra if (x509tm instanceof TrustManagerImpl) { 5836d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra TrustManagerImpl tm = (TrustManagerImpl) x509tm; 5846d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra tm.checkServerTrusted(peerCertificateChain, authMethod, wrappedHost); 5856d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } else { 5866d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra x509tm.checkServerTrusted(peerCertificateChain, authMethod); 5876d2a17ab04ab0967e3bff7fe6280066ef66d1d76Geremy Condra } 588bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } else { 5894ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom String authType = peerCertificateChain[0].getPublicKey().getAlgorithm(); 5906df6339ecd4662d351c622a59533cbbe9f275ffdBrian Carlstrom sslParameters.getTrustManager().checkClientTrusted(peerCertificateChain, 5914ae3fd787741bfe1b808f447dcb0785250024119Brian Carlstrom authType); 592adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 593bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom 594bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (CertificateException e) { 595bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom throw e; 596bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom } catch (Exception e) { 5978c4a407e34de1b348316a9175bd1c0577c887181Brian Carlstrom throw new CertificateException(e); 598adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 599adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 600adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6010c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public InputStream getInputStream() throws IOException { 6025f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 603ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 604adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (is == null) { 605adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project is = new SSLInputStream(); 606adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 607adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 608adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return is; 609adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 610adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 611adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 6120c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public OutputStream getOutputStream() throws IOException { 6135f2e6872311240319509aed64d9f58cd5b64719bBrian Carlstrom checkOpen(); 614ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (this) { 615adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (os == null) { 616adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project os = new SSLOutputStream(); 617adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 618adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 619adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return os; 620adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 621adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 622adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 623bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom /** 624adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides input data stream functionality 625adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 626adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read data received via SSL protocol. 627adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 628adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLInputStream extends InputStream { 629adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLInputStream() throws IOException { 630679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 631679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 632adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * SSLInputStream object will be created. 633adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 634679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 635adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 636adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 637adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 638adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Reads one byte. If there is no data in the underlying buffer, 639adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this operation can block until the data will be 640adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * available. 641adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @return read value. 642adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws <code>IOException</code> 643adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6444559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 645adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public int read() throws IOException { 646638000042da777f6d628d88dadde957c52597710Brian Carlstrom return Streams.readSingleByte(this); 647adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 648adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 649adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 650adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 651adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.InputStream#read(byte[],int,int) 652adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6534559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 654a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public int read(byte[] buf, int offset, int byteCount) throws IOException { 6555900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 656ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (readLock) { 65712e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 658a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 659a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 66012e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return 0; 66112e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 6625d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes return NativeCrypto.SSL_read(sslNativePointer, socket.getFileDescriptor$(), 6635d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 664adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 665adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 666adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 667adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 668adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 669adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * This inner class provides output data stream functionality 670adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * for the OpenSSL native implementation. It is used to 671adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * write data according to the encryption parameters given in SSL context. 672adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 673adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project private class SSLOutputStream extends OutputStream { 674adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project SSLOutputStream() throws IOException { 675679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson /* 676679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson * Note: When startHandshake() throws an exception, no 677ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom * SSLOutputStream object will be created. 678adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 679679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson OpenSSLSocketImpl.this.startHandshake(); 680adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 681adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 682adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 683adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 684adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(int) 685adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6864559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 687638000042da777f6d628d88dadde957c52597710Brian Carlstrom public void write(int oneByte) throws IOException { 688638000042da777f6d628d88dadde957c52597710Brian Carlstrom Streams.writeSingleByte(this, oneByte); 689adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 690adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 691adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 692adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Method acts as described in spec for superclass. 693adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see java.io.OutputStream#write(byte[],int,int) 694adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 6954559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom @Override 696a1603838fe9e865575c87982e32c6343740e464cElliott Hughes public void write(byte[] buf, int offset, int byteCount) throws IOException { 6975900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 698ef628d1464e57552403ad43366e153c1ef50b926Brian Carlstrom synchronized (writeLock) { 69912e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom checkOpen(); 700a1603838fe9e865575c87982e32c6343740e464cElliott Hughes Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 701a1603838fe9e865575c87982e32c6343740e464cElliott Hughes if (byteCount == 0) { 70212e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom return; 70312e7cb011c48b228cdeb2b799fff54d7fbfc6d85Brian Carlstrom } 7045d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_write(sslNativePointer, socket.getFileDescriptor$(), 705615225a35dbd838210270b282d1196deff643b51Brian Carlstrom OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 706adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 707adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 708adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 709adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 710adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7110c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public SSLSession getSession() { 712df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom if (sslSession == null) { 713df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom try { 714679ac55c3c037887edfc6ce6f42a23cd7c11cd12Jesse Wilson startHandshake(); 715df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } catch (IOException e) { 716df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // return an invalid session with 717df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 718df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom return SSLSessionImpl.NULL_SESSION; 719df349b3eaf4d1fa0643ab722173bc3bf20a266f5Brian Carlstrom } 720adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 721adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslSession; 722adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 723adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7240c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void addHandshakeCompletedListener( 725adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 726adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 727adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 728adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 729adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 7300c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson listeners = new ArrayList<HandshakeCompletedListener>(); 731adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 732adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project listeners.add(listener); 733adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 734adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7350c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void removeHandshakeCompletedListener( 736adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project HandshakeCompletedListener listener) { 737adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listener == null) { 738adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException("Provided listener is null"); 739adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 740adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (listeners == null) { 741adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 742adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 743adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 744adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!listeners.remove(listener)) { 745adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 746adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project "Provided listener is not registered"); 747adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 748adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 749adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7500c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getEnableSessionCreation() { 751adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getEnableSessionCreation(); 752adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 753adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7540c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnableSessionCreation(boolean flag) { 755adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setEnableSessionCreation(flag); 756adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 757adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7580c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedCipherSuites() { 759ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedCipherSuites(); 760adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 761adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7620c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledCipherSuites() { 763bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledCipherSuites.clone(); 764adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 765adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7660c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledCipherSuites(String[] suites) { 767bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledCipherSuites = NativeCrypto.checkEnabledCipherSuites(suites); 768adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 769adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7700c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getSupportedProtocols() { 771ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return NativeCrypto.getSupportedProtocols(); 772adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 773adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7740c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public String[] getEnabledProtocols() { 775bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom return enabledProtocols.clone(); 776adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 777adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 7780c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setEnabledProtocols(String[] protocols) { 779bcfb325d5b1f9529b439cc0805a1c140521510f7Brian Carlstrom enabledProtocols = NativeCrypto.checkEnabledProtocols(protocols); 780adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 781adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 782adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 7834559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables session ticket support. 7844559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 7854559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param useSessionTickets True to enable session tickets 7864559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 7874559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setUseSessionTickets(boolean useSessionTickets) { 7884559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.useSessionTickets = useSessionTickets; 7894559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 7904559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 7914559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom /** 7924559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * This method enables Server Name Indication 7934559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * 7944559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom * @param hostname the desired SNI hostname, or null to disable 7954559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom */ 7964559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom public void setHostname(String hostname) { 7974559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom this.hostname = hostname; 7984559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom } 7994559b1d37edcb5d7f1da086cf2e3290388d74f46Brian Carlstrom 8000c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getUseClientMode() { 801adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getUseClientMode(); 802adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 803adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8040c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setUseClientMode(boolean mode) { 805adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 806adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project throw new IllegalArgumentException( 8070c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson "Could not change the mode after the initial handshake has begun."); 808adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 809adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setUseClientMode(mode); 810adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 811adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8120c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getWantClientAuth() { 813adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getWantClientAuth(); 814adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 815adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8160c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public boolean getNeedClientAuth() { 817adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return sslParameters.getNeedClientAuth(); 818adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 819adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8200c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setNeedClientAuth(boolean need) { 821adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setNeedClientAuth(need); 822adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 823adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8240c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setWantClientAuth(boolean want) { 825adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project sslParameters.setWantClientAuth(want); 826adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 827adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8280c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void sendUrgentData(int data) throws IOException { 8290c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Method sendUrgentData() is not supported."); 830adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 831adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8320c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void setOOBInline(boolean on) throws SocketException { 8330c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 834adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 835adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 836615225a35dbd838210270b282d1196deff643b51Brian Carlstrom @Override public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 837615225a35dbd838210270b282d1196deff643b51Brian Carlstrom super.setSoTimeout(readTimeoutMilliseconds); 838615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.readTimeoutMilliseconds = readTimeoutMilliseconds; 839a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom } 840a4a95792af235d4bf3256eab3208f74fae8ec262Brian Carlstrom 8410c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public int getSoTimeout() throws SocketException { 842615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return readTimeoutMilliseconds; 843615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 844615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 845615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 846615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 847615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 848615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 849615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 850615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 851615225a35dbd838210270b282d1196deff643b51Brian Carlstrom StructTimeval tv = StructTimeval.fromMillis(writeTimeoutMilliseconds); 852615225a35dbd838210270b282d1196deff643b51Brian Carlstrom try { 853615225a35dbd838210270b282d1196deff643b51Brian Carlstrom Libcore.os.setsockoptTimeval(getFileDescriptor$(), SOL_SOCKET, SO_SNDTIMEO, tv); 854615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } catch (ErrnoException errnoException) { 855615225a35dbd838210270b282d1196deff643b51Brian Carlstrom throw errnoException.rethrowAsSocketException(); 856615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 857615225a35dbd838210270b282d1196deff643b51Brian Carlstrom } 858615225a35dbd838210270b282d1196deff643b51Brian Carlstrom 859615225a35dbd838210270b282d1196deff643b51Brian Carlstrom /** 860615225a35dbd838210270b282d1196deff643b51Brian Carlstrom * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 861615225a35dbd838210270b282d1196deff643b51Brian Carlstrom */ 862615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public int getSoWriteTimeout() throws SocketException { 863615225a35dbd838210270b282d1196deff643b51Brian Carlstrom return writeTimeoutMilliseconds; 864adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 865adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 8669d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor /** 8679d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * Set the handshake timeout on this socket. This timeout is specified in 8689d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor * milliseconds and will be used only during the handshake process. 8699d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor */ 870615225a35dbd838210270b282d1196deff643b51Brian Carlstrom public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 871615225a35dbd838210270b282d1196deff643b51Brian Carlstrom this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 8729d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor } 8739d48f97ae59510bac2b91dac2cc22d519cbf1bc7Dan Egnor 8740c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson @Override public void close() throws IOException { 8750c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // TODO: Close SSL sockets using a background thread so they close gracefully. 876adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 877adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (handshakeLock) { 878adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!handshakeStarted) { 8790c58d22d44cfb56f0c80f0fa1c69297ba45f3afcJesse Wilson // prevent further attempts to start handshake 880adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project handshakeStarted = true; 881ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 882adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 883ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom free(); 884adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 885df9c090e85c4d052cdd17b5f981819be86a56737Brian Carlstrom if (socket != this) { 886adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (autoClose && !socket.isClosed()) socket.close(); 887adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } else { 888adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (!super.isClosed()) super.close(); 889adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 890adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 891ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom 892adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project return; 893adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 894adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 895adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 896adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project synchronized (this) { 897adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 898783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom // Interrupt any outstanding reads or writes before taking the writeLock and readLock 899783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom NativeCrypto.SSL_interrupt(sslNativePointer); 900df9f5967a3b8dc2f61183d155791393b67980511Brian Carlstrom 901783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (writeLock) { 902783004cceef470884b3ee6946cbbfc4af0f28ae7Brian Carlstrom synchronized (readLock) { 903adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project // Shut down the SSL connection, per se. 904adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project try { 905adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project if (handshakeStarted) { 9065900e5546059f05d5e58e5732e4d08d83b8b7574Brad Fitzpatrick BlockGuard.getThreadPolicy().onNetwork(); 9075d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes NativeCrypto.SSL_shutdown(sslNativePointer, socket.getFileDescriptor$(), 9085d3f5200f3511c9a7107bcc0a996c7afa1b39aafElliott Hughes this); 909adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9101c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom } catch (IOException ignored) { 911adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /* 9121c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * Note that although close() can throw 9131c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * IOException, the RI does not throw if there 9141c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * is problem sending a "close notify" which 9151c64b3adb85345659ac60ad82216268acba18764Brian Carlstrom * can happen if the underlying socket is closed. 916adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 917d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } finally { 918d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom /* 919d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * Even if the above call failed, it is still safe to free 920d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * the native structs, and we need to do so lest we leak 921d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom * memory. 922d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom */ 923d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom free(); 924d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom 925d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (socket != this) { 926d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (autoClose && !socket.isClosed()) { 927d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom socket.close(); 928d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 929d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } else { 930d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom if (!super.isClosed()) { 931d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom super.close(); 932d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 933d3433cea484f380ab2c889c10e9d9d3268046a6cBrian Carlstrom } 934adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 935adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 936adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 937adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 938adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 939adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 940ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom private void free() { 941ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom if (sslNativePointer == 0) { 942ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom return; 943ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 944ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom NativeCrypto.SSL_free(sslNativePointer); 945ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom sslNativePointer = 0; 946f7aab022dcbfcd8f27b409ab92b4bca4a84d0b8aBrian Carlstrom guard.close(); 947ecaf759ba374a3e53613c97b47920bf520bb93cfBrian Carlstrom } 948adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 949e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom @Override protected void finalize() throws Throwable { 950e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom try { 951e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom /* 952e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * Just worry about our own state. Notably we do not try and 953e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * close anything. The SocketImpl, either our own 954e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * PlainSocketImpl, or the Socket we are wrapping, will do 955e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * that. This might mean we do not properly SSL_shutdown, but 956e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * if you want to do that, properly close the socket yourself. 957e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * 958e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * The reason why we don't try to SSL_shutdown, is that there 959e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * can be a race between finalizers where the PlainSocketImpl 960e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * finalizer runs first and closes the socket. However, in the 961e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * meanwhile, the underlying file descriptor could be reused 962e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * for another purpose. If we call SSL_shutdown, the 963e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * underlying socket BIOs still have the old file descriptor 964e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * and will write the close notify to some unsuspecting 965e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom * reader. 966e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom */ 96712f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom if (guard != null) { 96812f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom guard.warnIfOpen(); 96912f2d8e2760b78c673b7a187b9062b3938a03147Brian Carlstrom } 970e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom free(); 971e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } finally { 972e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom super.finalize(); 973e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom } 974adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 9753267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey 9763267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey @Override 9773267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey public FileDescriptor getFileDescriptor$() { 9783267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey if (socket == this) { 9793267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return super.getFileDescriptor$(); 9803267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } else { 9813267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey return socket.getFileDescriptor$(); 9823267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 9833267a46b52d848e1e9e20c226512688f0c50d4c3Jeff Sharkey } 98425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 98525977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 98625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Returns the protocol agreed upon by client and server, or null if no 98725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocol was agreed upon. 98825977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 98925977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public byte[] getNpnSelectedProtocol() { 990600dc4949de6bf5608e5f5a5214cde59299b683aJesse Wilson return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 99125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 99225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson 99325977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson /** 99425977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * Sets the list of protocols this peer is interested in. If null no 99525977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * protocols will be used. 99625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson * 9971982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * @param npnProtocols a non-empty array of protocol names. From 9981982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 9991982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * strings. The length byte itself is not included in the length. A byte 10001982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson * string of length 0 is invalid. No byte string may be truncated.". 100125977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson */ 100225977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson public void setNpnProtocols(byte[] npnProtocols) { 10031982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson if (npnProtocols != null && npnProtocols.length == 0) { 10041982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson throw new IllegalArgumentException("npnProtocols.length == 0"); 10051982194cb9067e3311ac491b4d02a6ead611fd59Jesse Wilson } 100625977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson this.npnProtocols = npnProtocols; 100725977e422febea04dac9fb9c35d7271d55d3b6b8Jesse Wilson } 1008adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 1009