Home | History | Annotate | Download | only in ssl
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.conscrypt.javax.net.ssl;
     18 
     19 import static org.conscrypt.TestUtils.UTF_8;
     20 import static org.junit.Assert.assertArrayEquals;
     21 import static org.junit.Assert.assertEquals;
     22 import static org.junit.Assert.assertFalse;
     23 import static org.junit.Assert.assertNotNull;
     24 import static org.junit.Assert.assertNotSame;
     25 import static org.junit.Assert.assertNull;
     26 import static org.junit.Assert.assertSame;
     27 import static org.junit.Assert.assertTrue;
     28 import static org.junit.Assert.fail;
     29 import static org.junit.Assume.assumeFalse;
     30 import static org.junit.Assume.assumeNoException;
     31 import static org.junit.Assume.assumeTrue;
     32 
     33 import java.io.ByteArrayInputStream;
     34 import java.io.DataInputStream;
     35 import java.io.EOFException;
     36 import java.io.IOException;
     37 import java.io.InputStream;
     38 import java.io.OutputStream;
     39 import java.lang.Thread.UncaughtExceptionHandler;
     40 import java.lang.reflect.Method;
     41 import java.math.BigInteger;
     42 import java.net.ConnectException;
     43 import java.net.InetAddress;
     44 import java.net.InetSocketAddress;
     45 import java.net.ServerSocket;
     46 import java.net.Socket;
     47 import java.net.SocketException;
     48 import java.net.SocketTimeoutException;
     49 import java.security.AlgorithmParameters;
     50 import java.security.InvalidAlgorithmParameterException;
     51 import java.security.InvalidKeyException;
     52 import java.security.InvalidParameterException;
     53 import java.security.Key;
     54 import java.security.KeyManagementException;
     55 import java.security.NoSuchAlgorithmException;
     56 import java.security.Principal;
     57 import java.security.PrivateKey;
     58 import java.security.Provider;
     59 import java.security.PublicKey;
     60 import java.security.SecureRandom;
     61 import java.security.Security;
     62 import java.security.Signature;
     63 import java.security.SignatureException;
     64 import java.security.SignatureSpi;
     65 import java.security.cert.Certificate;
     66 import java.security.cert.CertificateException;
     67 import java.security.cert.X509Certificate;
     68 import java.security.interfaces.ECKey;
     69 import java.security.interfaces.ECPrivateKey;
     70 import java.security.interfaces.RSAKey;
     71 import java.security.interfaces.RSAPrivateKey;
     72 import java.security.spec.AlgorithmParameterSpec;
     73 import java.security.spec.ECParameterSpec;
     74 import java.util.ArrayList;
     75 import java.util.Arrays;
     76 import java.util.Collections;
     77 import java.util.List;
     78 import java.util.Locale;
     79 import java.util.concurrent.Callable;
     80 import java.util.concurrent.ExecutorService;
     81 import java.util.concurrent.Executors;
     82 import java.util.concurrent.Future;
     83 import java.util.concurrent.ThreadFactory;
     84 import java.util.concurrent.TimeUnit;
     85 import javax.crypto.BadPaddingException;
     86 import javax.crypto.Cipher;
     87 import javax.crypto.CipherSpi;
     88 import javax.crypto.IllegalBlockSizeException;
     89 import javax.crypto.NoSuchPaddingException;
     90 import javax.crypto.SecretKey;
     91 import javax.crypto.ShortBufferException;
     92 import javax.crypto.spec.SecretKeySpec;
     93 import javax.net.ServerSocketFactory;
     94 import javax.net.SocketFactory;
     95 import javax.net.ssl.ExtendedSSLSession;
     96 import javax.net.ssl.HandshakeCompletedEvent;
     97 import javax.net.ssl.HandshakeCompletedListener;
     98 import javax.net.ssl.KeyManager;
     99 import javax.net.ssl.SNIHostName;
    100 import javax.net.ssl.SNIServerName;
    101 import javax.net.ssl.SSLContext;
    102 import javax.net.ssl.SSLEngine;
    103 import javax.net.ssl.SSLException;
    104 import javax.net.ssl.SSLHandshakeException;
    105 import javax.net.ssl.SSLParameters;
    106 import javax.net.ssl.SSLPeerUnverifiedException;
    107 import javax.net.ssl.SSLProtocolException;
    108 import javax.net.ssl.SSLServerSocket;
    109 import javax.net.ssl.SSLSession;
    110 import javax.net.ssl.SSLSocket;
    111 import javax.net.ssl.SSLSocketFactory;
    112 import javax.net.ssl.StandardConstants;
    113 import javax.net.ssl.TrustManager;
    114 import javax.net.ssl.X509KeyManager;
    115 import javax.net.ssl.X509TrustManager;
    116 import libcore.java.security.StandardNames;
    117 import libcore.tlswire.handshake.CipherSuite;
    118 import libcore.tlswire.handshake.ClientHello;
    119 import libcore.tlswire.handshake.CompressionMethod;
    120 import libcore.tlswire.handshake.EllipticCurve;
    121 import libcore.tlswire.handshake.EllipticCurvesHelloExtension;
    122 import libcore.tlswire.handshake.HandshakeMessage;
    123 import libcore.tlswire.handshake.HelloExtension;
    124 import libcore.tlswire.handshake.ServerNameHelloExtension;
    125 import libcore.tlswire.record.TlsProtocols;
    126 import libcore.tlswire.record.TlsRecord;
    127 import libcore.tlswire.util.TlsProtocolVersion;
    128 import org.conscrypt.Conscrypt;
    129 import org.conscrypt.TestUtils;
    130 import org.conscrypt.java.security.TestKeyStore;
    131 import org.junit.After;
    132 import org.junit.Before;
    133 import org.junit.Test;
    134 import org.junit.runner.RunWith;
    135 import org.junit.runners.JUnit4;
    136 import tests.net.DelegatingSSLSocketFactory;
    137 import tests.util.ForEachRunner;
    138 import tests.util.ForEachRunner.Callback;
    139 import tests.util.Pair;
    140 
    141 @RunWith(JUnit4.class)
    142 public class SSLSocketTest {
    143     private ExecutorService executor;
    144     private ThreadGroup threadGroup;
    145 
    146     @Before
    147     public void setup() {
    148         threadGroup = new ThreadGroup("SSLSocketTest");
    149         executor = Executors.newCachedThreadPool(new ThreadFactory() {
    150             @Override
    151             public Thread newThread(Runnable r) {
    152                 return new Thread(threadGroup, r);
    153             }
    154         });
    155     }
    156 
    157     @After
    158     public void teardown() throws InterruptedException {
    159         executor.shutdownNow();
    160         executor.awaitTermination(5, TimeUnit.SECONDS);
    161     }
    162 
    163     @Test
    164     public void test_SSLSocket_defaultConfiguration() throws Exception {
    165         SSLConfigurationAsserts.assertSSLSocketDefaultConfiguration(
    166                 (SSLSocket) SSLSocketFactory.getDefault().createSocket());
    167     }
    168 
    169     @Test
    170     public void test_SSLSocket_getSupportedCipherSuites_returnsCopies() throws Exception {
    171         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    172         SSLSocket ssl = (SSLSocket) sf.createSocket();
    173         assertNotSame(ssl.getSupportedCipherSuites(), ssl.getSupportedCipherSuites());
    174     }
    175 
    176     @Test
    177     public void test_SSLSocket_getSupportedCipherSuites_connect() throws Exception {
    178         // note the rare usage of non-RSA keys
    179         TestKeyStore testKeyStore = new TestKeyStore.Builder()
    180                                             .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA")
    181                                             .aliasPrefix("rsa-dsa-ec")
    182                                             .ca(true)
    183                                             .build();
    184         StringBuilder error = new StringBuilder();
    185         test_SSLSocket_getSupportedCipherSuites_connect(testKeyStore, error);
    186         if (error.length() > 0) {
    187             throw new Exception("One or more problems in "
    188                     + "test_SSLSocket_getSupportedCipherSuites_connect:\n" + error);
    189         }
    190     }
    191     private void test_SSLSocket_getSupportedCipherSuites_connect(
    192             TestKeyStore testKeyStore, StringBuilder error) throws Exception {
    193         String clientToServerString = "this is sent from the client to the server...";
    194         String serverToClientString = "... and this from the server to the client";
    195         byte[] clientToServer = clientToServerString.getBytes(UTF_8);
    196         byte[] serverToClient = serverToClientString.getBytes(UTF_8);
    197         KeyManager pskKeyManager =
    198                 PSKKeyManagerProxy.getConscryptPSKKeyManager(new PSKKeyManagerProxy() {
    199                     @Override
    200                     protected SecretKey getKey(
    201                             String identityHint, String identity, Socket socket) {
    202                         return newKey();
    203                     }
    204 
    205                     @Override
    206                     protected SecretKey getKey(
    207                             String identityHint, String identity, SSLEngine engine) {
    208                         return newKey();
    209                     }
    210 
    211                     private SecretKey newKey() {
    212                         return new SecretKeySpec("Just an arbitrary key".getBytes(UTF_8), "RAW");
    213                     }
    214                 });
    215         TestSSLContext c = TestSSLContext.newBuilder()
    216                                    .client(testKeyStore)
    217                                    .server(testKeyStore)
    218                                    .additionalClientKeyManagers(new KeyManager[] {pskKeyManager})
    219                                    .additionalServerKeyManagers(new KeyManager[] {pskKeyManager})
    220                                    .build();
    221         String[] cipherSuites = c.clientContext.getSocketFactory().getSupportedCipherSuites();
    222         for (String cipherSuite : cipherSuites) {
    223             try {
    224                 /*
    225                  * TLS_EMPTY_RENEGOTIATION_INFO_SCSV cannot be used on
    226                  * its own, but instead in conjunction with other
    227                  * cipher suites.
    228                  */
    229                 if (cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) {
    230                     continue;
    231                 }
    232                 /*
    233                  * Similarly with the TLS_FALLBACK_SCSV suite, it is not
    234                  * a selectable suite, but is used in conjunction with
    235                  * other cipher suites.
    236                  */
    237                 if (cipherSuite.equals(StandardNames.CIPHER_SUITE_FALLBACK)) {
    238                     continue;
    239                 }
    240                 /*
    241                  * Kerberos cipher suites require external setup. See "Kerberos Requirements" in
    242                  * https://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/JSSERefGuide.html
    243                  * #KRBRequire
    244                  */
    245                 if (cipherSuite.startsWith("TLS_KRB5_")) {
    246                     continue;
    247                 }
    248                 String[] clientCipherSuiteArray =
    249                         new String[] {cipherSuite, StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION};
    250                 TestSSLSocketPair socketPair = TestSSLSocketPair.create(c).connect(
    251                         clientCipherSuiteArray, clientCipherSuiteArray);
    252                 SSLSocket server = socketPair.server;
    253                 SSLSocket client = socketPair.client;
    254                 // Check that the client can read the message sent by the server
    255                 server.getOutputStream().write(serverToClient);
    256                 byte[] clientFromServer = new byte[serverToClient.length];
    257                 readFully(client.getInputStream(), clientFromServer);
    258                 assertEquals(serverToClientString, new String(clientFromServer, UTF_8));
    259                 // Check that the server can read the message sent by the client
    260                 client.getOutputStream().write(clientToServer);
    261                 byte[] serverFromClient = new byte[clientToServer.length];
    262                 readFully(server.getInputStream(), serverFromClient);
    263                 assertEquals(clientToServerString, new String(serverFromClient, UTF_8));
    264                 // Check that the server and the client cannot read anything else
    265                 // (reads should time out)
    266                 server.setSoTimeout(10);
    267                 try {
    268                     @SuppressWarnings("unused")
    269                     int value = server.getInputStream().read();
    270                     fail();
    271                 } catch (IOException expected) {
    272                     // Ignored.
    273                 }
    274                 client.setSoTimeout(10);
    275                 try {
    276                     @SuppressWarnings("unused")
    277                     int value = client.getInputStream().read();
    278                     fail();
    279                 } catch (IOException expected) {
    280                     // Ignored.
    281                 }
    282                 client.close();
    283                 server.close();
    284             } catch (Exception maybeExpected) {
    285                 String message = ("Problem trying to connect cipher suite " + cipherSuite);
    286                 System.out.println(message);
    287                 maybeExpected.printStackTrace();
    288                 error.append(message);
    289                 error.append('\n');
    290             }
    291         }
    292         c.close();
    293     }
    294 
    295     @Test
    296     public void test_SSLSocket_getEnabledCipherSuites_returnsCopies() throws Exception {
    297         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    298         SSLSocket ssl = (SSLSocket) sf.createSocket();
    299         assertNotSame(ssl.getEnabledCipherSuites(), ssl.getEnabledCipherSuites());
    300     }
    301 
    302     @Test
    303     public void test_SSLSocket_setEnabledCipherSuites_storesCopy() throws Exception {
    304         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    305         SSLSocket ssl = (SSLSocket) sf.createSocket();
    306         String[] array = new String[] {ssl.getEnabledCipherSuites()[0]};
    307         String originalFirstElement = array[0];
    308         ssl.setEnabledCipherSuites(array);
    309         array[0] = "Modified after having been set";
    310         assertEquals(originalFirstElement, ssl.getEnabledCipherSuites()[0]);
    311     }
    312 
    313     @Test
    314     public void test_SSLSocket_setEnabledCipherSuites() throws Exception {
    315         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    316         SSLSocket ssl = (SSLSocket) sf.createSocket();
    317         try {
    318             ssl.setEnabledCipherSuites(null);
    319             fail();
    320         } catch (IllegalArgumentException expected) {
    321             // Ignored.
    322         }
    323         try {
    324             ssl.setEnabledCipherSuites(new String[1]);
    325             fail();
    326         } catch (IllegalArgumentException expected) {
    327             // Ignored.
    328         }
    329         try {
    330             ssl.setEnabledCipherSuites(new String[] {"Bogus"});
    331             fail();
    332         } catch (IllegalArgumentException expected) {
    333             // Ignored.
    334         }
    335         ssl.setEnabledCipherSuites(new String[0]);
    336         ssl.setEnabledCipherSuites(ssl.getEnabledCipherSuites());
    337         ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
    338         // Check that setEnabledCipherSuites affects getEnabledCipherSuites
    339         String[] cipherSuites = new String[] {ssl.getSupportedCipherSuites()[0]};
    340         ssl.setEnabledCipherSuites(cipherSuites);
    341         assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
    342     }
    343 
    344     @Test
    345     public void test_SSLSocket_getSupportedProtocols_returnsCopies() throws Exception {
    346         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    347         SSLSocket ssl = (SSLSocket) sf.createSocket();
    348         assertNotSame(ssl.getSupportedProtocols(), ssl.getSupportedProtocols());
    349     }
    350 
    351     @Test
    352     public void test_SSLSocket_getEnabledProtocols_returnsCopies() throws Exception {
    353         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    354         SSLSocket ssl = (SSLSocket) sf.createSocket();
    355         assertNotSame(ssl.getEnabledProtocols(), ssl.getEnabledProtocols());
    356     }
    357 
    358     @Test
    359     public void test_SSLSocket_setEnabledProtocols_storesCopy() throws Exception {
    360         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    361         SSLSocket ssl = (SSLSocket) sf.createSocket();
    362         String[] array = new String[] {ssl.getEnabledProtocols()[0]};
    363         String originalFirstElement = array[0];
    364         ssl.setEnabledProtocols(array);
    365         array[0] = "Modified after having been set";
    366         assertEquals(originalFirstElement, ssl.getEnabledProtocols()[0]);
    367     }
    368 
    369     @Test
    370     public void test_SSLSocket_setEnabledProtocols() throws Exception {
    371         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    372         SSLSocket ssl = (SSLSocket) sf.createSocket();
    373         try {
    374             ssl.setEnabledProtocols(null);
    375             fail();
    376         } catch (IllegalArgumentException expected) {
    377             // Ignored.
    378         }
    379         try {
    380             ssl.setEnabledProtocols(new String[1]);
    381             fail();
    382         } catch (IllegalArgumentException expected) {
    383             // Ignored.
    384         }
    385         try {
    386             ssl.setEnabledProtocols(new String[] {"Bogus"});
    387             fail();
    388         } catch (IllegalArgumentException expected) {
    389             // Ignored.
    390         }
    391         ssl.setEnabledProtocols(new String[0]);
    392         ssl.setEnabledProtocols(ssl.getEnabledProtocols());
    393         ssl.setEnabledProtocols(ssl.getSupportedProtocols());
    394         // Check that setEnabledProtocols affects getEnabledProtocols
    395         for (String protocol : ssl.getSupportedProtocols()) {
    396             if ("SSLv2Hello".equals(protocol)) {
    397                 try {
    398                     ssl.setEnabledProtocols(new String[] {protocol});
    399                     fail("Should fail when SSLv2Hello is set by itself");
    400                 } catch (IllegalArgumentException expected) {
    401                     // Ignored.
    402                 }
    403             } else {
    404                 String[] protocols = new String[] {protocol};
    405                 ssl.setEnabledProtocols(protocols);
    406                 assertEquals(Arrays.deepToString(protocols),
    407                         Arrays.deepToString(ssl.getEnabledProtocols()));
    408             }
    409         }
    410     }
    411 
    412     /**
    413      * Tests that when the client has a hole in their supported protocol list, the
    414      * lower span of contiguous protocols is used in practice.
    415      */
    416     @Test
    417     public void test_SSLSocket_noncontiguousProtocols_useLower() throws Exception {
    418         TestSSLContext c = TestSSLContext.create();
    419         SSLContext serverContext = c.serverContext;
    420         SSLContext clientContext = c.clientContext;
    421         SSLSocket client = (SSLSocket)
    422                 clientContext.getSocketFactory().createSocket(c.host, c.port);
    423         client.setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1"});
    424         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    425         server.setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1.1", "TLSv1"});
    426         ExecutorService executor = Executors.newSingleThreadExecutor();
    427         Future<Void> future = executor.submit(new Callable<Void>() {
    428             @Override public Void call() throws Exception {
    429                 server.startHandshake();
    430                 return null;
    431             }
    432         });
    433         executor.shutdown();
    434         client.startHandshake();
    435 
    436         assertEquals("TLSv1", client.getSession().getProtocol());
    437 
    438         future.get();
    439         client.close();
    440         server.close();
    441         c.close();
    442     }
    443 
    444     /**
    445      * Tests that protocol negotiation succeeds when the highest-supported protocol
    446      * for both client and server isn't supported by the other.
    447      */
    448     @Test
    449     public void test_SSLSocket_noncontiguousProtocols_canNegotiate() throws Exception {
    450         TestSSLContext c = TestSSLContext.create();
    451         SSLContext serverContext = c.serverContext;
    452         SSLContext clientContext = c.clientContext;
    453         SSLSocket client = (SSLSocket)
    454                 clientContext.getSocketFactory().createSocket(c.host, c.port);
    455         client.setEnabledProtocols(new String[] {"TLSv1.2", "TLSv1"});
    456         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    457         server.setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1"});
    458         ExecutorService executor = Executors.newSingleThreadExecutor();
    459         Future<Void> future = executor.submit(new Callable<Void>() {
    460             @Override public Void call() throws Exception {
    461                 server.startHandshake();
    462                 return null;
    463             }
    464         });
    465         executor.shutdown();
    466         client.startHandshake();
    467 
    468         assertEquals("TLSv1", client.getSession().getProtocol());
    469 
    470         future.get();
    471         client.close();
    472         server.close();
    473         c.close();
    474     }
    475 
    476     @Test
    477     public void test_SSLSocket_getSession() throws Exception {
    478         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    479         SSLSocket ssl = (SSLSocket) sf.createSocket();
    480         SSLSession session = ssl.getSession();
    481         assertNotNull(session);
    482         assertFalse(session.isValid());
    483     }
    484 
    485     @Test
    486     public void test_SSLSocket_getHandshakeSession() throws Exception {
    487         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
    488         SSLSocket socket = (SSLSocket) sf.createSocket();
    489         SSLSession session = getHandshakeSession(socket);
    490         assertNull(session);
    491     }
    492 
    493     @Test
    494     public void test_SSLSocket_startHandshake() throws Exception {
    495         final TestSSLContext c = TestSSLContext.create();
    496         SSLSocket client =
    497                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    498         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    499         Future<Void> future = runAsync(new Callable<Void>() {
    500             @Override
    501             public Void call() throws Exception {
    502                 server.startHandshake();
    503                 assertNotNull(server.getSession());
    504                 assertNull(getHandshakeSession(server));
    505                 try {
    506                     server.getSession().getPeerCertificates();
    507                     fail();
    508                 } catch (SSLPeerUnverifiedException expected) {
    509                     // Ignored.
    510                 }
    511                 Certificate[] localCertificates = server.getSession().getLocalCertificates();
    512                 assertNotNull(localCertificates);
    513                 TestKeyStore.assertChainLength(localCertificates);
    514                 assertNotNull(localCertificates[0]);
    515                 TestSSLContext
    516                     .assertServerCertificateChain(c.serverTrustManager, localCertificates);
    517                 TestSSLContext.assertCertificateInKeyStore(localCertificates[0], c.serverKeyStore);
    518                 return null;
    519             }
    520         });
    521         client.startHandshake();
    522         assertNotNull(client.getSession());
    523         assertNull(client.getSession().getLocalCertificates());
    524         Certificate[] peerCertificates = client.getSession().getPeerCertificates();
    525         assertNotNull(peerCertificates);
    526         TestKeyStore.assertChainLength(peerCertificates);
    527         assertNotNull(peerCertificates[0]);
    528         TestSSLContext.assertServerCertificateChain(c.clientTrustManager, peerCertificates);
    529         TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
    530         future.get();
    531         client.close();
    532         server.close();
    533         c.close();
    534     }
    535     private static final class SSLServerSessionIdCallable implements Callable<byte[]> {
    536         private final SSLSocket server;
    537         private SSLServerSessionIdCallable(SSLSocket server) {
    538             this.server = server;
    539         }
    540         @Override
    541         public byte[] call() throws Exception {
    542             server.startHandshake();
    543             assertNotNull(server.getSession());
    544             assertNotNull(server.getSession().getId());
    545             return server.getSession().getId();
    546         }
    547     }
    548 
    549     @Test
    550     public void test_SSLSocket_confirmSessionReuse() throws Exception {
    551         final TestSSLContext c = TestSSLContext.create();
    552         final SSLSocket client1 = (SSLSocket) c.clientContext.getSocketFactory().createSocket(
    553                 c.host.getHostName(), c.port);
    554         final SSLSocket server1 = (SSLSocket) c.serverSocket.accept();
    555         final Future<byte[]> future1 = runAsync(new SSLServerSessionIdCallable(server1));
    556         client1.startHandshake();
    557         assertNotNull(client1.getSession());
    558         assertNotNull(client1.getSession().getId());
    559         final byte[] clientSessionId1 = client1.getSession().getId();
    560         final byte[] serverSessionId1 = future1.get();
    561         assertTrue(Arrays.equals(clientSessionId1, serverSessionId1));
    562         client1.close();
    563         server1.close();
    564         final SSLSocket client2 = (SSLSocket) c.clientContext.getSocketFactory().createSocket(
    565                 c.host.getHostName(), c.port);
    566         final SSLSocket server2 = (SSLSocket) c.serverSocket.accept();
    567         final Future<byte[]> future2 = runAsync(new SSLServerSessionIdCallable(server2));
    568         client2.startHandshake();
    569         assertNotNull(client2.getSession());
    570         assertNotNull(client2.getSession().getId());
    571         final byte[] clientSessionId2 = client2.getSession().getId();
    572         final byte[] serverSessionId2 = future2.get();
    573         assertTrue(Arrays.equals(clientSessionId2, serverSessionId2));
    574         client2.close();
    575         server2.close();
    576         assertTrue(Arrays.equals(clientSessionId1, clientSessionId2));
    577         c.close();
    578     }
    579 
    580     @Test
    581     public void test_SSLSocket_NoEnabledCipherSuites_Failure() throws Exception {
    582         TestSSLContext c = TestSSLContext.newBuilder()
    583                                    .useDefaults(false)
    584                                    .clientContext(SSLContext.getDefault())
    585                                    .serverContext(SSLContext.getDefault())
    586                                    .build();
    587         SSLSocket client =
    588                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    589         client.setEnabledCipherSuites(new String[0]);
    590         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    591         Future<Void> future = runAsync(new Callable<Void>() {
    592             @Override
    593             public Void call() throws Exception {
    594                 try {
    595                     server.startHandshake();
    596                     fail();
    597                 } catch (SSLHandshakeException expected) {
    598                     // Ignored.
    599                 }
    600                 return null;
    601             }
    602         });
    603         try {
    604             client.startHandshake();
    605             fail();
    606         } catch (SSLHandshakeException expected) {
    607             // Ignored.
    608         }
    609         future.get();
    610         server.close();
    611         client.close();
    612         c.close();
    613     }
    614 
    615     @Test
    616     public void test_SSLSocket_startHandshake_noKeyStore() throws Exception {
    617         TestSSLContext c = TestSSLContext.newBuilder()
    618                                    .useDefaults(false)
    619                                    .clientContext(SSLContext.getDefault())
    620                                    .serverContext(SSLContext.getDefault())
    621                                    .build();
    622         SSLSocket client =
    623                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    624         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    625         Future<Void> future = runAsync(new Callable<Void>() {
    626             @Override
    627             public Void call() throws Exception {
    628                 try {
    629                     server.startHandshake();
    630                     fail();
    631                 } catch (SSLHandshakeException expected) {
    632                     // Ignored.
    633                 }
    634                 return null;
    635             }
    636         });
    637         try {
    638             client.startHandshake();
    639             fail();
    640         } catch (SSLHandshakeException expected) {
    641             // Ignored.
    642         }
    643         future.get();
    644         server.close();
    645         client.close();
    646         c.close();
    647     }
    648 
    649     @Test
    650     public void test_SSLSocket_startHandshake_noClientCertificate() throws Exception {
    651         TestSSLContext c = TestSSLContext.create();
    652         SSLContext clientContext = c.clientContext;
    653         SSLSocket client =
    654                 (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port);
    655         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    656         Future<Void> future = runAsync(new Callable<Void>() {
    657             @Override
    658             public Void call() throws Exception {
    659                 server.startHandshake();
    660                 return null;
    661             }
    662         });
    663         client.startHandshake();
    664         future.get();
    665         client.close();
    666         server.close();
    667         c.close();
    668     }
    669 
    670     @Test
    671     public void test_SSLSocket_HandshakeCompletedListener() throws Exception {
    672         final TestSSLContext c = TestSSLContext.create();
    673         final SSLSocket client =
    674                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    675         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    676         Future<Void> future = runAsync(new Callable<Void>() {
    677             @Override
    678             public Void call() throws Exception {
    679                 server.startHandshake();
    680                 return null;
    681             }
    682         });
    683         final boolean[] handshakeCompletedListenerCalled = new boolean[1];
    684         client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
    685             @Override
    686             public void handshakeCompleted(HandshakeCompletedEvent event) {
    687                 try {
    688                     SSLSession session = event.getSession();
    689                     String cipherSuite = event.getCipherSuite();
    690                     Certificate[] localCertificates = event.getLocalCertificates();
    691                     Certificate[] peerCertificates = event.getPeerCertificates();
    692                     javax.security.cert.X509Certificate[] peerCertificateChain =
    693                         event.getPeerCertificateChain();
    694                     Principal peerPrincipal = event.getPeerPrincipal();
    695                     Principal localPrincipal = event.getLocalPrincipal();
    696                     Socket socket = event.getSocket();
    697                     assertNotNull(session);
    698                     byte[] id = session.getId();
    699                     assertNotNull(id);
    700                     assertEquals(32, id.length);
    701                     assertNotNull(c.clientContext.getClientSessionContext().getSession(id));
    702 
    703                     assertNotNull(cipherSuite);
    704                     assertTrue(
    705                         Arrays.asList(client.getEnabledCipherSuites()).contains(cipherSuite));
    706                     assertTrue(Arrays.asList(c.serverSocket.getEnabledCipherSuites())
    707                         .contains(cipherSuite));
    708                     assertNull(localCertificates);
    709                     assertNotNull(peerCertificates);
    710                     TestKeyStore.assertChainLength(peerCertificates);
    711                     assertNotNull(peerCertificates[0]);
    712                     TestSSLContext
    713                         .assertServerCertificateChain(c.clientTrustManager, peerCertificates);
    714                     TestSSLContext
    715                         .assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
    716                     assertNotNull(peerCertificateChain);
    717                     TestKeyStore.assertChainLength(peerCertificateChain);
    718                     assertNotNull(peerCertificateChain[0]);
    719                     TestSSLContext.assertCertificateInKeyStore(
    720                         peerCertificateChain[0].getSubjectDN(), c.serverKeyStore);
    721                     assertNotNull(peerPrincipal);
    722                     TestSSLContext.assertCertificateInKeyStore(peerPrincipal, c.serverKeyStore);
    723                     assertNull(localPrincipal);
    724                     assertNotNull(socket);
    725                     assertSame(client, socket);
    726                     assertNull(getHandshakeSession((SSLSocket) socket));
    727                     synchronized (handshakeCompletedListenerCalled) {
    728                         handshakeCompletedListenerCalled[0] = true;
    729                         handshakeCompletedListenerCalled.notify();
    730                     }
    731                     handshakeCompletedListenerCalled[0] = true;
    732                 } catch (RuntimeException e) {
    733                     throw e;
    734                 } catch (Exception e) {
    735                     throw new RuntimeException(e);
    736                 }
    737             }
    738         });
    739         client.startHandshake();
    740         future.get();
    741         assertNotNull(
    742                 c.serverContext.getServerSessionContext().getSession(client.getSession().getId()));
    743         synchronized (handshakeCompletedListenerCalled) {
    744             while (!handshakeCompletedListenerCalled[0]) {
    745                 handshakeCompletedListenerCalled.wait();
    746             }
    747         }
    748         client.close();
    749         server.close();
    750         c.close();
    751     }
    752     private static final class TestUncaughtExceptionHandler implements UncaughtExceptionHandler {
    753         Throwable actualException;
    754         @Override
    755         public void uncaughtException(Thread thread, Throwable ex) {
    756             assertNull(actualException);
    757             actualException = ex;
    758         }
    759     }
    760 
    761     @Test
    762     public void test_SSLSocket_HandshakeCompletedListener_RuntimeException() throws Exception {
    763         final Thread self = Thread.currentThread();
    764         final UncaughtExceptionHandler original = self.getUncaughtExceptionHandler();
    765         final RuntimeException expectedException = new RuntimeException("expected");
    766         final TestUncaughtExceptionHandler test = new TestUncaughtExceptionHandler();
    767         self.setUncaughtExceptionHandler(test);
    768         final TestSSLContext c = TestSSLContext.create();
    769         final SSLSocket client =
    770                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    771         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    772         Future<Void> future = runAsync(new Callable<Void>() {
    773             @Override
    774             public Void call() throws Exception {
    775                 server.startHandshake();
    776                 return null;
    777             }
    778         });
    779         client.addHandshakeCompletedListener(new HandshakeCompletedListener() {
    780             @Override
    781             public void handshakeCompleted(HandshakeCompletedEvent event) {
    782                 throw expectedException;
    783             }
    784         });
    785         client.startHandshake();
    786         future.get();
    787         client.close();
    788         server.close();
    789         c.close();
    790         assertSame(expectedException, test.actualException);
    791         self.setUncaughtExceptionHandler(original);
    792     }
    793 
    794     @Test
    795     public void test_SSLSocket_getUseClientMode() throws Exception {
    796         TestSSLContext c = TestSSLContext.create();
    797         SSLSocket client =
    798                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    799         SSLSocket server = (SSLSocket) c.serverSocket.accept();
    800         assertTrue(client.getUseClientMode());
    801         assertFalse(server.getUseClientMode());
    802         client.close();
    803         server.close();
    804         c.close();
    805     }
    806 
    807     @Test
    808     public void testClientMode_normal() throws Exception {
    809         // Client is client and server is server.
    810         test_SSLSocket_setUseClientMode(true, false);
    811     }
    812 
    813     @Test(expected = SSLHandshakeException.class)
    814     public void testClientMode_reverse() throws Exception {
    815         // Client is server and server is client.
    816         test_SSLSocket_setUseClientMode(false, true);
    817     }
    818 
    819     @Test(expected = SSLHandshakeException.class)
    820     public void testClientMode_bothClient() throws Exception {
    821         test_SSLSocket_setUseClientMode(true, true);
    822     }
    823 
    824     @Test
    825     public void testClientMode_bothServer() throws Exception {
    826         try {
    827             test_SSLSocket_setUseClientMode(false, false);
    828             fail();
    829         } catch (SocketTimeoutException expected) {
    830             // Ignore
    831         } catch (SSLHandshakeException expected) {
    832             // Depending on the timing of the socket closures, this can happen as well.
    833             assertTrue("Unexpected handshake error: " + expected.getMessage(),
    834                     expected.getMessage().toLowerCase().contains("connection closed"));
    835         }
    836     }
    837 
    838     private void test_SSLSocket_setUseClientMode(
    839             final boolean clientClientMode, final boolean serverClientMode) throws Exception {
    840         TestSSLContext c = TestSSLContext.create();
    841         SSLSocket client =
    842                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    843         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    844         Future<IOException> future = runAsync(new Callable<IOException>() {
    845             @Override
    846             public IOException call() throws Exception {
    847                 try {
    848                     if (!serverClientMode) {
    849                         server.setSoTimeout(1000);
    850                     }
    851                     server.setUseClientMode(serverClientMode);
    852                     server.startHandshake();
    853                     return null;
    854                 } catch (SSLHandshakeException e) {
    855                     return e;
    856                 } catch (SocketTimeoutException e) {
    857                     return e;
    858                 }
    859             }
    860         });
    861         if (!clientClientMode) {
    862             client.setSoTimeout(1000);
    863         }
    864         client.setUseClientMode(clientClientMode);
    865         client.startHandshake();
    866         IOException ioe = future.get();
    867         if (ioe != null) {
    868             throw ioe;
    869         }
    870         client.close();
    871         server.close();
    872         c.close();
    873     }
    874 
    875     @Test
    876     public void test_SSLSocket_setUseClientMode_afterHandshake() throws Exception {
    877         // can't set after handshake
    878         TestSSLSocketPair pair = TestSSLSocketPair.create().connect();
    879         try {
    880             pair.server.setUseClientMode(false);
    881             fail();
    882         } catch (IllegalArgumentException expected) {
    883             // Ignored.
    884         }
    885         try {
    886             pair.client.setUseClientMode(false);
    887             fail();
    888         } catch (IllegalArgumentException expected) {
    889             // Ignored.
    890         }
    891     }
    892 
    893     @Test
    894     public void test_SSLSocket_untrustedServer() throws Exception {
    895         TestSSLContext c =
    896                 TestSSLContext.create(TestKeyStore.getClientCA2(), TestKeyStore.getServer());
    897         SSLSocket client =
    898                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    899         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    900         Future<Void> future = runAsync(new Callable<Void>() {
    901             @Override
    902             public Void call() throws Exception {
    903                 try {
    904                     server.startHandshake();
    905                     fail();
    906                 } catch (SSLHandshakeException expected) {
    907                     // Ignored.
    908                 }
    909                 return null;
    910             }
    911         });
    912         try {
    913             client.startHandshake();
    914             fail();
    915         } catch (SSLHandshakeException expected) {
    916             assertTrue(expected.getCause() instanceof CertificateException);
    917         }
    918         future.get();
    919         client.close();
    920         server.close();
    921         c.close();
    922     }
    923 
    924     @Test
    925     public void test_SSLSocket_clientAuth() throws Exception {
    926         TestSSLContext c = TestSSLContext.create(
    927                 TestKeyStore.getClientCertificate(), TestKeyStore.getServer());
    928         SSLSocket client =
    929                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
    930         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
    931         Future<Void> future = runAsync(new Callable<Void>() {
    932             @Override
    933             public Void call() throws Exception {
    934                 assertFalse(server.getWantClientAuth());
    935                 assertFalse(server.getNeedClientAuth());
    936                 // confirm turning one on by itself
    937                 server.setWantClientAuth(true);
    938                 assertTrue(server.getWantClientAuth());
    939                 assertFalse(server.getNeedClientAuth());
    940                 // confirm turning setting on toggles the other
    941                 server.setNeedClientAuth(true);
    942                 assertFalse(server.getWantClientAuth());
    943                 assertTrue(server.getNeedClientAuth());
    944                 // confirm toggling back
    945                 server.setWantClientAuth(true);
    946                 assertTrue(server.getWantClientAuth());
    947                 assertFalse(server.getNeedClientAuth());
    948                 server.startHandshake();
    949                 return null;
    950             }
    951         });
    952         client.startHandshake();
    953         assertNotNull(client.getSession().getLocalCertificates());
    954         TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
    955         TestSSLContext.assertClientCertificateChain(
    956                 c.clientTrustManager, client.getSession().getLocalCertificates());
    957         future.get();
    958         client.close();
    959         server.close();
    960         c.close();
    961     }
    962 
    963     @Test
    964     public void test_SSLSocket_clientAuth_bogusAlias() throws Exception {
    965         TestSSLContext c = TestSSLContext.create();
    966         SSLContext clientContext = SSLContext.getInstance("TLS");
    967         X509KeyManager keyManager = new X509KeyManager() {
    968             @Override
    969             public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) {
    970                 return "bogus";
    971             }
    972             @Override
    973             public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) {
    974                 throw new AssertionError();
    975             }
    976             @Override
    977             public X509Certificate[] getCertificateChain(String alias) {
    978                 // return null for "bogus" alias
    979                 return null;
    980             }
    981             @Override
    982             public String[] getClientAliases(String keyType, Principal[] issuers) {
    983                 throw new AssertionError();
    984             }
    985             @Override
    986             public String[] getServerAliases(String keyType, Principal[] issuers) {
    987                 throw new AssertionError();
    988             }
    989             @Override
    990             public PrivateKey getPrivateKey(String alias) {
    991                 // return null for "bogus" alias
    992                 return null;
    993             }
    994         };
    995         clientContext.init(
    996                 new KeyManager[] {keyManager}, new TrustManager[] {c.clientTrustManager}, null);
    997         SSLSocket client =
    998                 (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port);
    999         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1000         Future<Void> future = runAsync(new Callable<Void>() {
   1001             @Override
   1002             public Void call() throws Exception {
   1003                 try {
   1004                     server.setNeedClientAuth(true);
   1005                     server.startHandshake();
   1006                     fail();
   1007                 } catch (SSLHandshakeException expected) {
   1008                     // Ignored.
   1009                 }
   1010                 return null;
   1011             }
   1012         });
   1013         try {
   1014             client.startHandshake();
   1015             fail();
   1016         } catch (SSLHandshakeException expected) {
   1017             // before we would get a NullPointerException from passing
   1018             // due to the null PrivateKey return by the X509KeyManager.
   1019         }
   1020         future.get();
   1021         client.close();
   1022         server.close();
   1023         c.close();
   1024     }
   1025 
   1026     @Test
   1027     public void test_SSLSocket_clientAuth_OpaqueKey_RSA() throws Exception {
   1028         run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientCertificate());
   1029     }
   1030 
   1031     @Test
   1032     public void test_SSLSocket_clientAuth_OpaqueKey_EC_RSA() throws Exception {
   1033         run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientEcRsaCertificate());
   1034     }
   1035 
   1036     @Test
   1037     public void test_SSLSocket_clientAuth_OpaqueKey_EC_EC() throws Exception {
   1038         run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore.getClientEcEcCertificate());
   1039     }
   1040     private void run_SSLSocket_clientAuth_OpaqueKey(TestKeyStore keyStore) throws Exception {
   1041         try {
   1042             Security.insertProviderAt(new OpaqueProvider(), 1);
   1043             final TestSSLContext c = TestSSLContext.create(keyStore, TestKeyStore.getServer());
   1044             SSLContext clientContext = SSLContext.getInstance("TLS");
   1045             final X509KeyManager delegateKeyManager = (X509KeyManager) c.clientKeyManagers[0];
   1046             X509KeyManager keyManager = new X509KeyManager() {
   1047                 @Override
   1048                 public String chooseClientAlias(
   1049                         String[] keyType, Principal[] issuers, Socket socket) {
   1050                     return delegateKeyManager.chooseClientAlias(keyType, issuers, socket);
   1051                 }
   1052                 @Override
   1053                 public String chooseServerAlias(
   1054                         String keyType, Principal[] issuers, Socket socket) {
   1055                     return delegateKeyManager.chooseServerAlias(keyType, issuers, socket);
   1056                 }
   1057                 @Override
   1058                 public X509Certificate[] getCertificateChain(String alias) {
   1059                     return delegateKeyManager.getCertificateChain(alias);
   1060                 }
   1061                 @Override
   1062                 public String[] getClientAliases(String keyType, Principal[] issuers) {
   1063                     return delegateKeyManager.getClientAliases(keyType, issuers);
   1064                 }
   1065                 @Override
   1066                 public String[] getServerAliases(String keyType, Principal[] issuers) {
   1067                     return delegateKeyManager.getServerAliases(keyType, issuers);
   1068                 }
   1069                 @Override
   1070                 public PrivateKey getPrivateKey(String alias) {
   1071                     PrivateKey privKey = delegateKeyManager.getPrivateKey(alias);
   1072                     if (privKey instanceof RSAPrivateKey) {
   1073                         return new OpaqueDelegatingRSAPrivateKey((RSAPrivateKey) privKey);
   1074                     } else if (privKey instanceof ECPrivateKey) {
   1075                         return new OpaqueDelegatingECPrivateKey((ECPrivateKey) privKey);
   1076                     } else {
   1077                         return null;
   1078                     }
   1079                 }
   1080             };
   1081             clientContext.init(
   1082                     new KeyManager[] {keyManager}, new TrustManager[] {c.clientTrustManager}, null);
   1083             SSLSocket client =
   1084                     (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port);
   1085             final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1086             Future<Void> future = runAsync(new Callable<Void>() {
   1087                 @Override
   1088                 public Void call() throws Exception {
   1089                     server.setNeedClientAuth(true);
   1090                     server.startHandshake();
   1091                     return null;
   1092                 }
   1093             });
   1094             client.startHandshake();
   1095             assertNotNull(client.getSession().getLocalCertificates());
   1096             TestKeyStore.assertChainLength(client.getSession().getLocalCertificates());
   1097             TestSSLContext.assertClientCertificateChain(
   1098                     c.clientTrustManager, client.getSession().getLocalCertificates());
   1099             future.get();
   1100             client.close();
   1101             server.close();
   1102             c.close();
   1103         } finally {
   1104             Security.removeProvider(OpaqueProvider.NAME);
   1105         }
   1106     }
   1107     @SuppressWarnings("serial")
   1108     public static class OpaqueProvider extends Provider {
   1109         static final String NAME = "OpaqueProvider";
   1110         public OpaqueProvider() {
   1111             super(NAME, 1.0, "test provider");
   1112             put("Signature.NONEwithRSA", OpaqueSignatureSpi.RSA.class.getName());
   1113             put("Signature.NONEwithECDSA", OpaqueSignatureSpi.ECDSA.class.getName());
   1114             put("Cipher.RSA/ECB/NoPadding", OpaqueCipherSpi.class.getName());
   1115         }
   1116     }
   1117     protected static class OpaqueSignatureSpi extends SignatureSpi {
   1118         private final String algorithm;
   1119         private Signature delegate;
   1120         OpaqueSignatureSpi(String algorithm) {
   1121             this.algorithm = algorithm;
   1122         }
   1123         public final static class RSA extends OpaqueSignatureSpi {
   1124             public RSA() {
   1125                 super("NONEwithRSA");
   1126             }
   1127         }
   1128         public final static class ECDSA extends OpaqueSignatureSpi {
   1129             public ECDSA() {
   1130                 super("NONEwithECDSA");
   1131             }
   1132         }
   1133         @Override
   1134         protected void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
   1135             fail("Cannot verify");
   1136         }
   1137         @Override
   1138         protected void engineInitSign(PrivateKey privateKey) throws InvalidKeyException {
   1139             DelegatingPrivateKey opaqueKey = (DelegatingPrivateKey) privateKey;
   1140             try {
   1141                 delegate = Signature.getInstance(algorithm);
   1142             } catch (NoSuchAlgorithmException e) {
   1143                 throw new InvalidKeyException(e);
   1144             }
   1145             delegate.initSign(opaqueKey.getDelegate());
   1146         }
   1147         @Override
   1148         protected void engineUpdate(byte b) throws SignatureException {
   1149             delegate.update(b);
   1150         }
   1151         @Override
   1152         protected void engineUpdate(byte[] b, int off, int len) throws SignatureException {
   1153             delegate.update(b, off, len);
   1154         }
   1155         @Override
   1156         protected byte[] engineSign() throws SignatureException {
   1157             return delegate.sign();
   1158         }
   1159         @Override
   1160         protected boolean engineVerify(byte[] sigBytes) throws SignatureException {
   1161             return delegate.verify(sigBytes);
   1162         }
   1163         @SuppressWarnings("deprecation")
   1164         @Override
   1165         protected void engineSetParameter(String param, Object value)
   1166                 throws InvalidParameterException {
   1167             delegate.setParameter(param, value);
   1168         }
   1169         @SuppressWarnings("deprecation")
   1170         @Override
   1171         protected Object engineGetParameter(String param) throws InvalidParameterException {
   1172             return delegate.getParameter(param);
   1173         }
   1174     }
   1175     public static class OpaqueCipherSpi extends CipherSpi {
   1176         private Cipher delegate;
   1177         public OpaqueCipherSpi() {}
   1178         @Override
   1179         protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
   1180             fail();
   1181         }
   1182         @Override
   1183         protected void engineSetPadding(String padding) throws NoSuchPaddingException {
   1184             fail();
   1185         }
   1186         @Override
   1187         protected int engineGetBlockSize() {
   1188             return delegate.getBlockSize();
   1189         }
   1190         @Override
   1191         protected int engineGetOutputSize(int inputLen) {
   1192             return delegate.getOutputSize(inputLen);
   1193         }
   1194         @Override
   1195         protected byte[] engineGetIV() {
   1196             return delegate.getIV();
   1197         }
   1198         @Override
   1199         protected AlgorithmParameters engineGetParameters() {
   1200             return delegate.getParameters();
   1201         }
   1202         @Override
   1203         protected void engineInit(int opmode, Key key, SecureRandom random)
   1204                 throws InvalidKeyException {
   1205             getCipher();
   1206             delegate.init(opmode, key, random);
   1207         }
   1208         void getCipher() throws InvalidKeyException {
   1209             try {
   1210                 delegate = Cipher.getInstance("RSA/ECB/NoPadding");
   1211             } catch (NoSuchAlgorithmException e) {
   1212                 throw new InvalidKeyException(e);
   1213             } catch (NoSuchPaddingException e) {
   1214                 throw new InvalidKeyException(e);
   1215             }
   1216         }
   1217         @Override
   1218         protected void engineInit(
   1219                 int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)
   1220                 throws InvalidKeyException, InvalidAlgorithmParameterException {
   1221             getCipher();
   1222             delegate.init(opmode, key, params, random);
   1223         }
   1224         @Override
   1225         protected void engineInit(
   1226                 int opmode, Key key, AlgorithmParameters params, SecureRandom random)
   1227                 throws InvalidKeyException, InvalidAlgorithmParameterException {
   1228             getCipher();
   1229             delegate.init(opmode, key, params, random);
   1230         }
   1231         @Override
   1232         protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
   1233             return delegate.update(input, inputOffset, inputLen);
   1234         }
   1235         @Override
   1236         protected int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
   1237                 int outputOffset) throws ShortBufferException {
   1238             return delegate.update(input, inputOffset, inputLen, output, outputOffset);
   1239         }
   1240         @Override
   1241         protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
   1242                 throws IllegalBlockSizeException, BadPaddingException {
   1243             return delegate.update(input, inputOffset, inputLen);
   1244         }
   1245         @Override
   1246         protected int engineDoFinal(
   1247                 byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)
   1248                 throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
   1249             return delegate.doFinal(input, inputOffset, inputLen, output, outputOffset);
   1250         }
   1251     }
   1252     private interface DelegatingPrivateKey { PrivateKey getDelegate(); }
   1253     @SuppressWarnings("serial")
   1254     private static class OpaqueDelegatingECPrivateKey
   1255             implements ECKey, PrivateKey, DelegatingPrivateKey {
   1256         private final ECPrivateKey delegate;
   1257         OpaqueDelegatingECPrivateKey(ECPrivateKey delegate) {
   1258             this.delegate = delegate;
   1259         }
   1260         @Override
   1261         public PrivateKey getDelegate() {
   1262             return delegate;
   1263         }
   1264         @Override
   1265         public String getAlgorithm() {
   1266             return delegate.getAlgorithm();
   1267         }
   1268         @Override
   1269         public String getFormat() {
   1270             return null;
   1271         }
   1272         @Override
   1273         public byte[] getEncoded() {
   1274             return null;
   1275         }
   1276         @Override
   1277         public ECParameterSpec getParams() {
   1278             return delegate.getParams();
   1279         }
   1280     }
   1281     @SuppressWarnings("serial")
   1282     private static class OpaqueDelegatingRSAPrivateKey
   1283             implements RSAKey, PrivateKey, DelegatingPrivateKey {
   1284         private final RSAPrivateKey delegate;
   1285         OpaqueDelegatingRSAPrivateKey(RSAPrivateKey delegate) {
   1286             this.delegate = delegate;
   1287         }
   1288         @Override
   1289         public String getAlgorithm() {
   1290             return delegate.getAlgorithm();
   1291         }
   1292         @Override
   1293         public String getFormat() {
   1294             return null;
   1295         }
   1296         @Override
   1297         public byte[] getEncoded() {
   1298             return null;
   1299         }
   1300         @Override
   1301         public BigInteger getModulus() {
   1302             return delegate.getModulus();
   1303         }
   1304         @Override
   1305         public PrivateKey getDelegate() {
   1306             return delegate;
   1307         }
   1308     }
   1309 
   1310     @Test
   1311     public void test_SSLSocket_TrustManagerRuntimeException() throws Exception {
   1312         TestSSLContext c = TestSSLContext.create();
   1313         SSLContext clientContext = SSLContext.getInstance("TLS");
   1314         X509TrustManager trustManager = new X509TrustManager() {
   1315             @Override
   1316             public void checkClientTrusted(X509Certificate[] chain, String authType)
   1317                     throws CertificateException {
   1318                 throw new AssertionError();
   1319             }
   1320             @Override
   1321             public void checkServerTrusted(X509Certificate[] chain, String authType)
   1322                     throws CertificateException {
   1323                 throw new RuntimeException(); // throw a RuntimeException from custom TrustManager
   1324             }
   1325             @Override
   1326             public X509Certificate[] getAcceptedIssuers() {
   1327                 throw new AssertionError();
   1328             }
   1329         };
   1330         clientContext.init(null, new TrustManager[] {trustManager}, null);
   1331         SSLSocket client =
   1332                 (SSLSocket) clientContext.getSocketFactory().createSocket(c.host, c.port);
   1333         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1334         Future<Void> future = runAsync(new Callable<Void>() {
   1335             @Override
   1336             public Void call() throws Exception {
   1337                 try {
   1338                     server.startHandshake();
   1339                     fail();
   1340                 } catch (SSLHandshakeException expected) {
   1341                     // Ignored.
   1342                 }
   1343                 return null;
   1344             }
   1345         });
   1346         try {
   1347             client.startHandshake();
   1348             fail();
   1349         } catch (SSLHandshakeException expected) {
   1350             // before we would get a RuntimeException from checkServerTrusted.
   1351         }
   1352         future.get();
   1353         client.close();
   1354         server.close();
   1355         c.close();
   1356     }
   1357 
   1358     @Test
   1359     public void test_SSLSocket_getEnableSessionCreation() throws Exception {
   1360         TestSSLContext c = TestSSLContext.create();
   1361         SSLSocket client =
   1362                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
   1363         SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1364         assertTrue(client.getEnableSessionCreation());
   1365         assertTrue(server.getEnableSessionCreation());
   1366         client.close();
   1367         server.close();
   1368         c.close();
   1369     }
   1370 
   1371     @Test
   1372     public void test_SSLSocket_setEnableSessionCreation_server() throws Exception {
   1373         TestSSLContext c = TestSSLContext.create();
   1374         SSLSocket client =
   1375                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
   1376         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1377         Future<Void> future = runAsync(new Callable<Void>() {
   1378             @Override
   1379             public Void call() throws Exception {
   1380                 server.setEnableSessionCreation(false);
   1381                 try {
   1382                     server.startHandshake();
   1383                     fail();
   1384                 } catch (SSLException expected) {
   1385                     // Ignored.
   1386                 }
   1387                 return null;
   1388             }
   1389         });
   1390         try {
   1391             client.startHandshake();
   1392             fail();
   1393         } catch (SSLException expected) {
   1394             // Ignored.
   1395         }
   1396         future.get();
   1397         client.close();
   1398         server.close();
   1399         c.close();
   1400     }
   1401 
   1402     @Test
   1403     public void test_SSLSocket_setEnableSessionCreation_client() throws Exception {
   1404         TestSSLContext c = TestSSLContext.create();
   1405         SSLSocket client =
   1406                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
   1407         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1408         Future<Void> future = runAsync(new Callable<Void>() {
   1409             @Override
   1410             public Void call() throws Exception {
   1411                 try {
   1412                     server.startHandshake();
   1413                     fail();
   1414                 } catch (SSLException expected) {
   1415                     // Ignored.
   1416                 }
   1417                 return null;
   1418             }
   1419         });
   1420         client.setEnableSessionCreation(false);
   1421         try {
   1422             client.startHandshake();
   1423             fail();
   1424         } catch (SSLException expected) {
   1425             // Ignored.
   1426         }
   1427         future.get();
   1428         client.close();
   1429         server.close();
   1430         c.close();
   1431     }
   1432 
   1433     @Test
   1434     public void test_SSLSocket_getSSLParameters() throws Exception {
   1435         TestUtils.assumeSetEndpointIdentificationAlgorithmAvailable();
   1436         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
   1437         SSLSocket ssl = (SSLSocket) sf.createSocket();
   1438         SSLParameters p = ssl.getSSLParameters();
   1439         assertNotNull(p);
   1440         String[] cipherSuites = p.getCipherSuites();
   1441         assertNotSame(cipherSuites, ssl.getEnabledCipherSuites());
   1442         assertEquals(Arrays.asList(cipherSuites), Arrays.asList(ssl.getEnabledCipherSuites()));
   1443         String[] protocols = p.getProtocols();
   1444         assertNotSame(protocols, ssl.getEnabledProtocols());
   1445         assertEquals(Arrays.asList(protocols), Arrays.asList(ssl.getEnabledProtocols()));
   1446         assertEquals(p.getWantClientAuth(), ssl.getWantClientAuth());
   1447         assertEquals(p.getNeedClientAuth(), ssl.getNeedClientAuth());
   1448         assertNull(p.getEndpointIdentificationAlgorithm());
   1449         p.setEndpointIdentificationAlgorithm(null);
   1450         assertNull(p.getEndpointIdentificationAlgorithm());
   1451         p.setEndpointIdentificationAlgorithm("HTTPS");
   1452         assertEquals("HTTPS", p.getEndpointIdentificationAlgorithm());
   1453         p.setEndpointIdentificationAlgorithm("FOO");
   1454         assertEquals("FOO", p.getEndpointIdentificationAlgorithm());
   1455     }
   1456 
   1457     @Test
   1458     public void test_SSLSocket_setSSLParameters() throws Exception {
   1459         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
   1460         SSLSocket ssl = (SSLSocket) sf.createSocket();
   1461         String[] defaultCipherSuites = ssl.getEnabledCipherSuites();
   1462         String[] defaultProtocols = ssl.getEnabledProtocols();
   1463         String[] supportedCipherSuites = ssl.getSupportedCipherSuites();
   1464         String[] supportedProtocols = ssl.getSupportedProtocols();
   1465         {
   1466             SSLParameters p = new SSLParameters();
   1467             ssl.setSSLParameters(p);
   1468             assertEquals(Arrays.asList(defaultCipherSuites),
   1469                     Arrays.asList(ssl.getEnabledCipherSuites()));
   1470             assertEquals(Arrays.asList(defaultProtocols), Arrays.asList(ssl.getEnabledProtocols()));
   1471         }
   1472         {
   1473             SSLParameters p = new SSLParameters(supportedCipherSuites, supportedProtocols);
   1474             ssl.setSSLParameters(p);
   1475             assertEquals(Arrays.asList(supportedCipherSuites),
   1476                     Arrays.asList(ssl.getEnabledCipherSuites()));
   1477             assertEquals(
   1478                     Arrays.asList(supportedProtocols), Arrays.asList(ssl.getEnabledProtocols()));
   1479         }
   1480         {
   1481             SSLParameters p = new SSLParameters();
   1482             p.setNeedClientAuth(true);
   1483             assertFalse(ssl.getNeedClientAuth());
   1484             assertFalse(ssl.getWantClientAuth());
   1485             ssl.setSSLParameters(p);
   1486             assertTrue(ssl.getNeedClientAuth());
   1487             assertFalse(ssl.getWantClientAuth());
   1488             p.setWantClientAuth(true);
   1489             assertTrue(ssl.getNeedClientAuth());
   1490             assertFalse(ssl.getWantClientAuth());
   1491             ssl.setSSLParameters(p);
   1492             assertFalse(ssl.getNeedClientAuth());
   1493             assertTrue(ssl.getWantClientAuth());
   1494             p.setWantClientAuth(false);
   1495             assertFalse(ssl.getNeedClientAuth());
   1496             assertTrue(ssl.getWantClientAuth());
   1497             ssl.setSSLParameters(p);
   1498             assertFalse(ssl.getNeedClientAuth());
   1499             assertFalse(ssl.getWantClientAuth());
   1500         }
   1501     }
   1502 
   1503     @Test
   1504     public void test_SSLSocket_close() throws Exception {
   1505         TestSSLSocketPair pair = TestSSLSocketPair.create().connect();
   1506         SSLSocket server = pair.server;
   1507         SSLSocket client = pair.client;
   1508         assertFalse(server.isClosed());
   1509         assertFalse(client.isClosed());
   1510         InputStream input = client.getInputStream();
   1511         OutputStream output = client.getOutputStream();
   1512         server.close();
   1513         client.close();
   1514         assertTrue(server.isClosed());
   1515         assertTrue(client.isClosed());
   1516         // close after close is okay...
   1517         server.close();
   1518         client.close();
   1519         // ...so are a lot of other operations...
   1520         HandshakeCompletedListener l = new HandshakeCompletedListener() {
   1521             @Override
   1522             public void handshakeCompleted(HandshakeCompletedEvent e) {
   1523             }
   1524         };
   1525         client.addHandshakeCompletedListener(l);
   1526         assertNotNull(client.getEnabledCipherSuites());
   1527         assertNotNull(client.getEnabledProtocols());
   1528         client.getEnableSessionCreation();
   1529         client.getNeedClientAuth();
   1530         assertNotNull(client.getSession());
   1531         assertNotNull(client.getSSLParameters());
   1532         assertNotNull(client.getSupportedProtocols());
   1533         client.getUseClientMode();
   1534         client.getWantClientAuth();
   1535         client.removeHandshakeCompletedListener(l);
   1536         client.setEnabledCipherSuites(new String[0]);
   1537         client.setEnabledProtocols(new String[0]);
   1538         client.setEnableSessionCreation(false);
   1539         client.setNeedClientAuth(false);
   1540         client.setSSLParameters(client.getSSLParameters());
   1541         client.setWantClientAuth(false);
   1542         // ...but some operations are expected to give SocketException...
   1543         try {
   1544             client.startHandshake();
   1545             fail();
   1546         } catch (SocketException expected) {
   1547             // Ignored.
   1548         }
   1549         try {
   1550             client.getInputStream();
   1551             fail();
   1552         } catch (SocketException expected) {
   1553             // Ignored.
   1554         }
   1555         try {
   1556             client.getOutputStream();
   1557             fail();
   1558         } catch (SocketException expected) {
   1559             // Ignored.
   1560         }
   1561         try {
   1562             @SuppressWarnings("unused")
   1563             int value = input.read();
   1564             fail();
   1565         } catch (SocketException expected) {
   1566             // Ignored.
   1567         }
   1568         try {
   1569             @SuppressWarnings("unused")
   1570             int bytesRead = input.read(null, -1, -1);
   1571             fail();
   1572         } catch (NullPointerException expected) {
   1573             // Ignored.
   1574         } catch (SocketException expected) {
   1575             // Ignored.
   1576         }
   1577         try {
   1578             output.write(-1);
   1579             fail();
   1580         } catch (SocketException expected) {
   1581             // Ignored.
   1582         }
   1583         try {
   1584             output.write(null, -1, -1);
   1585             fail();
   1586         } catch (NullPointerException expected) {
   1587             // Ignored.
   1588         } catch (SocketException expected) {
   1589             // Ignored.
   1590         }
   1591         // ... and one gives IllegalArgumentException
   1592         try {
   1593             client.setUseClientMode(false);
   1594             fail();
   1595         } catch (IllegalArgumentException expected) {
   1596             // Ignored.
   1597         }
   1598         pair.close();
   1599     }
   1600     /**
   1601      * b/3350645 Test to confirm that an SSLSocket.close() performing
   1602      * an SSL_shutdown does not throw an IOException if the peer
   1603      * socket has been closed.
   1604      */
   1605     @Test
   1606     public void test_SSLSocket_shutdownCloseOnClosedPeer() throws Exception {
   1607         TestSSLContext c = TestSSLContext.create();
   1608         final Socket underlying = new Socket(c.host, c.port);
   1609         final SSLSocket wrapping = (SSLSocket) c.clientContext.getSocketFactory().createSocket(
   1610                 underlying, c.host.getHostName(), c.port, false);
   1611         Future<Void> clientFuture = runAsync(new Callable<Void>() {
   1612             @Override
   1613             public Void call() throws Exception {
   1614                 wrapping.startHandshake();
   1615                 wrapping.getOutputStream().write(42);
   1616                 // close the underlying socket,
   1617                 // so that no SSL shutdown is sent
   1618                 underlying.close();
   1619                 wrapping.close();
   1620                 return null;
   1621             }
   1622         });
   1623         SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1624         server.startHandshake();
   1625         @SuppressWarnings("unused")
   1626         int value = server.getInputStream().read();
   1627         // wait for thread to finish so we know client is closed.
   1628         clientFuture.get();
   1629         // close should cause an SSL_shutdown which will fail
   1630         // because the peer has closed, but it shouldn't throw.
   1631         server.close();
   1632     }
   1633 
   1634     @Test
   1635     public void test_SSLSocket_endpointIdentification_Success() throws Exception {
   1636         TestUtils.assumeSetEndpointIdentificationAlgorithmAvailable();
   1637         final TestSSLContext c = TestSSLContext.create();
   1638         SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
   1639         SSLParameters p = client.getSSLParameters();
   1640         p.setEndpointIdentificationAlgorithm("HTTPS");
   1641         client.setSSLParameters(p);
   1642         client.connect(new InetSocketAddress(c.host, c.port));
   1643         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1644         Future<Void> future = runAsync(new Callable<Void>() {
   1645             @Override
   1646             public Void call() throws Exception {
   1647                 server.startHandshake();
   1648                 assertNotNull(server.getSession());
   1649                 try {
   1650                     server.getSession().getPeerCertificates();
   1651                     fail();
   1652                 } catch (SSLPeerUnverifiedException expected) {
   1653                     // Ignored.
   1654                 }
   1655                 Certificate[] localCertificates = server.getSession().getLocalCertificates();
   1656                 assertNotNull(localCertificates);
   1657                 TestKeyStore.assertChainLength(localCertificates);
   1658                 assertNotNull(localCertificates[0]);
   1659                 TestSSLContext.assertCertificateInKeyStore(localCertificates[0], c.serverKeyStore);
   1660                 return null;
   1661             }
   1662         });
   1663         client.startHandshake();
   1664         assertNotNull(client.getSession());
   1665         assertNull(client.getSession().getLocalCertificates());
   1666         Certificate[] peerCertificates = client.getSession().getPeerCertificates();
   1667         assertNotNull(peerCertificates);
   1668         TestKeyStore.assertChainLength(peerCertificates);
   1669         assertNotNull(peerCertificates[0]);
   1670         TestSSLContext.assertCertificateInKeyStore(peerCertificates[0], c.serverKeyStore);
   1671         future.get();
   1672         client.close();
   1673         server.close();
   1674         c.close();
   1675     }
   1676 
   1677     @Test
   1678     public void test_SSLSocket_endpointIdentification_Failure() throws Exception {
   1679         TestUtils.assumeSetEndpointIdentificationAlgorithmAvailable();
   1680         final TestSSLContext c = TestSSLContext.create();
   1681         SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
   1682         SSLParameters p = client.getSSLParameters();
   1683         p.setEndpointIdentificationAlgorithm("HTTPS");
   1684         client.setSSLParameters(p);
   1685         client.connect(c.getLoopbackAsHostname("unmatched.example.com", c.port));
   1686         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1687         Future<Void> future = runAsync(new Callable<Void>() {
   1688             @Override
   1689             public Void call() throws Exception {
   1690                 try {
   1691                     server.startHandshake();
   1692                     fail("Should receive SSLHandshakeException as server");
   1693                 } catch (SSLHandshakeException expected) {
   1694                     // Ignored.
   1695                 }
   1696                 return null;
   1697             }
   1698         });
   1699         try {
   1700             client.startHandshake();
   1701             fail("Should throw when hostname does not match expected");
   1702         } catch (SSLHandshakeException expected) {
   1703             // Ignored.
   1704         } finally {
   1705             try {
   1706                 future.get();
   1707             } finally {
   1708                 client.close();
   1709                 server.close();
   1710                 c.close();
   1711             }
   1712         }
   1713     }
   1714 
   1715     @Test
   1716     public void test_SSLSocket_setSoTimeout_basic() throws Exception {
   1717         ServerSocket listening = new ServerSocket(0);
   1718         Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
   1719         assertEquals(0, underlying.getSoTimeout());
   1720         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
   1721         Socket wrapping = sf.createSocket(underlying, null, -1, false);
   1722         assertEquals(0, wrapping.getSoTimeout());
   1723         // setting wrapper sets underlying and ...
   1724         int expectedTimeoutMillis = 1000; // 10 was too small because it was affected by rounding
   1725         wrapping.setSoTimeout(expectedTimeoutMillis);
   1726         // The kernel can round the requested value based on the HZ setting. We allow up to 10ms.
   1727         assertTrue(Math.abs(expectedTimeoutMillis - wrapping.getSoTimeout()) <= 10);
   1728         assertTrue(Math.abs(expectedTimeoutMillis - underlying.getSoTimeout()) <= 10);
   1729         // ... getting wrapper inspects underlying
   1730         underlying.setSoTimeout(0);
   1731         assertEquals(0, wrapping.getSoTimeout());
   1732         assertEquals(0, underlying.getSoTimeout());
   1733     }
   1734 
   1735     @Test
   1736     public void test_SSLSocket_setSoTimeout_wrapper() throws Exception {
   1737         ServerSocket listening = new ServerSocket(0);
   1738         // setSoTimeout applies to read, not connect, so connect first
   1739         Socket underlying = new Socket(listening.getInetAddress(), listening.getLocalPort());
   1740         Socket server = listening.accept();
   1741         SSLSocketFactory sf = (SSLSocketFactory) SSLSocketFactory.getDefault();
   1742         Socket clientWrapping = sf.createSocket(underlying, null, -1, false);
   1743         underlying.setSoTimeout(1);
   1744         try {
   1745             @SuppressWarnings("unused")
   1746             int value = clientWrapping.getInputStream().read();
   1747             fail();
   1748         } catch (SocketTimeoutException expected) {
   1749             // Ignored.
   1750         }
   1751         clientWrapping.close();
   1752         server.close();
   1753         underlying.close();
   1754         listening.close();
   1755     }
   1756 
   1757     @Test(expected = SocketTimeoutException.class)
   1758     public void test_SSLSocket_setSoWriteTimeout() throws Exception {
   1759         // Only run this test on Linux since it relies on non-posix methods.
   1760         assumeTrue("Test only runs on Linux. Current OS: " + osName(), isLinux());
   1761 
   1762         // In jb-mr2 it was found that we need to also set SO_RCVBUF
   1763         // to a minimal size or the write would not block.
   1764         final int receiveBufferSize = 128;
   1765         TestSSLContext c =
   1766                 TestSSLContext.newBuilder().serverReceiveBufferSize(receiveBufferSize).build();
   1767 
   1768         final SSLSocket client =
   1769                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(c.host, c.port);
   1770 
   1771         // Try to make the client SO_SNDBUF size as small as possible
   1772         // (it can default to 512k or even megabytes).  Note that
   1773         // socket(7) says that the kernel will double the request to
   1774         // leave room for its own book keeping and that the minimal
   1775         // value will be 2048. Also note that tcp(7) says the value
   1776         // needs to be set before connect(2).
   1777         int sendBufferSize = 1024;
   1778         client.setSendBufferSize(sendBufferSize);
   1779         sendBufferSize = client.getSendBufferSize();
   1780 
   1781         // Start the handshake.
   1782         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1783         Future<Void> future = runAsync(new Callable<Void>() {
   1784             @Override
   1785             public Void call() throws Exception {
   1786                 client.startHandshake();
   1787                 return null;
   1788             }
   1789         });
   1790         server.startHandshake();
   1791 
   1792         assertTrue(isConscryptSocket(client));
   1793         // The concrete class that Conscrypt returns has methods on it that have no
   1794         // equivalent on the public API (like setSoWriteTimeout), so users have
   1795         // previously used reflection to access those otherwise-inaccessible methods
   1796         // on that class.  The concrete class used to be named OpenSSLSocketImpl, so
   1797         // check that OpenSSLSocketImpl is still in the class hierarchy so applications
   1798         // that rely on getting that class back still work.
   1799         Class<?> superClass = client.getClass();
   1800         do {
   1801             superClass = superClass.getSuperclass();
   1802         } while (superClass != Object.class && !superClass.getName().endsWith("OpenSSLSocketImpl"));
   1803         assertEquals("OpenSSLSocketImpl", superClass.getSimpleName());
   1804 
   1805 
   1806         try {
   1807             setWriteTimeout(client, 1);
   1808 
   1809             // Add extra space to the write to exceed the send buffer
   1810             // size and cause the write to block.
   1811             final int extra = 1;
   1812             client.getOutputStream().write(new byte[sendBufferSize + extra]);
   1813         } finally {
   1814             future.get();
   1815             client.close();
   1816             server.close();
   1817             c.close();
   1818         }
   1819     }
   1820 
   1821     @Test
   1822     public void test_SSLSocket_reusedNpnSocket() throws Exception {
   1823         byte[] npnProtocols = new byte[] {
   1824                 8, 'h', 't', 't', 'p', '/', '1', '.', '1'
   1825         };
   1826 
   1827         final TestSSLContext c = TestSSLContext.create();
   1828         SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
   1829 
   1830         assertTrue(isConscryptSocket(client));
   1831         Class<?> actualClass = client.getClass();
   1832         Method setNpnProtocols = actualClass.getMethod("setNpnProtocols", byte[].class);
   1833 
   1834         ExecutorService executor = Executors.newSingleThreadExecutor();
   1835 
   1836         // First connection with NPN set on client and server
   1837         {
   1838             setNpnProtocols.invoke(client, npnProtocols);
   1839             client.connect(new InetSocketAddress(c.host, c.port));
   1840 
   1841             final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1842             assertTrue(isConscryptSocket(server));
   1843             setNpnProtocols.invoke(server, npnProtocols);
   1844 
   1845             Future<Void> future = executor.submit(new Callable<Void>() {
   1846                 @Override
   1847                 public Void call() throws Exception {
   1848                     server.startHandshake();
   1849                     return null;
   1850                 }
   1851             });
   1852             client.startHandshake();
   1853 
   1854             future.get();
   1855             client.close();
   1856             server.close();
   1857         }
   1858 
   1859         // Second connection with client NPN already set on the SSL context, but
   1860         // without server NPN set.
   1861         {
   1862             SSLServerSocket serverSocket = (SSLServerSocket) c.serverContext
   1863                     .getServerSocketFactory().createServerSocket(0);
   1864             InetAddress host = InetAddress.getLocalHost();
   1865             int port = serverSocket.getLocalPort();
   1866 
   1867             client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
   1868             client.connect(new InetSocketAddress(host, port));
   1869 
   1870             final SSLSocket server = (SSLSocket) serverSocket.accept();
   1871 
   1872             Future<Void> future = executor.submit(new Callable<Void>() {
   1873                 @Override
   1874                 public Void call() throws Exception {
   1875                     server.startHandshake();
   1876                     return null;
   1877                 }
   1878             });
   1879             client.startHandshake();
   1880 
   1881             future.get();
   1882             client.close();
   1883             server.close();
   1884             serverSocket.close();
   1885         }
   1886 
   1887         c.close();
   1888     }
   1889 
   1890     // TODO(nmittler): Conscrypt socket read may return -1 instead of SocketException.
   1891     @Test
   1892     public void test_SSLSocket_interrupt_readUnderlyingAndCloseUnderlying() throws Exception {
   1893         test_SSLSocket_interrupt_case(true, true);
   1894     }
   1895 
   1896     // TODO(nmittler): Conscrypt socket read may return -1 instead of SocketException.
   1897     @Test
   1898     public void test_SSLSocket_interrupt_readUnderlyingAndCloseWrapper() throws Exception {
   1899         test_SSLSocket_interrupt_case(true, false);
   1900     }
   1901 
   1902     // TODO(nmittler): FD socket gets stuck in read on Windows and OSX.
   1903     @Test
   1904     public void test_SSLSocket_interrupt_readWrapperAndCloseUnderlying() throws Exception {
   1905         test_SSLSocket_interrupt_case(false, true);
   1906     }
   1907 
   1908     // TODO(nmittler): Conscrypt socket read may return -1 instead of SocketException.
   1909     @Test
   1910     public void test_SSLSocket_interrupt_readWrapperAndCloseWrapper() throws Exception {
   1911         test_SSLSocket_interrupt_case(false, false);
   1912     }
   1913 
   1914     private void test_SSLSocket_interrupt_case(boolean readUnderlying, boolean closeUnderlying)
   1915             throws Exception {
   1916         final int readingTimeoutMillis = 5000;
   1917         TestSSLContext c = TestSSLContext.create();
   1918         final Socket underlying = new Socket(c.host, c.port);
   1919         final SSLSocket clientWrapping =
   1920                 (SSLSocket) c.clientContext.getSocketFactory().createSocket(
   1921                         underlying, c.host.getHostName(), c.port, true);
   1922 
   1923         if (isConscryptFdSocket(clientWrapping) && !readUnderlying && closeUnderlying) {
   1924             // TODO(nmittler): FD socket gets stuck in the read on Windows and OSX.
   1925             assumeFalse("Skipping interrupt test on Windows", isWindows());
   1926             assumeFalse("Skipping interrupt test on OSX", isOsx());
   1927         }
   1928 
   1929         SSLSocket server = (SSLSocket) c.serverSocket.accept();
   1930 
   1931         // Start the handshake.
   1932         Future<Void> handshakeFuture = runAsync(new Callable<Void>() {
   1933             @Override
   1934             public Void call() throws Exception {
   1935                 clientWrapping.startHandshake();
   1936                 return null;
   1937             }
   1938         });
   1939         server.startHandshake();
   1940         handshakeFuture.get();
   1941 
   1942         final Socket toRead = (readUnderlying) ? underlying : clientWrapping;
   1943         final Socket toClose = (closeUnderlying) ? underlying : clientWrapping;
   1944 
   1945         // Schedule the socket to be closed in 1 second.
   1946         Future<Void> future = runAsync(new Callable<Void>() {
   1947             @Override
   1948             public Void call() throws Exception {
   1949                 Thread.sleep(1000);
   1950                 toClose.close();
   1951                 return null;
   1952             }
   1953         });
   1954 
   1955         // Read from the socket.
   1956         try {
   1957             toRead.setSoTimeout(readingTimeoutMillis);
   1958             int read = toRead.getInputStream().read();
   1959             // In the case of reading the wrapper and closing the underlying socket,
   1960             // there is a race condition between the reading thread being woken and
   1961             // reading the socket again and the closing thread marking the file descriptor
   1962             // as invalid.  If the latter happens first, a SocketException is thrown,
   1963             // but if the former happens first it just looks like the peer closed the
   1964             // connection and a -1 return is acceptable.
   1965             if (read != -1 || readUnderlying || !closeUnderlying) {
   1966                 fail();
   1967             }
   1968         } catch (SocketTimeoutException e) {
   1969             throw e;
   1970         } catch (IOException expected) {
   1971             // Expected
   1972         }
   1973 
   1974         future.get();
   1975         server.close();
   1976         underlying.close();
   1977         server.close();
   1978     }
   1979 
   1980     /**
   1981      * b/7014266 Test to confirm that an SSLSocket.close() on one
   1982      * thread will interrupt another thread blocked reading on the same
   1983      * socket.
   1984      */
   1985     // TODO(nmittler): Interrupts do not work with the engine-based socket.
   1986     @Test
   1987     public void test_SSLSocket_interrupt_read_withoutAutoClose() throws Exception {
   1988         final int readingTimeoutMillis = 5000;
   1989         TestSSLContext c = TestSSLContext.create();
   1990         final Socket underlying = new Socket(c.host, c.port);
   1991         final SSLSocket wrapping = (SSLSocket) c.clientContext.getSocketFactory().createSocket(
   1992                 underlying, c.host.getHostName(), c.port, false);
   1993 
   1994         // TODO(nmittler): Interrupts do not work with the engine-based socket.
   1995         assumeFalse(isConscryptEngineSocket(wrapping));
   1996 
   1997         Future<Void> clientFuture = runAsync(new Callable<Void>() {
   1998             @Override
   1999             public Void call() throws Exception {
   2000                 wrapping.startHandshake();
   2001                 try {
   2002                     wrapping.setSoTimeout(readingTimeoutMillis);
   2003                     wrapping.getInputStream().read();
   2004                     fail();
   2005                 } catch (SocketException expected) {
   2006                     // Conscrypt throws an exception complaining that the socket is closed
   2007                     // if it's interrupted by a close() in the middle of a read()
   2008                     assertTrue(expected.getMessage().contains("closed"));
   2009                 }
   2010                 return null;
   2011             }
   2012         });
   2013         SSLSocket server = (SSLSocket) c.serverSocket.accept();
   2014         server.startHandshake();
   2015 
   2016         // Wait for the client to at least be in the "read" method before calling close()
   2017         Thread[] threads = new Thread[1];
   2018         threadGroup.enumerate(threads);
   2019         if (threads[0] != null) {
   2020             boolean clientInRead = false;
   2021             while (!clientInRead) {
   2022                 StackTraceElement[] elements = threads[0].getStackTrace();
   2023                 for (StackTraceElement element : elements) {
   2024                     if ("read".equals(element.getMethodName())) {
   2025                         // The client might be executing "read" but still not have reached the
   2026                         // point in which it's blocked reading. This is causing flakiness
   2027                         // (b/24367646). Delaying for a fraction of the timeout.
   2028                         Thread.sleep(1000);
   2029                         clientInRead = true;
   2030                         break;
   2031                     }
   2032                 }
   2033             }
   2034         }
   2035 
   2036         wrapping.close();
   2037 
   2038         clientFuture.get();
   2039         server.close();
   2040     }
   2041 
   2042     @Test
   2043     public void test_TestSSLSocketPair_create() {
   2044         TestSSLSocketPair test = TestSSLSocketPair.create().connect();
   2045         assertNotNull(test.c);
   2046         assertNotNull(test.server);
   2047         assertNotNull(test.client);
   2048         assertTrue(test.server.isConnected());
   2049         assertTrue(test.client.isConnected());
   2050         assertFalse(test.server.isClosed());
   2051         assertFalse(test.client.isClosed());
   2052         assertNotNull(test.server.getSession());
   2053         assertNotNull(test.client.getSession());
   2054         assertTrue(test.server.getSession().isValid());
   2055         assertTrue(test.client.getSession().isValid());
   2056         test.close();
   2057     }
   2058 
   2059     @Test
   2060     public void test_SSLSocket_ClientHello_record_size() throws Exception {
   2061         // This test checks the size of ClientHello of the default SSLSocket. TLS/SSL handshakes
   2062         // with older/unpatched F5/BIG-IP appliances are known to stall and time out when
   2063         // the fragment containing ClientHello is between 256 and 511 (inclusive) bytes long.
   2064         SSLContext sslContext = SSLContext.getInstance("TLS");
   2065         sslContext.init(null, null, null);
   2066         SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
   2067         sslSocketFactory = new DelegatingSSLSocketFactory(sslSocketFactory) {
   2068             @Override
   2069             protected SSLSocket configureSocket(SSLSocket socket) {
   2070                 // Enable SNI extension on the socket (this is typically enabled by default)
   2071                 // to increase the size of ClientHello.
   2072                 setHostname(socket);
   2073 
   2074                 // Enable Session Tickets extension on the socket (this is typically enabled
   2075                 // by default) to increase the size of ClientHello.
   2076                 enableSessionTickets(socket);
   2077                 return socket;
   2078             }
   2079         };
   2080         TlsRecord firstReceivedTlsRecord = captureTlsHandshakeFirstTlsRecord(sslSocketFactory);
   2081         assertEquals("TLS record type", TlsProtocols.HANDSHAKE, firstReceivedTlsRecord.type);
   2082         HandshakeMessage handshakeMessage = HandshakeMessage.read(
   2083                 new DataInputStream(new ByteArrayInputStream(firstReceivedTlsRecord.fragment)));
   2084         assertEquals(
   2085                 "HandshakeMessage type", HandshakeMessage.TYPE_CLIENT_HELLO, handshakeMessage.type);
   2086         int fragmentLength = firstReceivedTlsRecord.fragment.length;
   2087         if ((fragmentLength >= 256) && (fragmentLength <= 511)) {
   2088             fail("Fragment containing ClientHello is of dangerous length: " + fragmentLength
   2089                     + " bytes");
   2090         }
   2091     }
   2092 
   2093     @Test
   2094     public void test_SSLSocket_ClientHello_cipherSuites() throws Exception {
   2095         ForEachRunner.runNamed(new Callback<SSLSocketFactory>() {
   2096             @Override
   2097             public void run(SSLSocketFactory sslSocketFactory) throws Exception {
   2098                 ClientHello clientHello = SSLSocketTest.this
   2099                     .captureTlsHandshakeClientHello(sslSocketFactory);
   2100                 final String[] cipherSuites;
   2101                 // RFC 5746 allows you to send an empty "renegotiation_info" extension *or*
   2102                 // a special signaling cipher suite. The TLS API has no way to check or
   2103                 // indicate that a certain TLS extension should be used.
   2104                 HelloExtension renegotiationInfoExtension =
   2105                     clientHello.findExtensionByType(HelloExtension.TYPE_RENEGOTIATION_INFO);
   2106                 if (renegotiationInfoExtension != null
   2107                     && renegotiationInfoExtension.data.length == 1
   2108                     && renegotiationInfoExtension.data[0] == 0) {
   2109                     cipherSuites = new String[clientHello.cipherSuites.size() + 1];
   2110                     cipherSuites[clientHello.cipherSuites.size()] =
   2111                         StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION;
   2112                 } else {
   2113                     cipherSuites = new String[clientHello.cipherSuites.size()];
   2114                 }
   2115                 for (int i = 0; i < clientHello.cipherSuites.size(); i++) {
   2116                     CipherSuite cipherSuite = clientHello.cipherSuites.get(i);
   2117                     cipherSuites[i] = cipherSuite.getAndroidName();
   2118                 }
   2119                 StandardNames.assertDefaultCipherSuites(cipherSuites);
   2120             }
   2121         }, getSSLSocketFactoriesToTest());
   2122     }
   2123 
   2124     @Test
   2125     public void test_SSLSocket_ClientHello_supportedCurves() throws Exception {
   2126         ForEachRunner.runNamed(new Callback<SSLSocketFactory>() {
   2127             @Override
   2128             public void run(SSLSocketFactory sslSocketFactory) throws Exception {
   2129                 ClientHello clientHello = SSLSocketTest.this
   2130                     .captureTlsHandshakeClientHello(sslSocketFactory);
   2131                 EllipticCurvesHelloExtension ecExtension =
   2132                     (EllipticCurvesHelloExtension) clientHello.findExtensionByType(
   2133                         HelloExtension.TYPE_ELLIPTIC_CURVES);
   2134                 final String[] supportedCurves;
   2135                 if (ecExtension == null) {
   2136                     supportedCurves = new String[0];
   2137                 } else {
   2138                     assertTrue(ecExtension.wellFormed);
   2139                     supportedCurves = new String[ecExtension.supported.size()];
   2140                     for (int i = 0; i < ecExtension.supported.size(); i++) {
   2141                         EllipticCurve curve = ecExtension.supported.get(i);
   2142                         supportedCurves[i] = curve.toString();
   2143                     }
   2144                 }
   2145                 StandardNames.assertDefaultEllipticCurves(supportedCurves);
   2146             }
   2147         }, getSSLSocketFactoriesToTest());
   2148     }
   2149 
   2150     @Test
   2151     public void test_SSLSocket_ClientHello_clientProtocolVersion() throws Exception {
   2152         ForEachRunner.runNamed(new Callback<SSLSocketFactory>() {
   2153             @Override
   2154             public void run(SSLSocketFactory sslSocketFactory) throws Exception {
   2155                 ClientHello clientHello = SSLSocketTest.this
   2156                     .captureTlsHandshakeClientHello(sslSocketFactory);
   2157                 assertEquals(TlsProtocolVersion.TLSv1_2, clientHello.clientVersion);
   2158             }
   2159         }, getSSLSocketFactoriesToTest());
   2160     }
   2161 
   2162     @Test
   2163     public void test_SSLSocket_ClientHello_compressionMethods() throws Exception {
   2164         ForEachRunner.runNamed(new Callback<SSLSocketFactory>() {
   2165             @Override
   2166             public void run(SSLSocketFactory sslSocketFactory) throws Exception {
   2167                 ClientHello clientHello = SSLSocketTest.this
   2168                     .captureTlsHandshakeClientHello(sslSocketFactory);
   2169                 assertEquals(Collections.singletonList(CompressionMethod.NULL),
   2170                     clientHello.compressionMethods);
   2171             }
   2172         }, getSSLSocketFactoriesToTest());
   2173     }
   2174 
   2175     @Test
   2176     public void test_SSLSocket_ClientHello_SNI() throws Exception {
   2177         ForEachRunner.runNamed(new Callback<SSLSocketFactory>() {
   2178             @Override
   2179             public void run(SSLSocketFactory sslSocketFactory) throws Exception {
   2180                 ClientHello clientHello = SSLSocketTest.this
   2181                     .captureTlsHandshakeClientHello(sslSocketFactory);
   2182                 ServerNameHelloExtension sniExtension =
   2183                     (ServerNameHelloExtension) clientHello.findExtensionByType(
   2184                         HelloExtension.TYPE_SERVER_NAME);
   2185                 assertNotNull(sniExtension);
   2186                 assertEquals(
   2187                     Collections.singletonList("localhost.localdomain"), sniExtension.hostnames);
   2188             }
   2189         }, getSSLSocketFactoriesToTest());
   2190     }
   2191     private List<Pair<String, SSLSocketFactory>> getSSLSocketFactoriesToTest()
   2192             throws NoSuchAlgorithmException, KeyManagementException {
   2193         List<Pair<String, SSLSocketFactory>> result =
   2194                 new ArrayList<Pair<String, SSLSocketFactory>>();
   2195         result.add(Pair.of("default", (SSLSocketFactory) SSLSocketFactory.getDefault()));
   2196         for (String sslContextProtocol : StandardNames.SSL_CONTEXT_PROTOCOLS) {
   2197             SSLContext sslContext = SSLContext.getInstance(sslContextProtocol);
   2198             if (StandardNames.SSL_CONTEXT_PROTOCOLS_DEFAULT.equals(sslContextProtocol)) {
   2199                 continue;
   2200             }
   2201             sslContext.init(null, null, null);
   2202             result.add(Pair.of("SSLContext(\"" + sslContext.getProtocol() + "\")",
   2203                     sslContext.getSocketFactory()));
   2204         }
   2205         return result;
   2206     }
   2207     private ClientHello captureTlsHandshakeClientHello(SSLSocketFactory sslSocketFactory)
   2208             throws Exception {
   2209         TlsRecord record = captureTlsHandshakeFirstTlsRecord(sslSocketFactory);
   2210         assertEquals("TLS record type", TlsProtocols.HANDSHAKE, record.type);
   2211         ByteArrayInputStream fragmentIn = new ByteArrayInputStream(record.fragment);
   2212         HandshakeMessage handshakeMessage = HandshakeMessage.read(new DataInputStream(fragmentIn));
   2213         assertEquals(
   2214                 "HandshakeMessage type", HandshakeMessage.TYPE_CLIENT_HELLO, handshakeMessage.type);
   2215         // Assert that the fragment does not contain any more messages
   2216         assertEquals(0, fragmentIn.available());
   2217         return (ClientHello) handshakeMessage;
   2218     }
   2219     private TlsRecord captureTlsHandshakeFirstTlsRecord(SSLSocketFactory sslSocketFactory)
   2220             throws Exception {
   2221         byte[] firstReceivedChunk = captureTlsHandshakeFirstTransmittedChunkBytes(sslSocketFactory);
   2222         ByteArrayInputStream firstReceivedChunkIn = new ByteArrayInputStream(firstReceivedChunk);
   2223         TlsRecord record = TlsRecord.read(new DataInputStream(firstReceivedChunkIn));
   2224         // Assert that the chunk does not contain any more data
   2225         assertEquals(0, firstReceivedChunkIn.available());
   2226         return record;
   2227     }
   2228     @SuppressWarnings("FutureReturnValueIgnored")
   2229     private byte[] captureTlsHandshakeFirstTransmittedChunkBytes(
   2230             final SSLSocketFactory sslSocketFactory) throws Exception {
   2231         // Since there's no straightforward way to obtain a ClientHello from SSLSocket, this test
   2232         // does the following:
   2233         // 1. Creates a listening server socket (a plain one rather than a TLS/SSL one).
   2234         // 2. Creates a client SSLSocket, which connects to the server socket and initiates the
   2235         //    TLS/SSL handshake.
   2236         // 3. Makes the server socket accept an incoming connection on the server socket, and reads
   2237         //    the first chunk of data received. This chunk is assumed to be the ClientHello.
   2238         // NOTE: Steps 2 and 3 run concurrently.
   2239         ServerSocket listeningSocket = null;
   2240         // Some Socket operations are not interruptible via Thread.interrupt for some reason. To
   2241         // work around, we unblock these sockets using Socket.close.
   2242         final Socket[] sockets = new Socket[2];
   2243         try {
   2244             // 1. Create the listening server socket.
   2245             listeningSocket = ServerSocketFactory.getDefault().createServerSocket(0);
   2246             final ServerSocket finalListeningSocket = listeningSocket;
   2247             // 2. (in background) Wait for an incoming connection and read its first chunk.
   2248             final Future<byte[]> readFirstReceivedChunkFuture = runAsync(new Callable<byte[]>() {
   2249                 @Override
   2250                 public byte[] call() throws Exception {
   2251                     Socket socket = finalListeningSocket.accept();
   2252                     sockets[1] = socket;
   2253                     try {
   2254                         byte[] buffer = new byte[64 * 1024];
   2255                         int bytesRead = socket.getInputStream().read(buffer);
   2256                         if (bytesRead == -1) {
   2257                             throw new EOFException("Failed to read anything");
   2258                         }
   2259                         return Arrays.copyOf(buffer, bytesRead);
   2260                     } finally {
   2261                         closeQuietly(socket);
   2262                     }
   2263                 }
   2264             });
   2265             // 3. Create a client socket, connect it to the server socket, and start the TLS/SSL
   2266             //    handshake.
   2267             runAsync(new Callable<Void>() {
   2268                 @Override
   2269                 public Void call() throws Exception {
   2270                     Socket client = new Socket();
   2271                     sockets[0] = client;
   2272                     try {
   2273                         client.connect(finalListeningSocket.getLocalSocketAddress());
   2274                         // Initiate the TLS/SSL handshake which is expected to fail as soon as the
   2275                         // server socket receives a ClientHello.
   2276                         try {
   2277                             SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(client,
   2278                                     "localhost.localdomain", finalListeningSocket.getLocalPort(),
   2279                                     true);
   2280                             sslSocket.startHandshake();
   2281                             fail();
   2282                             return null;
   2283                         } catch (IOException expected) {
   2284                             // Ignored.
   2285                         }
   2286                         return null;
   2287                     } finally {
   2288                         closeQuietly(client);
   2289                     }
   2290                 }
   2291             });
   2292             // Wait for the ClientHello to arrive
   2293             return readFirstReceivedChunkFuture.get(10, TimeUnit.SECONDS);
   2294         } finally {
   2295             closeQuietly(listeningSocket);
   2296             closeQuietly(sockets[0]);
   2297             closeQuietly(sockets[1]);
   2298         }
   2299     }
   2300     // http://b/18428603
   2301     @Test
   2302     public void test_SSLSocket_getPortWithSNI() throws Exception {
   2303         TestSSLContext context = TestSSLContext.create();
   2304         SSLSocket client =
   2305             (SSLSocket) context.clientContext.getSocketFactory().createSocket();
   2306         try {
   2307             client.connect(new InetSocketAddress(context.host, context.port));
   2308             setHostname(client);
   2309             assertTrue(client.getPort() > 0);
   2310         } finally {
   2311             client.close();
   2312             context.close();
   2313         }
   2314     }
   2315 
   2316     @Test
   2317     public void test_SSLSocket_SNIHostName() throws Exception {
   2318         TestUtils.assumeSNIHostnameAvailable();
   2319         TestSSLContext c = TestSSLContext.create();
   2320         final SSLSocket client = (SSLSocket) c.clientContext.getSocketFactory().createSocket();
   2321         SSLParameters clientParams = client.getSSLParameters();
   2322         clientParams.setServerNames(
   2323                 Collections.singletonList((SNIServerName) new SNIHostName("www.example.com")));
   2324         client.setSSLParameters(clientParams);
   2325         SSLParameters serverParams = c.serverSocket.getSSLParameters();
   2326         serverParams.setSNIMatchers(
   2327                 Collections.singletonList(SNIHostName.createSNIMatcher("www\\.example\\.com")));
   2328         c.serverSocket.setSSLParameters(serverParams);
   2329         client.connect(new InetSocketAddress(c.host, c.port));
   2330         final SSLSocket server = (SSLSocket) c.serverSocket.accept();
   2331         @SuppressWarnings("unused")
   2332         Future<?> future = runAsync(new Callable<Object>() {
   2333             @Override
   2334             public Object call() throws Exception {
   2335                 client.startHandshake();
   2336                 return null;
   2337             }
   2338         });
   2339         server.startHandshake();
   2340         SSLSession serverSession = server.getSession();
   2341         assertTrue(serverSession instanceof ExtendedSSLSession);
   2342         ExtendedSSLSession extendedServerSession = (ExtendedSSLSession) serverSession;
   2343         List<SNIServerName> requestedNames = extendedServerSession.getRequestedServerNames();
   2344         assertNotNull(requestedNames);
   2345         assertEquals(1, requestedNames.size());
   2346         SNIServerName serverName = requestedNames.get(0);
   2347         assertEquals(StandardConstants.SNI_HOST_NAME, serverName.getType());
   2348         assertTrue(serverName instanceof SNIHostName);
   2349         SNIHostName serverHostName = (SNIHostName) serverName;
   2350         assertEquals("www.example.com", serverHostName.getAsciiName());
   2351     }
   2352 
   2353     @Test
   2354     public void test_SSLSocket_sendsTlsFallbackScsv_Fallback_Success() throws Exception {
   2355         TestSSLContext context = TestSSLContext.create();
   2356         final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(
   2357                 context.host, context.port);
   2358         final SSLSocket server = (SSLSocket) context.serverSocket.accept();
   2359         final String[] serverCipherSuites = server.getEnabledCipherSuites();
   2360         final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
   2361         System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
   2362         clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
   2363         Future<Void> s = runAsync(new Callable<Void>() {
   2364             @Override
   2365             public Void call() throws Exception {
   2366                 server.setEnabledProtocols(new String[]{"TLSv1.2"});
   2367                 server.setEnabledCipherSuites(serverCipherSuites);
   2368                 server.startHandshake();
   2369                 return null;
   2370             }
   2371         });
   2372         Future<Void> c = runAsync(new Callable<Void>() {
   2373             @Override
   2374             public Void call() throws Exception {
   2375                 client.setEnabledProtocols(new String[]{"TLSv1.2"});
   2376                 client.setEnabledCipherSuites(clientCipherSuites);
   2377                 client.startHandshake();
   2378                 return null;
   2379             }
   2380         });
   2381         s.get();
   2382         c.get();
   2383         client.close();
   2384         server.close();
   2385         context.close();
   2386     }
   2387     // Confirms that communication without the TLS_FALLBACK_SCSV cipher works as it always did.
   2388     @Test
   2389     public void test_SSLSocket_sendsNoTlsFallbackScsv_Fallback_Success() throws Exception {
   2390         TestSSLContext context = TestSSLContext.create();
   2391         final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(
   2392                 context.host, context.port);
   2393         final SSLSocket server = (SSLSocket) context.serverSocket.accept();
   2394         // Confirm absence of TLS_FALLBACK_SCSV.
   2395         assertFalse(Arrays.asList(client.getEnabledCipherSuites())
   2396                             .contains(StandardNames.CIPHER_SUITE_FALLBACK));
   2397         Future<Void> s = runAsync(new Callable<Void>() {
   2398             @Override
   2399             public Void call() throws Exception {
   2400                 server.setEnabledProtocols(new String[]{"TLSv1.2", "TLSv1.1"});
   2401                 server.startHandshake();
   2402                 return null;
   2403             }
   2404         });
   2405         Future<Void> c = runAsync(new Callable<Void>() {
   2406             @Override
   2407             public Void call() throws Exception {
   2408                 client.setEnabledProtocols(new String[]{"TLSv1.1"});
   2409                 client.startHandshake();
   2410                 return null;
   2411             }
   2412         });
   2413         s.get();
   2414         c.get();
   2415         client.close();
   2416         server.close();
   2417         context.close();
   2418     }
   2419 
   2420     private static void assertInappropriateFallbackIsCause(Throwable cause) {
   2421         assertTrue(cause.getMessage(),
   2422                 cause.getMessage().contains("inappropriate fallback")
   2423                         || cause.getMessage().contains("INAPPROPRIATE_FALLBACK"));
   2424     }
   2425 
   2426     @Test
   2427     public void test_SSLSocket_sendsTlsFallbackScsv_InappropriateFallback_Failure()
   2428             throws Exception {
   2429         TestSSLContext context = TestSSLContext.create();
   2430         final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(
   2431                 context.host, context.port);
   2432         final SSLSocket server = (SSLSocket) context.serverSocket.accept();
   2433         final String[] serverCipherSuites = server.getEnabledCipherSuites();
   2434         // Add TLS_FALLBACK_SCSV
   2435         final String[] clientCipherSuites = new String[serverCipherSuites.length + 1];
   2436         System.arraycopy(serverCipherSuites, 0, clientCipherSuites, 0, serverCipherSuites.length);
   2437         clientCipherSuites[serverCipherSuites.length] = StandardNames.CIPHER_SUITE_FALLBACK;
   2438         Future<Void> s = runAsync(new Callable<Void>() {
   2439             @Override
   2440             public Void call() throws Exception {
   2441                 server.setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1"});
   2442                 server.setEnabledCipherSuites(serverCipherSuites);
   2443                 try {
   2444                     server.startHandshake();
   2445                     fail("Should result in inappropriate fallback");
   2446                 } catch (SSLHandshakeException expected) {
   2447                     Throwable cause = expected.getCause();
   2448                     assertEquals(SSLProtocolException.class, cause.getClass());
   2449                     assertInappropriateFallbackIsCause(cause);
   2450                 }
   2451                 return null;
   2452             }
   2453         });
   2454         Future<Void> c = runAsync(new Callable<Void>() {
   2455             @Override
   2456             public Void call() throws Exception {
   2457                 client.setEnabledProtocols(new String[]{"TLSv1"});
   2458                 client.setEnabledCipherSuites(clientCipherSuites);
   2459                 try {
   2460                     client.startHandshake();
   2461                     fail("Should receive TLS alert inappropriate fallback");
   2462                 } catch (SSLHandshakeException expected) {
   2463                     Throwable cause = expected.getCause();
   2464                     assertEquals(SSLProtocolException.class, cause.getClass());
   2465                     assertInappropriateFallbackIsCause(cause);
   2466                 }
   2467                 return null;
   2468             }
   2469         });
   2470         s.get();
   2471         c.get();
   2472         client.close();
   2473         server.close();
   2474         context.close();
   2475     }
   2476 
   2477     @Test
   2478     public void test_SSLSocket_ClientGetsAlertDuringHandshake_HasGoodExceptionMessage()
   2479             throws Exception {
   2480         TestSSLContext context = TestSSLContext.create();
   2481         final ServerSocket listener = ServerSocketFactory.getDefault().createServerSocket(0);
   2482         final SSLSocket client = (SSLSocket) context.clientContext.getSocketFactory().createSocket(
   2483                 context.host, listener.getLocalPort());
   2484         final Socket server = listener.accept();
   2485         Future<Void> c = runAsync(new Callable<Void>() {
   2486             @Override
   2487             public Void call() throws Exception {
   2488                 try {
   2489                     client.startHandshake();
   2490                     fail("Should receive handshake exception");
   2491                 } catch (SSLHandshakeException expected) {
   2492                     assertFalse(expected.getMessage().contains("SSL_ERROR_ZERO_RETURN"));
   2493                     assertFalse(expected.getMessage().contains("You should never see this."));
   2494                 }
   2495                 return null;
   2496             }
   2497         });
   2498         Future<Void> s = runAsync(new Callable<Void>() {
   2499             @Override
   2500             public Void call() throws Exception {
   2501                 // Wait until the client sends something.
   2502                 byte[] scratch = new byte[8192];
   2503                 @SuppressWarnings("unused")
   2504                 int bytesRead = server.getInputStream().read(scratch);
   2505                 // Write a bogus TLS alert:
   2506                 // TLSv1.2 Record Layer: Alert (Level: Warning, Description: Protocol Version)
   2507                 server.getOutputStream()
   2508                     .write(new byte[]{0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x46});
   2509                 // TLSv1.2 Record Layer: Alert (Level: Warning, Description: Close Notify)
   2510                 server.getOutputStream()
   2511                     .write(new byte[]{0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00});
   2512                 return null;
   2513             }
   2514         });
   2515         c.get(5, TimeUnit.SECONDS);
   2516         s.get(5, TimeUnit.SECONDS);
   2517         client.close();
   2518         server.close();
   2519         listener.close();
   2520         context.close();
   2521     }
   2522 
   2523     @Test
   2524     public void test_SSLSocket_ServerGetsAlertDuringHandshake_HasGoodExceptionMessage()
   2525             throws Exception {
   2526         TestSSLContext context = TestSSLContext.create();
   2527         final Socket client = SocketFactory.getDefault().createSocket(context.host, context.port);
   2528         final SSLSocket server = (SSLSocket) context.serverSocket.accept();
   2529         Future<Void> s = runAsync(new Callable<Void>() {
   2530             @Override
   2531             public Void call() throws Exception {
   2532                 try {
   2533                     server.startHandshake();
   2534                     fail("Should receive handshake exception");
   2535                 } catch (SSLHandshakeException expected) {
   2536                     assertFalse(expected.getMessage().contains("SSL_ERROR_ZERO_RETURN"));
   2537                     assertFalse(expected.getMessage().contains("You should never see this."));
   2538                 }
   2539                 return null;
   2540             }
   2541         });
   2542         Future<Void> c = runAsync(new Callable<Void>() {
   2543             @Override
   2544             public Void call() throws Exception {
   2545                 // Send bogus ClientHello:
   2546                 // TLSv1.2 Record Layer: Handshake Protocol: Client Hello
   2547                 client.getOutputStream().write(new byte[]{
   2548                     (byte) 0x16, (byte) 0x03, (byte) 0x01, (byte) 0x00, (byte) 0xb9,
   2549                     (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0xb5, (byte) 0x03,
   2550                     (byte) 0x03, (byte) 0x5a, (byte) 0x31, (byte) 0xba, (byte) 0x44,
   2551                     (byte) 0x24, (byte) 0xfd, (byte) 0xf0, (byte) 0x56, (byte) 0x46,
   2552                     (byte) 0xea, (byte) 0xee, (byte) 0x1c, (byte) 0x62, (byte) 0x8f,
   2553                     (byte) 0x18, (byte) 0x04, (byte) 0xbd, (byte) 0x1c, (byte) 0xbc,
   2554                     (byte) 0xbf, (byte) 0x6d, (byte) 0x84, (byte) 0x12, (byte) 0xe9,
   2555                     (byte) 0x94, (byte) 0xf5, (byte) 0x1c, (byte) 0x15, (byte) 0x3e,
   2556                     (byte) 0x79, (byte) 0x01, (byte) 0xe2, (byte) 0x00, (byte) 0x00,
   2557                     (byte) 0x28, (byte) 0xc0, (byte) 0x2b, (byte) 0xc0, (byte) 0x2c,
   2558                     (byte) 0xc0, (byte) 0x2f, (byte) 0xc0, (byte) 0x30, (byte) 0x00,
   2559                     (byte) 0x9e, (byte) 0x00, (byte) 0x9f, (byte) 0xc0, (byte) 0x09,
   2560                     (byte) 0xc0, (byte) 0x0a, (byte) 0xc0, (byte) 0x13, (byte) 0xc0,
   2561                     (byte) 0x14, (byte) 0x00, (byte) 0x33, (byte) 0x00, (byte) 0x39,
   2562                     (byte) 0xc0, (byte) 0x07, (byte) 0xc0, (byte) 0x11, (byte) 0x00,
   2563                     (byte) 0x9c, (byte) 0x00, (byte) 0x9d, (byte) 0x00, (byte) 0x2f,
   2564                     (byte) 0x00, (byte) 0x35, (byte) 0x00, (byte) 0x05, (byte) 0x00,
   2565                     (byte) 0xff, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x64,
   2566                     (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x04, (byte) 0x03,
   2567                     (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x00, (byte) 0x0a,
   2568                     (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x32, (byte) 0x00,
   2569                     (byte) 0x0e, (byte) 0x00, (byte) 0x0d, (byte) 0x00, (byte) 0x19,
   2570                     (byte) 0x00, (byte) 0x0b, (byte) 0x00, (byte) 0x0c, (byte) 0x00,
   2571                     (byte) 0x18, (byte) 0x00, (byte) 0x09, (byte) 0x00, (byte) 0x0a,
   2572                     (byte) 0x00, (byte) 0x16, (byte) 0x00, (byte) 0x17, (byte) 0x00,
   2573                     (byte) 0x08, (byte) 0x00, (byte) 0x06, (byte) 0x00, (byte) 0x07,
   2574                     (byte) 0x00, (byte) 0x14, (byte) 0x00, (byte) 0x15, (byte) 0x00,
   2575                     (byte) 0x04, (byte) 0x00, (byte) 0x05, (byte) 0x00, (byte) 0x12,
   2576                     (byte) 0x00, (byte) 0x13, (byte) 0x00, (byte) 0x01, (byte) 0x00,
   2577                     (byte) 0x02, (byte) 0x00, (byte) 0x03, (byte) 0x00, (byte) 0x0f,
   2578                     (byte) 0x00, (byte) 0x10, (byte) 0x00, (byte) 0x11, (byte) 0x00,
   2579                     (byte) 0x0d, (byte) 0x00, (byte) 0x20, (byte) 0x00, (byte) 0x1e,
   2580                     (byte) 0x06, (byte) 0x01, (byte) 0x06, (byte) 0x02, (byte) 0x06,
   2581                     (byte) 0x03, (byte) 0x05, (byte) 0x01, (byte) 0x05, (byte) 0x02,
   2582                     (byte) 0x05, (byte) 0x03, (byte) 0x04, (byte) 0x01, (byte) 0x04,
   2583                     (byte) 0x02, (byte) 0x04, (byte) 0x03, (byte) 0x03, (byte) 0x01,
   2584                     (byte) 0x03, (byte) 0x02, (byte) 0x03, (byte) 0x03, (byte) 0x02,
   2585                     (byte) 0x01, (byte) 0x02, (byte) 0x02, (byte) 0x02, (byte) 0x03,
   2586                 });
   2587                 // Wait until the server sends something.
   2588                 byte[] scratch = new byte[8192];
   2589                 @SuppressWarnings("unused")
   2590                 int bytesRead = client.getInputStream().read(scratch);
   2591                 // Write a bogus TLS alert:
   2592                 // TLSv1.2 Record Layer: Alert (Level: Warning, Description:
   2593                 // Protocol Version)
   2594                 client.getOutputStream()
   2595                     .write(new byte[]{0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x46});
   2596                 // TLSv1.2 Record Layer: Alert (Level: Warning, Description:
   2597                 // Close Notify)
   2598                 client.getOutputStream()
   2599                     .write(new byte[]{0x15, 0x03, 0x03, 0x00, 0x02, 0x01, 0x00});
   2600                 return null;
   2601             }
   2602         });
   2603         c.get(5, TimeUnit.SECONDS);
   2604         s.get(5, TimeUnit.SECONDS);
   2605         client.close();
   2606         server.close();
   2607         context.close();
   2608     }
   2609 
   2610     @Test
   2611     public void test_SSLSocket_SSLv3Unsupported() throws Exception {
   2612         TestSSLContext context = TestSSLContext.create();
   2613         final SSLSocket client =
   2614                 (SSLSocket) context.clientContext.getSocketFactory().createSocket();
   2615         // For app compatibility, SSLv3 is stripped out when setting only.
   2616         client.setEnabledProtocols(new String[] {"SSLv3"});
   2617         assertEquals(0, client.getEnabledProtocols().length);
   2618         try {
   2619             client.setEnabledProtocols(new String[] {"SSL"});
   2620             fail("SSLSocket should not support SSL protocol");
   2621         } catch (IllegalArgumentException expected) {
   2622             // Ignored.
   2623         }
   2624     }
   2625 
   2626     // Under some circumstances, the file descriptor socket may get finalized but still
   2627     // be reused by the JDK's built-in HTTP connection reuse code.  Ensure that a
   2628     // SocketException is thrown if that happens.
   2629     @Test
   2630     public void test_SSLSocket_finalizeThrowsProperException() throws Exception {
   2631         TestSSLSocketPair test = TestSSLSocketPair.create().connect();
   2632         try {
   2633             if (isConscryptFdSocket(test.client)) {
   2634                 // The finalize method might be declared on a superclass rather than this
   2635                 // class.
   2636                 Method method = null;
   2637                 Class<?> clazz = test.client.getClass();
   2638                 while (clazz != null) {
   2639                     try {
   2640                         method = clazz.getDeclaredMethod("finalize");
   2641                         break;
   2642                     } catch (NoSuchMethodException e) {
   2643                         // Try the superclass
   2644                     }
   2645                     clazz = clazz.getSuperclass();
   2646                 }
   2647                 assertNotNull(method);
   2648                 method.setAccessible(true);
   2649                 method.invoke(test.client);
   2650                 try {
   2651                     test.client.getOutputStream().write(new byte[] { 0x01 });
   2652                     fail("The socket shouldn't work after being finalized");
   2653                 } catch (SocketException expected) {
   2654                     // Expected
   2655                 }
   2656             }
   2657         } finally {
   2658             test.close();
   2659         }
   2660     }
   2661 
   2662     @Test
   2663     public void test_SSLSocket_TlsUnique() throws Exception {
   2664         TestSSLSocketPair pair = TestSSLSocketPair.create();
   2665         try {
   2666             assertNull(Conscrypt.getTlsUnique(pair.client));
   2667             assertNull(Conscrypt.getTlsUnique(pair.server));
   2668 
   2669             pair.connect();
   2670 
   2671             byte[] clientTlsUnique = Conscrypt.getTlsUnique(pair.client);
   2672             byte[] serverTlsUnique = Conscrypt.getTlsUnique(pair.server);
   2673             assertNotNull(clientTlsUnique);
   2674             assertNotNull(serverTlsUnique);
   2675             assertArrayEquals(clientTlsUnique, serverTlsUnique);
   2676         } finally {
   2677             pair.close();
   2678         }
   2679     }
   2680 
   2681     // Tests that all cipher suites have a 12-byte tls-unique channel binding value.  If this
   2682     // test fails, that means some cipher suite has been added that uses a customized verify_data
   2683     // length and we need to update MAX_TLS_UNIQUE_LENGTH in native_crypto.cc to account for that.
   2684     @Test
   2685     public void test_SSLSocket_TlsUniqueLength() throws Exception {
   2686         // note the rare usage of non-RSA keys
   2687         TestKeyStore testKeyStore = new TestKeyStore.Builder()
   2688                 .keyAlgorithms("RSA", "DSA", "EC", "EC_RSA")
   2689                 .aliasPrefix("rsa-dsa-ec")
   2690                 .ca(true)
   2691                 .build();
   2692         KeyManager pskKeyManager =
   2693                 PSKKeyManagerProxy.getConscryptPSKKeyManager(new PSKKeyManagerProxy() {
   2694                     @Override
   2695                     protected SecretKey getKey(
   2696                             String identityHint, String identity, Socket socket) {
   2697                         return newKey();
   2698                     }
   2699 
   2700                     @Override
   2701                     protected SecretKey getKey(
   2702                             String identityHint, String identity, SSLEngine engine) {
   2703                         return newKey();
   2704                     }
   2705 
   2706                     private SecretKey newKey() {
   2707                         return new SecretKeySpec("Just an arbitrary key".getBytes(UTF_8), "RAW");
   2708                     }
   2709                 });
   2710         TestSSLContext c = TestSSLContext.newBuilder()
   2711                 .client(testKeyStore)
   2712                 .server(testKeyStore)
   2713                 .additionalClientKeyManagers(new KeyManager[] {pskKeyManager})
   2714                 .additionalServerKeyManagers(new KeyManager[] {pskKeyManager})
   2715                 .build();
   2716         for (String cipherSuite : c.clientContext.getSocketFactory().getSupportedCipherSuites()) {
   2717             if (cipherSuite.equals(StandardNames.CIPHER_SUITE_FALLBACK)
   2718                     || cipherSuite.equals(StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION)) {
   2719                 continue;
   2720             }
   2721             TestSSLSocketPair pair = TestSSLSocketPair.create(c);
   2722             try {
   2723                 String[] cipherSuites =
   2724                         new String[] {cipherSuite, StandardNames.CIPHER_SUITE_SECURE_RENEGOTIATION};
   2725                 pair.connect(cipherSuites, cipherSuites);
   2726 
   2727                 assertEquals(cipherSuite, pair.client.getSession().getCipherSuite());
   2728 
   2729                 byte[] clientTlsUnique = Conscrypt.getTlsUnique(pair.client);
   2730                 byte[] serverTlsUnique = Conscrypt.getTlsUnique(pair.server);
   2731                 assertNotNull(clientTlsUnique);
   2732                 assertNotNull(serverTlsUnique);
   2733                 assertArrayEquals(clientTlsUnique, serverTlsUnique);
   2734                 assertEquals(12, clientTlsUnique.length);
   2735             } catch (Exception e) {
   2736                 throw new AssertionError("Cipher suite is " + cipherSuite, e);
   2737             } finally {
   2738                 pair.client.close();
   2739                 pair.server.close();
   2740             }
   2741         }
   2742     }
   2743 
   2744     // Tests that a socket will close cleanly even if it fails to create due to an
   2745     // internal IOException
   2746     @Test
   2747     public void test_SSLSocket_CloseCleanlyOnConstructorFailure() throws Exception {
   2748         TestSSLContext c = TestSSLContext.create();
   2749         try {
   2750             c.clientContext.getSocketFactory().createSocket(c.host, 1);
   2751             fail();
   2752         } catch (ConnectException ignored) {
   2753             // Ignored.
   2754         }
   2755     }
   2756 
   2757     private static void setWriteTimeout(Object socket, int timeout) {
   2758         Exception ex = null;
   2759         try {
   2760             Method method = socket.getClass().getMethod("setSoWriteTimeout", int.class);
   2761             method.setAccessible(true);
   2762             method.invoke(socket, timeout);
   2763         } catch (Exception e) {
   2764             ex = e;
   2765         }
   2766         // Engine-based socket currently has the method but throws UnsupportedOperationException.
   2767         assumeNoException("Client socket does not support setting write timeout", ex);
   2768     }
   2769 
   2770     private static void setHostname(SSLSocket socket) {
   2771         try {
   2772             Method method = socket.getClass().getMethod("setHostname", String.class);
   2773             method.setAccessible(true);
   2774             method.invoke(socket, "sslsockettest.androidcts.google.com");
   2775         } catch (NoSuchMethodException ignored) {
   2776             // Ignored.
   2777         } catch (Exception e) {
   2778             throw new RuntimeException("Failed to enable SNI", e);
   2779         }
   2780     }
   2781 
   2782     private static void enableSessionTickets(SSLSocket socket) {
   2783         try {
   2784             Method method =
   2785                     socket.getClass().getMethod("setUseSessionTickets", boolean.class);
   2786             method.setAccessible(true);
   2787             method.invoke(socket, true);
   2788         } catch (NoSuchMethodException ignored) {
   2789             // Ignored.
   2790         } catch (Exception e) {
   2791             throw new RuntimeException("Failed to enable Session Tickets", e);
   2792         }
   2793     }
   2794 
   2795     private static boolean isConscryptSocket(SSLSocket socket) {
   2796         return isConscryptFdSocket(socket) || isConscryptEngineSocket(socket);
   2797     }
   2798 
   2799     private static boolean isConscryptFdSocket(SSLSocket socket) {
   2800         Class<?> clazz = socket.getClass();
   2801         while (clazz != Object.class && !"ConscryptFileDescriptorSocket".equals(clazz.getSimpleName())) {
   2802             clazz = clazz.getSuperclass();
   2803         }
   2804         return "ConscryptFileDescriptorSocket".equals(clazz.getSimpleName());
   2805     }
   2806 
   2807     private static boolean isConscryptEngineSocket(SSLSocket socket) {
   2808         Class<?> clazz = socket.getClass();
   2809         while (clazz != Object.class && !"ConscryptEngineSocket".equals(clazz.getSimpleName())) {
   2810             clazz = clazz.getSuperclass();
   2811         }
   2812         return "ConscryptEngineSocket".equals(clazz.getSimpleName());
   2813     }
   2814 
   2815     private static String osName() {
   2816         return System.getProperty("os.name").toLowerCase(Locale.US).replaceAll("[^a-z0-9]+", "");
   2817     }
   2818 
   2819     private static boolean isLinux() {
   2820         return osName().startsWith("linux");
   2821     }
   2822 
   2823     private static boolean isWindows() {
   2824         return osName().startsWith("windows");
   2825     }
   2826 
   2827     private static boolean isOsx() {
   2828         String name = osName();
   2829         return name.startsWith("macosx") || name.startsWith("osx");
   2830     }
   2831 
   2832     private <T> Future<T> runAsync(Callable<T> callable) {
   2833         return executor.submit(callable);
   2834     }
   2835 
   2836     private static void readFully(InputStream in, byte[] dst) throws IOException {
   2837         int offset = 0;
   2838         int byteCount = dst.length;
   2839         while (byteCount > 0) {
   2840             int bytesRead = in.read(dst, offset, byteCount);
   2841             if (bytesRead < 0) {
   2842                 throw new EOFException();
   2843             }
   2844             offset += bytesRead;
   2845             byteCount -= bytesRead;
   2846         }
   2847     }
   2848 
   2849     private static SSLSession getHandshakeSession(SSLSocket socket) {
   2850         try {
   2851             Method method = socket.getClass().getMethod("getHandshakeSession");
   2852             return (SSLSession) method.invoke(socket);
   2853         } catch (Exception e) {
   2854             return null;
   2855         }
   2856     }
   2857 
   2858     private static void closeQuietly(Socket socket) {
   2859         if (socket != null) {
   2860             try {
   2861                 socket.close();
   2862             } catch (Exception ignored) {
   2863                 // Ignored.
   2864             }
   2865         }
   2866     }
   2867 
   2868     private static void closeQuietly(ServerSocket serverSocket) {
   2869         if (serverSocket != null) {
   2870             try {
   2871                 serverSocket.close();
   2872             } catch (Exception ignored) {
   2873                 // Ignored.
   2874             }
   2875         }
   2876     }
   2877 }
   2878