Home | History | Annotate | Download | only in jsse
      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.apache.harmony.xnet.provider.jsse;
     18 
     19 import java.io.FileDescriptor;
     20 import java.io.IOException;
     21 import java.net.ServerSocket;
     22 import java.net.Socket;
     23 import java.net.SocketTimeoutException;
     24 import java.security.KeyStore;
     25 import java.security.KeyStore.PrivateKeyEntry;
     26 import java.security.cert.CertificateException;
     27 import java.security.cert.X509Certificate;
     28 import java.util.ArrayList;
     29 import java.util.Arrays;
     30 import java.util.List;
     31 import java.util.concurrent.Callable;
     32 import java.util.concurrent.ExecutionException;
     33 import java.util.concurrent.ExecutorService;
     34 import java.util.concurrent.Executors;
     35 import java.util.concurrent.Future;
     36 import java.util.concurrent.TimeUnit;
     37 import javax.net.ssl.SSLException;
     38 import javax.net.ssl.SSLProtocolException;
     39 import javax.security.auth.x500.X500Principal;
     40 import junit.framework.TestCase;
     41 import libcore.java.security.StandardNames;
     42 import libcore.java.security.TestKeyStore;
     43 import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks;
     44 import static org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
     45 
     46 public class NativeCryptoTest extends TestCase {
     47 
     48     private static final int NULL = 0;
     49     private static final FileDescriptor INVALID_FD = new FileDescriptor();
     50     private static final SSLHandshakeCallbacks DUMMY_CB = new TestSSLHandshakeCallbacks(-1, null);
     51 
     52     private static final long TIMEOUT_SECONDS = 5;
     53 
     54     private static byte[] SERVER_PRIVATE_KEY;
     55     private static byte[][] SERVER_CERTIFICATES;
     56     private static byte[] CLIENT_PRIVATE_KEY;
     57     private static byte[][] CLIENT_CERTIFICATES;
     58     private static byte[][] CA_PRINCIPALS;
     59 
     60     private static byte[] getServerPrivateKey() {
     61         initCerts();
     62         return SERVER_PRIVATE_KEY;
     63     }
     64 
     65     private static byte[][] getServerCertificates() {
     66         initCerts();
     67         return SERVER_CERTIFICATES;
     68     }
     69 
     70     private static byte[] getClientPrivateKey() {
     71         initCerts();
     72         return CLIENT_PRIVATE_KEY;
     73     }
     74 
     75     private static byte[][] getClientCertificates() {
     76         initCerts();
     77         return CLIENT_CERTIFICATES;
     78     }
     79 
     80     private static byte[][] getCaPrincipals() {
     81         initCerts();
     82         return CA_PRINCIPALS;
     83     }
     84 
     85     /**
     86      * Lazily create shared test certificates.
     87      */
     88     private static synchronized void initCerts() {
     89         if (SERVER_PRIVATE_KEY != null) {
     90             return;
     91         }
     92 
     93         try {
     94             PrivateKeyEntry serverPrivateKeyEntry
     95                     = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
     96             SERVER_PRIVATE_KEY = serverPrivateKeyEntry.getPrivateKey().getEncoded();
     97             SERVER_CERTIFICATES = NativeCrypto.encodeCertificates(
     98                     serverPrivateKeyEntry.getCertificateChain());
     99 
    100             PrivateKeyEntry clientPrivateKeyEntry
    101                     = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
    102             CLIENT_PRIVATE_KEY = clientPrivateKeyEntry.getPrivateKey().getEncoded();
    103             CLIENT_CERTIFICATES = NativeCrypto.encodeCertificates(
    104                     clientPrivateKeyEntry.getCertificateChain());
    105 
    106             KeyStore ks = TestKeyStore.getClient().keyStore;
    107             String caCertAlias = ks.aliases().nextElement();
    108             X509Certificate certificate = (X509Certificate) ks.getCertificate(caCertAlias);
    109             X500Principal principal = certificate.getIssuerX500Principal();
    110             CA_PRINCIPALS = new byte[][] { principal.getEncoded() };
    111         } catch (Exception e) {
    112             throw new RuntimeException(e);
    113         }
    114     }
    115 
    116     public static void assertEqualSessions(int expected, int actual) {
    117         assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected),
    118                               NativeCrypto.SSL_SESSION_session_id(actual));
    119     }
    120     public static void assertEqualByteArrays(byte[] expected, byte[] actual) {
    121         assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    122     }
    123 
    124     public static void assertEqualPrincipals(byte[][] expected, byte[][] actual) {
    125         assertEqualByteArrays(expected, actual);
    126     }
    127     public static void assertEqualCertificateChains(byte[][] expected, byte[][] actual) {
    128         assertEqualByteArrays(expected, actual);
    129     }
    130     public static void assertEqualByteArrays(byte[][] expected, byte[][] actual) {
    131         assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual));
    132     }
    133 
    134     public void test_SSL_CTX_new() throws Exception {
    135         int c = NativeCrypto.SSL_CTX_new();
    136         assertTrue(c != NULL);
    137         int c2 = NativeCrypto.SSL_CTX_new();
    138         assertTrue(c != c2);
    139         NativeCrypto.SSL_CTX_free(c);
    140         NativeCrypto.SSL_CTX_free(c2);
    141     }
    142 
    143     public void test_SSL_CTX_free() throws Exception {
    144         try {
    145             NativeCrypto.SSL_CTX_free(NULL);
    146             fail();
    147         } catch (NullPointerException expected) {
    148         }
    149 
    150         NativeCrypto.SSL_CTX_free(NativeCrypto.SSL_CTX_new());
    151     }
    152 
    153     public void test_SSL_CTX_set_session_id_context() throws Exception {
    154         byte[] empty = new byte[0];
    155         try {
    156             NativeCrypto.SSL_CTX_set_session_id_context(NULL, empty);
    157             fail();
    158         } catch (NullPointerException expected) {
    159         }
    160         int c = NativeCrypto.SSL_CTX_new();
    161         try {
    162             NativeCrypto.SSL_CTX_set_session_id_context(c, null);
    163             fail();
    164         } catch (NullPointerException expected) {
    165         }
    166         NativeCrypto.SSL_CTX_set_session_id_context(c, empty);
    167         NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[32]);
    168         try {
    169             NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[33]);
    170         } catch (IllegalArgumentException expected) {
    171         }
    172         NativeCrypto.SSL_CTX_free(c);
    173     }
    174 
    175     public void test_SSL_new() throws Exception {
    176         int c = NativeCrypto.SSL_CTX_new();
    177         int s = NativeCrypto.SSL_new(c);
    178 
    179         assertTrue(s != NULL);
    180         assertTrue((NativeCrypto.SSL_get_options(s) & 0x01000000L) != 0); // SSL_OP_NO_SSLv2
    181         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
    182         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1) == 0);
    183         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1_1) == 0);
    184         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1_2) == 0);
    185 
    186         int s2 = NativeCrypto.SSL_new(c);
    187         assertTrue(s != s2);
    188         NativeCrypto.SSL_free(s2);
    189 
    190         NativeCrypto.SSL_free(s);
    191         NativeCrypto.SSL_CTX_free(c);
    192     }
    193 
    194     public void test_SSL_use_certificate() throws Exception {
    195         try {
    196             NativeCrypto.SSL_use_certificate(NULL, null);
    197             fail();
    198         } catch (NullPointerException expected) {
    199         }
    200 
    201         int c = NativeCrypto.SSL_CTX_new();
    202         int s = NativeCrypto.SSL_new(c);
    203 
    204         try {
    205             NativeCrypto.SSL_use_certificate(s, null);
    206             fail();
    207         } catch (NullPointerException expected) {
    208         }
    209 
    210         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    211 
    212         NativeCrypto.SSL_free(s);
    213         NativeCrypto.SSL_CTX_free(c);
    214     }
    215 
    216     public void test_SSL_use_PrivateKey() throws Exception {
    217         try {
    218             NativeCrypto.SSL_use_PrivateKey(NULL, null);
    219             fail();
    220         } catch (NullPointerException expected) {
    221         }
    222 
    223         int c = NativeCrypto.SSL_CTX_new();
    224         int s = NativeCrypto.SSL_new(c);
    225 
    226         try {
    227             NativeCrypto.SSL_use_PrivateKey(s, null);
    228             fail();
    229         } catch (NullPointerException expected) {
    230         }
    231 
    232         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
    233 
    234         NativeCrypto.SSL_free(s);
    235         NativeCrypto.SSL_CTX_free(c);
    236     }
    237 
    238     public void test_SSL_check_private_key_null() throws Exception {
    239         try {
    240             NativeCrypto.SSL_check_private_key(NULL);
    241             fail();
    242         } catch (NullPointerException expected) {
    243         }
    244     }
    245 
    246     public void test_SSL_check_private_key_no_key_no_cert() throws Exception {
    247         int c = NativeCrypto.SSL_CTX_new();
    248         int s = NativeCrypto.SSL_new(c);
    249 
    250         // neither private or certificate set
    251         try {
    252             NativeCrypto.SSL_check_private_key(s);
    253             fail();
    254         } catch (SSLException expected) {
    255         }
    256 
    257         NativeCrypto.SSL_free(s);
    258         NativeCrypto.SSL_CTX_free(c);
    259     }
    260 
    261     public void test_SSL_check_private_key_cert_then_key() throws Exception {
    262         int c = NativeCrypto.SSL_CTX_new();
    263         int s = NativeCrypto.SSL_new(c);
    264 
    265         // first certificate, then private
    266         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    267 
    268         try {
    269             NativeCrypto.SSL_check_private_key(s);
    270             fail();
    271         } catch (SSLException expected) {
    272         }
    273 
    274         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
    275         NativeCrypto.SSL_check_private_key(s);
    276 
    277         NativeCrypto.SSL_free(s);
    278         NativeCrypto.SSL_CTX_free(c);
    279     }
    280     public void test_SSL_check_private_key_key_then_cert() throws Exception {
    281         int c = NativeCrypto.SSL_CTX_new();
    282         int s = NativeCrypto.SSL_new(c);
    283 
    284         // first private, then certificate
    285         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey());
    286 
    287         try {
    288             NativeCrypto.SSL_check_private_key(s);
    289             fail();
    290         } catch (SSLException expected) {
    291         }
    292 
    293         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    294         NativeCrypto.SSL_check_private_key(s);
    295 
    296         NativeCrypto.SSL_free(s);
    297         NativeCrypto.SSL_CTX_free(c);
    298     }
    299 
    300     public void test_SSL_get_mode() throws Exception {
    301         try {
    302             NativeCrypto.SSL_get_mode(NULL);
    303             fail();
    304         } catch (NullPointerException expected) {
    305         }
    306 
    307         int c = NativeCrypto.SSL_CTX_new();
    308         int s = NativeCrypto.SSL_new(c);
    309         assertTrue(NativeCrypto.SSL_get_mode(s) != 0);
    310         NativeCrypto.SSL_free(s);
    311         NativeCrypto.SSL_CTX_free(c);
    312     }
    313 
    314     public void test_SSL_set_mode_and_clear_mode() throws Exception {
    315         try {
    316             NativeCrypto.SSL_set_mode(NULL, 0);
    317             fail();
    318         } catch (NullPointerException expected) {
    319         }
    320 
    321         int c = NativeCrypto.SSL_CTX_new();
    322         int s = NativeCrypto.SSL_new(c);
    323         // check SSL_MODE_HANDSHAKE_CUTTHROUGH off by default
    324         assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
    325         // set SSL_MODE_HANDSHAKE_CUTTHROUGH on
    326         NativeCrypto.SSL_set_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
    327         assertTrue((NativeCrypto.SSL_get_mode(s)
    328                 & SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0);
    329         // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off
    330         NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
    331         assertTrue((NativeCrypto.SSL_get_mode(s)
    332                     & SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0);
    333 
    334         NativeCrypto.SSL_free(s);
    335         NativeCrypto.SSL_CTX_free(c);
    336     }
    337 
    338     public void test_SSL_get_options() throws Exception {
    339         try {
    340             NativeCrypto.SSL_get_options(NULL);
    341             fail();
    342         } catch (NullPointerException expected) {
    343         }
    344 
    345         int c = NativeCrypto.SSL_CTX_new();
    346         int s = NativeCrypto.SSL_new(c);
    347         assertTrue(NativeCrypto.SSL_get_options(s) != 0);
    348         NativeCrypto.SSL_free(s);
    349         NativeCrypto.SSL_CTX_free(c);
    350     }
    351 
    352     public void test_SSL_set_options() throws Exception {
    353         try {
    354             NativeCrypto.SSL_set_options(NULL, 0);
    355             fail();
    356         } catch (NullPointerException expected) {
    357         }
    358 
    359         int c = NativeCrypto.SSL_CTX_new();
    360         int s = NativeCrypto.SSL_new(c);
    361         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
    362         NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
    363         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0);
    364         NativeCrypto.SSL_free(s);
    365         NativeCrypto.SSL_CTX_free(c);
    366     }
    367 
    368     public void test_SSL_clear_options() throws Exception {
    369         try {
    370             NativeCrypto.SSL_clear_options(NULL, 0);
    371             fail();
    372         } catch (NullPointerException expected) {
    373         }
    374 
    375         int c = NativeCrypto.SSL_CTX_new();
    376         int s = NativeCrypto.SSL_new(c);
    377         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
    378         NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
    379         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0);
    380         NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
    381         assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
    382         NativeCrypto.SSL_free(s);
    383         NativeCrypto.SSL_CTX_free(c);
    384     }
    385 
    386     public void test_SSL_set_cipher_lists() throws Exception {
    387         try {
    388             NativeCrypto.SSL_set_cipher_lists(NULL, null);
    389             fail();
    390         } catch (NullPointerException expected) {
    391         }
    392 
    393         int c = NativeCrypto.SSL_CTX_new();
    394         int s = NativeCrypto.SSL_new(c);
    395 
    396         try {
    397             NativeCrypto.SSL_set_cipher_lists(s, null);
    398             fail();
    399         } catch (NullPointerException expected) {
    400         }
    401 
    402         NativeCrypto.SSL_set_cipher_lists(s, new String[] {});
    403 
    404         try {
    405             NativeCrypto.SSL_set_cipher_lists(s, new String[] { null });
    406             fail();
    407         } catch (NullPointerException expected) {
    408         }
    409 
    410         // see OpenSSL ciphers man page
    411         String[] illegals = new String[] {
    412             // empty
    413             "",
    414             // never standardized
    415             "EXP1024-DES-CBC-SHA", "EXP1024-RC4-SHA", "DHE-DSS-RC4-SHA",
    416             // IDEA
    417             "IDEA-CBC-SHA", "IDEA-CBC-MD5"
    418         };
    419 
    420         for (String illegal : illegals) {
    421             try {
    422                 NativeCrypto.SSL_set_cipher_lists(s, new String[] { illegal });
    423                 fail(illegal);
    424             } catch (IllegalArgumentException expected) {
    425             }
    426         }
    427 
    428         List<String> ciphers
    429                 = new ArrayList<String>(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.keySet());
    430         NativeCrypto.SSL_set_cipher_lists(s, ciphers.toArray(new String[ciphers.size()]));
    431 
    432         NativeCrypto.SSL_free(s);
    433         NativeCrypto.SSL_CTX_free(c);
    434     }
    435 
    436     public void test_SSL_set_verify() throws Exception {
    437         try {
    438             NativeCrypto.SSL_set_verify(NULL, 0);
    439             fail();
    440         } catch (NullPointerException expected) {
    441         }
    442 
    443         int c = NativeCrypto.SSL_CTX_new();
    444         int s = NativeCrypto.SSL_new(c);
    445         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
    446         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
    447         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
    448         NativeCrypto.SSL_set_verify(s, (NativeCrypto.SSL_VERIFY_PEER
    449                                         | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT));
    450         NativeCrypto.SSL_free(s);
    451         NativeCrypto.SSL_CTX_free(c);
    452     }
    453 
    454     private static final boolean DEBUG = false;
    455 
    456     public static class Hooks {
    457         public int getContext() throws SSLException {
    458             return NativeCrypto.SSL_CTX_new();
    459         }
    460         public int beforeHandshake(int context) throws SSLException {
    461             int s = NativeCrypto.SSL_new(context);
    462             // without this SSL_set_cipher_lists call the tests were
    463             // negotiating DHE-RSA-AES256-SHA by default which had
    464             // very slow ephemeral RSA key generation
    465             NativeCrypto.SSL_set_cipher_lists(s, new String[] { "RC4-MD5" });
    466             return s;
    467         }
    468         public void clientCertificateRequested(int s) {}
    469         public void afterHandshake(int session, int ssl, int context,
    470                                    Socket socket, FileDescriptor fd,
    471                                    SSLHandshakeCallbacks callback)
    472                 throws Exception {
    473             if (session != NULL) {
    474                 NativeCrypto.SSL_SESSION_free(session);
    475             }
    476             if (ssl != NULL) {
    477                 try {
    478                     NativeCrypto.SSL_shutdown(ssl, fd, callback);
    479                 } catch (IOException e) {
    480                 }
    481                 NativeCrypto.SSL_free(ssl);
    482             }
    483             if (context != NULL) {
    484                 NativeCrypto.SSL_CTX_free(context);
    485             }
    486             if (socket != null) {
    487                 socket.close();
    488             }
    489         }
    490     }
    491 
    492     public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks {
    493         private final int sslNativePointer;
    494         private final Hooks hooks;
    495 
    496         public TestSSLHandshakeCallbacks(int sslNativePointer,
    497                                          Hooks hooks) {
    498             this.sslNativePointer = sslNativePointer;
    499             this.hooks = hooks;
    500         }
    501 
    502         public byte[][] asn1DerEncodedCertificateChain;
    503         public String authMethod;
    504         public boolean verifyCertificateChainCalled;
    505 
    506         public void verifyCertificateChain(byte[][] asn1DerEncodedCertificateChain,
    507                                            String authMethod)
    508                 throws CertificateException {
    509             if (DEBUG) {
    510                 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16)
    511                                    + " verifyCertificateChain"
    512                                    + " asn1DerEncodedCertificateChain="
    513                                    + asn1DerEncodedCertificateChain
    514                                    + " authMethod=" + authMethod);
    515             }
    516             this.asn1DerEncodedCertificateChain = asn1DerEncodedCertificateChain;
    517             this.authMethod = authMethod;
    518             this.verifyCertificateChainCalled = true;
    519         }
    520 
    521         public byte[] keyTypes;
    522         public byte[][] asn1DerEncodedX500Principals;
    523         public boolean clientCertificateRequestedCalled;
    524         public void clientCertificateRequested(byte[] keyTypes,
    525                                                byte[][] asn1DerEncodedX500Principals) {
    526             if (DEBUG) {
    527                 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16)
    528                                    + " clientCertificateRequested"
    529                                    + " keyTypes=" + keyTypes
    530                                    + " asn1DerEncodedX500Principals="
    531                                    + asn1DerEncodedX500Principals);
    532             }
    533             this.keyTypes = keyTypes;
    534             this.asn1DerEncodedX500Principals = asn1DerEncodedX500Principals;
    535             this.clientCertificateRequestedCalled = true;
    536             if (hooks != null ) {
    537                 hooks.clientCertificateRequested(sslNativePointer);
    538             }
    539         }
    540 
    541         public boolean handshakeCompletedCalled;
    542         public void handshakeCompleted() {
    543             if (DEBUG) {
    544                 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16)
    545                                    + " handshakeCompleted");
    546             }
    547             this.handshakeCompletedCalled = true;
    548         }
    549     }
    550 
    551     public static class ServerHooks extends Hooks {
    552         private final byte[] privateKey;
    553         private final byte[][] certificates;
    554         public ServerHooks(byte[] privateKey, byte[][] certificates) {
    555             this.privateKey = privateKey;
    556             this.certificates = certificates;
    557         }
    558 
    559         @Override
    560         public int beforeHandshake(int c) throws SSLException {
    561             int s = super.beforeHandshake(c);
    562             if (privateKey != null) {
    563                 NativeCrypto.SSL_use_PrivateKey(s, privateKey);
    564             }
    565             if (certificates != null) {
    566                 NativeCrypto.SSL_use_certificate(s, certificates);
    567             }
    568             return s;
    569         }
    570         public void clientCertificateRequested(int s) {
    571             fail("Server asked for client certificates");
    572         }
    573     }
    574 
    575     public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
    576             final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols) {
    577         ExecutorService executor = Executors.newSingleThreadExecutor();
    578         Future<TestSSLHandshakeCallbacks> future = executor.submit(
    579                 new Callable<TestSSLHandshakeCallbacks>() {
    580             public TestSSLHandshakeCallbacks call() throws Exception {
    581                 Socket socket = (client
    582                                  ? new Socket(listener.getInetAddress(),
    583                                               listener.getLocalPort())
    584                                  : listener.accept());
    585                 if (timeout == -1) {
    586                     return null;
    587                 }
    588                 FileDescriptor fd = socket.getFileDescriptor$();
    589                 int c = hooks.getContext();
    590                 int s = hooks.beforeHandshake(c);
    591                 TestSSLHandshakeCallbacks callback = new TestSSLHandshakeCallbacks(s, hooks);
    592                 if (DEBUG) {
    593                     System.out.println("ssl=0x" + Integer.toString(s, 16)
    594                                        + " handshake"
    595                                        + " context=0x" + Integer.toString(c, 16)
    596                                        + " socket=" + socket
    597                                        + " fd=" + fd
    598                                        + " timeout=" + timeout
    599                                        + " client=" + client);
    600                 }
    601                 int session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
    602                         npnProtocols);
    603                 if (DEBUG) {
    604                     System.out.println("ssl=0x" + Integer.toString(s, 16)
    605                                        + " handshake"
    606                                        + " session=0x" + Integer.toString(session, 16));
    607                 }
    608                 hooks.afterHandshake(session, s, c, socket, fd, callback);
    609                 return callback;
    610             }
    611         });
    612         executor.shutdown();
    613         return future;
    614     }
    615 
    616     public void test_SSL_do_handshake_NULL_SSL() throws Exception {
    617         try {
    618             NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null);
    619             fail();
    620         } catch (NullPointerException expected) {
    621         }
    622     }
    623 
    624     public void test_SSL_do_handshake_null_args() throws Exception {
    625         int c = NativeCrypto.SSL_CTX_new();
    626         int s = NativeCrypto.SSL_new(c);
    627 
    628         try {
    629             NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null);
    630             fail();
    631         } catch (NullPointerException expected) {
    632         }
    633 
    634         try {
    635             NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null);
    636             fail();
    637         } catch (NullPointerException expected) {
    638         }
    639 
    640         NativeCrypto.SSL_free(s);
    641         NativeCrypto.SSL_CTX_free(c);
    642     }
    643 
    644     public void test_SSL_do_handshake_normal() throws Exception {
    645         // normal client and server case
    646         final ServerSocket listener = new ServerSocket(0);
    647         Hooks cHooks = new Hooks();
    648         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
    649         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    650         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    651         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    652         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    653         assertTrue(clientCallback.verifyCertificateChainCalled);
    654         assertEqualCertificateChains(getServerCertificates(),
    655                                      clientCallback.asn1DerEncodedCertificateChain);
    656         assertEquals("RSA", clientCallback.authMethod);
    657         assertFalse(serverCallback.verifyCertificateChainCalled);
    658         assertFalse(clientCallback.clientCertificateRequestedCalled);
    659         assertFalse(serverCallback.clientCertificateRequestedCalled);
    660         assertTrue(clientCallback.handshakeCompletedCalled);
    661         assertTrue(serverCallback.handshakeCompletedCalled);
    662     }
    663 
    664     public void test_SSL_do_handshake_optional_client_certificate() throws Exception {
    665         // optional client certificate case
    666         final ServerSocket listener = new ServerSocket(0);
    667 
    668         Hooks cHooks = new Hooks() {
    669             @Override
    670             public void clientCertificateRequested(int s) {
    671                 super.clientCertificateRequested(s);
    672                 NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey());
    673                 NativeCrypto.SSL_use_certificate(s, getClientCertificates());
    674             }
    675         };
    676         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    677             @Override
    678             public int beforeHandshake(int c) throws SSLException {
    679                 int s = super.beforeHandshake(c);
    680                 NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
    681                 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
    682                 return s;
    683             }
    684         };
    685         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    686         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    687         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    688         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    689         assertTrue(clientCallback.verifyCertificateChainCalled);
    690         assertEqualCertificateChains(getServerCertificates(),
    691                                      clientCallback.asn1DerEncodedCertificateChain);
    692         assertEquals("RSA", clientCallback.authMethod);
    693         assertTrue(serverCallback.verifyCertificateChainCalled);
    694         assertEqualCertificateChains(getClientCertificates(),
    695                 serverCallback.asn1DerEncodedCertificateChain);
    696         assertEquals("RSA", serverCallback.authMethod);
    697 
    698         assertTrue(clientCallback.clientCertificateRequestedCalled);
    699         assertNotNull(clientCallback.keyTypes);
    700         // this depends on the SSL_set_cipher_lists call in beforeHandshake
    701         // the three returned are the non-ephemeral cases.
    702         assertEquals(3, clientCallback.keyTypes.length);
    703         assertEquals("RSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[0]));
    704         assertEquals("DSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[1]));
    705         assertEquals("EC", CipherSuite.getClientKeyType(clientCallback.keyTypes[2]));
    706         assertEqualPrincipals(getCaPrincipals(),
    707                               clientCallback.asn1DerEncodedX500Principals);
    708         assertFalse(serverCallback.clientCertificateRequestedCalled);
    709 
    710         assertTrue(clientCallback.handshakeCompletedCalled);
    711         assertTrue(serverCallback.handshakeCompletedCalled);
    712     }
    713 
    714     public void test_SSL_do_handshake_missing_required_certificate() throws Exception {
    715         // required client certificate negative case
    716         final ServerSocket listener = new ServerSocket(0);
    717         try {
    718             Hooks cHooks = new Hooks();
    719             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    720                 @Override
    721                 public int beforeHandshake(int c) throws SSLException {
    722                     int s = super.beforeHandshake(c);
    723                     NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
    724                     NativeCrypto.SSL_set_verify(s,
    725                                                 NativeCrypto.SSL_VERIFY_PEER
    726                                                 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
    727                     return s;
    728                 }
    729             };
    730             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    731             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    732             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    733             fail();
    734         } catch (ExecutionException expected) {
    735             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
    736         }
    737     }
    738 
    739     /**
    740      * Usually if a RuntimeException is thrown by the
    741      * clientCertificateRequestedCalled callback, the caller sees it
    742      * during the call to NativeCrypto_SSL_do_handshake.  However, IIS
    743      * does not request client certs until after the initial
    744      * handshake. It does an SSL renegotiation, which means we need to
    745      * be able to deliver the callback's exception in cases like
    746      * SSL_read, SSL_write, and SSL_shutdown.
    747      */
    748     public void test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate()
    749             throws Exception {
    750         final ServerSocket listener = new ServerSocket(0);
    751 
    752         Hooks cHooks = new Hooks() {
    753             @Override
    754             public int beforeHandshake(int context) throws SSLException {
    755                 int s = super.beforeHandshake(context);
    756                 NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
    757                 return s;
    758             }
    759             @Override
    760             public void afterHandshake(int session, int s, int c,
    761                                        Socket sock, FileDescriptor fd,
    762                                        SSLHandshakeCallbacks callback)
    763                     throws Exception {
    764                 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
    765                 fail();
    766                 super.afterHandshake(session, s, c, sock, fd, callback);
    767             }
    768             @Override
    769             public void clientCertificateRequested(int s) {
    770                 super.clientCertificateRequested(s);
    771                 throw new RuntimeException("expected");
    772             }
    773         };
    774         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    775             @Override
    776             public void afterHandshake(int session, int s, int c,
    777                                        Socket sock, FileDescriptor fd,
    778                                        SSLHandshakeCallbacks callback)
    779                     throws Exception {
    780                 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
    781                 NativeCrypto.SSL_set_options(
    782                         s, NativeCrypto.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
    783                 NativeCrypto.SSL_renegotiate(s);
    784                 NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1);
    785                 super.afterHandshake(session, s, c, sock, fd, callback);
    786             }
    787         };
    788         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    789         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    790         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    791         try {
    792             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    793         } catch (ExecutionException e) {
    794             if (!"expected".equals(e.getCause().getMessage())) {
    795                 throw e;
    796             }
    797         }
    798     }
    799 
    800     public void test_SSL_do_handshake_client_timeout() throws Exception {
    801         // client timeout
    802         final ServerSocket listener = new ServerSocket(0);
    803         try {
    804             Hooks cHooks = new Hooks();
    805             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
    806             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null);
    807             Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null);
    808             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    809             fail();
    810         } catch (ExecutionException expected) {
    811             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
    812         }
    813     }
    814 
    815     public void test_SSL_do_handshake_server_timeout() throws Exception {
    816         // server timeout
    817         final ServerSocket listener = new ServerSocket(0);
    818         try {
    819             Hooks cHooks = new Hooks();
    820             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
    821             Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null);
    822             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null);
    823             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    824             fail();
    825         } catch (ExecutionException expected) {
    826             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
    827         }
    828     }
    829 
    830     public void test_SSL_set_session() throws Exception {
    831         try {
    832             NativeCrypto.SSL_set_session(NULL, NULL);
    833             fail();
    834         } catch (NullPointerException expected) {
    835         }
    836 
    837         {
    838             int c = NativeCrypto.SSL_CTX_new();
    839             int s = NativeCrypto.SSL_new(c);
    840             NativeCrypto.SSL_set_session(s, NULL);
    841             NativeCrypto.SSL_free(s);
    842             NativeCrypto.SSL_CTX_free(c);
    843         }
    844 
    845         {
    846             final int clientContext = NativeCrypto.SSL_CTX_new();
    847             final int serverContext = NativeCrypto.SSL_CTX_new();
    848             final ServerSocket listener = new ServerSocket(0);
    849             final int[] clientSession = new int[] { NULL };
    850             final int[] serverSession = new int[] { NULL };
    851             {
    852                 Hooks cHooks = new Hooks() {
    853                     @Override
    854                     public int getContext() throws SSLException {
    855                         return clientContext;
    856                     }
    857                     @Override
    858                     public void afterHandshake(int session, int s, int c,
    859                                                Socket sock, FileDescriptor fd,
    860                                                SSLHandshakeCallbacks callback)
    861                             throws Exception {
    862                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
    863                         clientSession[0] = session;
    864                     }
    865                 };
    866                 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    867                     @Override
    868                     public int getContext() throws SSLException {
    869                         return serverContext;
    870                     }
    871                     @Override
    872                     public void afterHandshake(int session, int s, int c,
    873                                                Socket sock, FileDescriptor fd,
    874                                                SSLHandshakeCallbacks callback)
    875                             throws Exception {
    876                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
    877                         serverSession[0] = session;
    878                     }
    879                 };
    880                 Future<TestSSLHandshakeCallbacks> client
    881                         = handshake(listener, 0, true, cHooks, null);
    882                 Future<TestSSLHandshakeCallbacks> server
    883                         = handshake(listener, 0, false, sHooks, null);
    884                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    885                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    886             }
    887             assertEqualSessions(clientSession[0], serverSession[0]);
    888             {
    889                 Hooks cHooks = new Hooks() {
    890                     @Override
    891                     public int getContext() throws SSLException {
    892                         return clientContext;
    893                     }
    894                     @Override
    895                     public int beforeHandshake(int c) throws SSLException {
    896                         int s = NativeCrypto.SSL_new(clientContext);
    897                         NativeCrypto.SSL_set_session(s, clientSession[0]);
    898                         return s;
    899                     }
    900                     @Override
    901                     public void afterHandshake(int session, int s, int c,
    902                                                Socket sock, FileDescriptor fd,
    903                                                SSLHandshakeCallbacks callback)
    904                             throws Exception {
    905                         assertEqualSessions(clientSession[0], session);
    906                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
    907                     }
    908                 };
    909                 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    910                     @Override
    911                     public int getContext() throws SSLException {
    912                         return serverContext;
    913                     }
    914                     @Override
    915                     public void afterHandshake(int session, int s, int c,
    916                                                Socket sock, FileDescriptor fd,
    917                                                SSLHandshakeCallbacks callback)
    918                             throws Exception {
    919                         assertEqualSessions(serverSession[0], session);
    920                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
    921                     }
    922                 };
    923                 Future<TestSSLHandshakeCallbacks> client
    924                         = handshake(listener, 0, true, cHooks, null);
    925                 Future<TestSSLHandshakeCallbacks> server
    926                         = handshake(listener, 0, false, sHooks, null);
    927                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    928                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    929             }
    930             NativeCrypto.SSL_SESSION_free(clientSession[0]);
    931             NativeCrypto.SSL_SESSION_free(serverSession[0]);
    932             NativeCrypto.SSL_CTX_free(serverContext);
    933             NativeCrypto.SSL_CTX_free(clientContext);
    934         }
    935     }
    936 
    937     public void test_SSL_set_session_creation_enabled() throws Exception {
    938         try {
    939             NativeCrypto.SSL_set_session_creation_enabled(NULL, false);
    940             fail();
    941         } catch (NullPointerException expected) {
    942         }
    943 
    944         {
    945             int c = NativeCrypto.SSL_CTX_new();
    946             int s = NativeCrypto.SSL_new(c);
    947             NativeCrypto.SSL_set_session_creation_enabled(s, false);
    948             NativeCrypto.SSL_set_session_creation_enabled(s, true);
    949             NativeCrypto.SSL_free(s);
    950             NativeCrypto.SSL_CTX_free(c);
    951         }
    952 
    953         final ServerSocket listener = new ServerSocket(0);
    954 
    955         // negative test case for SSL_set_session_creation_enabled(false) on client
    956         try {
    957             Hooks cHooks = new Hooks() {
    958                 @Override
    959                 public int beforeHandshake(int c) throws SSLException {
    960                     int s = super.beforeHandshake(c);
    961                     NativeCrypto.SSL_set_session_creation_enabled(s, false);
    962                     return s;
    963                 }
    964             };
    965             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
    966             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    967             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    968             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    969             fail();
    970         } catch (ExecutionException expected) {
    971             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
    972         }
    973 
    974         // negative test case for SSL_set_session_creation_enabled(false) on server
    975         try {
    976             Hooks cHooks = new Hooks();
    977             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
    978                 @Override
    979                 public int beforeHandshake(int c) throws SSLException {
    980                     int s = super.beforeHandshake(c);
    981                     NativeCrypto.SSL_set_session_creation_enabled(s, false);
    982                     return s;
    983                 }
    984             };
    985             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
    986             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
    987             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
    988             fail();
    989         } catch (ExecutionException expected) {
    990             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
    991         }
    992     }
    993 
    994     public void test_SSL_set_tlsext_host_name() throws Exception {
    995         // NULL SSL
    996         try {
    997             NativeCrypto.SSL_set_tlsext_host_name(NULL, null);
    998             fail();
    999         } catch (NullPointerException expected) {
   1000         }
   1001 
   1002         final String hostname = "www.android.com";
   1003 
   1004         {
   1005             int c = NativeCrypto.SSL_CTX_new();
   1006             int s = NativeCrypto.SSL_new(c);
   1007 
   1008             // null hostname
   1009             try {
   1010                 NativeCrypto.SSL_set_tlsext_host_name(s, null);
   1011                 fail();
   1012             } catch (NullPointerException expected) {
   1013             }
   1014 
   1015             // too long hostname
   1016             try {
   1017                 char[] longHostname = new char[256];
   1018                 Arrays.fill(longHostname, 'w');
   1019                 NativeCrypto.SSL_set_tlsext_host_name(s, new String(longHostname));
   1020                 fail();
   1021             } catch (SSLException expected) {
   1022             }
   1023 
   1024             assertNull(NativeCrypto.SSL_get_servername(s));
   1025             NativeCrypto.SSL_set_tlsext_host_name(s, new String(hostname));
   1026             assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
   1027 
   1028             NativeCrypto.SSL_free(s);
   1029             NativeCrypto.SSL_CTX_free(c);
   1030         }
   1031 
   1032         final ServerSocket listener = new ServerSocket(0);
   1033 
   1034         // normal
   1035         Hooks cHooks = new Hooks() {
   1036             @Override
   1037             public int beforeHandshake(int c) throws SSLException {
   1038                 int s = super.beforeHandshake(c);
   1039                 NativeCrypto.SSL_set_tlsext_host_name(s, hostname);
   1040                 return s;
   1041             }
   1042         };
   1043         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1044             @Override
   1045             public void afterHandshake(int session, int s, int c,
   1046                                        Socket sock, FileDescriptor fd,
   1047                                        SSLHandshakeCallbacks callback)
   1048                     throws Exception {
   1049                 assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
   1050                 super.afterHandshake(session, s, c, sock, fd, callback);
   1051             }
   1052         };
   1053         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1054         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1055         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1056         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1057     }
   1058 
   1059     public void test_SSL_NpnNegotiateSuccess() throws Exception {
   1060         final byte[] clientNpnProtocols = new byte[] {
   1061                 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
   1062                 3, 'f', 'o', 'o',
   1063                 6, 's', 'p', 'd', 'y', '/', '2',
   1064         };
   1065         final byte[] serverNpnProtocols = new byte[] {
   1066                 6, 's', 'p', 'd', 'y', '/', '2',
   1067                 3, 'f', 'o', 'o',
   1068                 3, 'b', 'a', 'r',
   1069         };
   1070 
   1071         Hooks cHooks = new Hooks() {
   1072             @Override public int beforeHandshake(int context) throws SSLException {
   1073                 NativeCrypto.SSL_CTX_enable_npn(context);
   1074                 return super.beforeHandshake(context);
   1075             }
   1076             @Override public void afterHandshake(int session, int ssl, int context, Socket socket,
   1077                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1078                 byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
   1079                 assertEquals("spdy/2", new String(negotiated));
   1080                 assertTrue("NPN should enable cutthrough on the client",
   1081                         0 != (NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH));
   1082                 super.afterHandshake(session, ssl, context, socket, fd, callback);
   1083             }
   1084         };
   1085         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1086             @Override public int beforeHandshake(int context) throws SSLException {
   1087                 NativeCrypto.SSL_CTX_enable_npn(context);
   1088                 return super.beforeHandshake(context);
   1089             }
   1090             @Override public void afterHandshake(int session, int ssl, int c, Socket sock,
   1091                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1092                 byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
   1093                 assertEquals("spdy/2", new String(negotiated));
   1094                 assertEquals("NPN should not enable cutthrough on the server",
   1095                         0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
   1096                 super.afterHandshake(session, ssl, c, sock, fd, callback);
   1097             }
   1098         };
   1099 
   1100         ServerSocket listener = new ServerSocket(0);
   1101         Future<TestSSLHandshakeCallbacks> client
   1102                 = handshake(listener, 0, true, cHooks, clientNpnProtocols);
   1103         Future<TestSSLHandshakeCallbacks> server
   1104                 = handshake(listener, 0, false, sHooks, serverNpnProtocols);
   1105         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1106         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1107     }
   1108 
   1109     public void test_SSL_get_servername_null() throws Exception {
   1110         // NULL SSL
   1111         try {
   1112             NativeCrypto.SSL_get_servername(NULL);
   1113             fail();
   1114         } catch (NullPointerException expected) {
   1115         }
   1116 
   1117         int c = NativeCrypto.SSL_CTX_new();
   1118         int s = NativeCrypto.SSL_new(c);
   1119         assertNull(NativeCrypto.SSL_get_servername(s));
   1120         NativeCrypto.SSL_free(s);
   1121         NativeCrypto.SSL_CTX_free(c);
   1122 
   1123         // additional positive testing by test_SSL_set_tlsext_host_name
   1124     }
   1125 
   1126     public void test_SSL_renegotiate() throws Exception {
   1127         try {
   1128             NativeCrypto.SSL_renegotiate(NULL);
   1129             fail();
   1130         } catch (NullPointerException expected) {
   1131         }
   1132 
   1133         final ServerSocket listener = new ServerSocket(0);
   1134         Hooks cHooks = new Hooks() {
   1135             @Override
   1136             public void afterHandshake(int session, int s, int c,
   1137                                        Socket sock, FileDescriptor fd,
   1138                                        SSLHandshakeCallbacks callback)
   1139                     throws Exception {
   1140                 byte[] buffer = new byte[1];
   1141                 NativeCrypto.SSL_read(s, fd, callback, buffer, 0, 1, 0);
   1142                 assertEquals(42, buffer[0]);
   1143                 super.afterHandshake(session, s, c, sock, fd, callback);
   1144             }
   1145         };
   1146         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1147             @Override
   1148             public void afterHandshake(int session, int s, int c,
   1149                                        Socket sock, FileDescriptor fd,
   1150                                        SSLHandshakeCallbacks callback)
   1151                 throws Exception {
   1152                 NativeCrypto.SSL_renegotiate(s);
   1153                 NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1);
   1154                 super.afterHandshake(session, s, c, sock, fd, callback);
   1155             }
   1156         };
   1157         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1158         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1159         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1160         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1161     }
   1162 
   1163     public void test_SSL_get_certificate() throws Exception {
   1164         try {
   1165             NativeCrypto.SSL_get_certificate(NULL);
   1166             fail();
   1167         } catch (NullPointerException expected) {
   1168         }
   1169 
   1170         final ServerSocket listener = new ServerSocket(0);
   1171         Hooks cHooks = new Hooks() {
   1172             @Override
   1173             public void afterHandshake(int session, int s, int c,
   1174                                        Socket sock, FileDescriptor fd,
   1175                                        SSLHandshakeCallbacks callback)
   1176                 throws Exception {
   1177                 assertNull(NativeCrypto.SSL_get_certificate(s));
   1178                 super.afterHandshake(session, s, c, sock, fd, callback);
   1179             }
   1180         };
   1181         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1182             @Override
   1183             public void afterHandshake(int session, int s, int c,
   1184                                        Socket sock, FileDescriptor fd,
   1185                                        SSLHandshakeCallbacks callback)
   1186                     throws Exception {
   1187                 assertEqualCertificateChains(
   1188                                              getServerCertificates(),
   1189                                              NativeCrypto.SSL_get_certificate(s));
   1190                 super.afterHandshake(session, s, c, sock, fd, callback);
   1191             }
   1192         };
   1193         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1194         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1195         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1196         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1197     }
   1198 
   1199     public void test_SSL_get_peer_cert_chain() throws Exception {
   1200         try {
   1201             NativeCrypto.SSL_get_peer_cert_chain(NULL);
   1202             fail();
   1203         } catch (NullPointerException expected) {
   1204         }
   1205 
   1206         final ServerSocket listener = new ServerSocket(0);
   1207 
   1208         Hooks cHooks = new Hooks() {
   1209             @Override
   1210             public void afterHandshake(int session, int s, int c,
   1211                                        Socket sock, FileDescriptor fd,
   1212                                        SSLHandshakeCallbacks callback)
   1213                     throws Exception {
   1214                 byte[][] cc = NativeCrypto.SSL_get_peer_cert_chain(s);
   1215                 assertEqualCertificateChains(getServerCertificates(), cc);
   1216                 super.afterHandshake(session, s, c, sock, fd, callback);
   1217             }
   1218         };
   1219         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1220         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1221         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1222         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1223         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1224     }
   1225 
   1226     final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 };
   1227 
   1228     public void test_SSL_read() throws Exception {
   1229 
   1230         // NULL ssl
   1231         try {
   1232             NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0);
   1233             fail();
   1234         } catch (NullPointerException expected) {
   1235         }
   1236 
   1237         // null FileDescriptor
   1238         {
   1239             int c = NativeCrypto.SSL_CTX_new();
   1240             int s = NativeCrypto.SSL_new(c);
   1241             try {
   1242                 NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0);
   1243                 fail();
   1244             } catch (NullPointerException expected) {
   1245             }
   1246             NativeCrypto.SSL_free(s);
   1247             NativeCrypto.SSL_CTX_free(c);
   1248         }
   1249 
   1250         // null SSLHandshakeCallbacks
   1251         {
   1252             int c = NativeCrypto.SSL_CTX_new();
   1253             int s = NativeCrypto.SSL_new(c);
   1254             try {
   1255                 NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0);
   1256                 fail();
   1257             } catch (NullPointerException expected) {
   1258             }
   1259             NativeCrypto.SSL_free(s);
   1260             NativeCrypto.SSL_CTX_free(c);
   1261         }
   1262 
   1263         // null byte array
   1264         {
   1265             int c = NativeCrypto.SSL_CTX_new();
   1266             int s = NativeCrypto.SSL_new(c);
   1267             try {
   1268                 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0);
   1269                 fail();
   1270             } catch (NullPointerException expected) {
   1271             }
   1272             NativeCrypto.SSL_free(s);
   1273             NativeCrypto.SSL_CTX_free(c);
   1274         }
   1275 
   1276         // handshaking not yet performed
   1277         {
   1278             int c = NativeCrypto.SSL_CTX_new();
   1279             int s = NativeCrypto.SSL_new(c);
   1280             try {
   1281                 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
   1282                 fail();
   1283             } catch (SSLException expected) {
   1284             }
   1285             NativeCrypto.SSL_free(s);
   1286             NativeCrypto.SSL_CTX_free(c);
   1287         }
   1288 
   1289         final ServerSocket listener = new ServerSocket(0);
   1290 
   1291         // normal case
   1292         {
   1293             Hooks cHooks = new Hooks() {
   1294                 @Override
   1295                 public void afterHandshake(int session, int s, int c,
   1296                                            Socket sock, FileDescriptor fd,
   1297                                            SSLHandshakeCallbacks callback)
   1298                         throws Exception {
   1299                     byte[] in = new byte[256];
   1300                     assertEquals(BYTES.length,
   1301                                  NativeCrypto.SSL_read(s,
   1302                                                        fd,
   1303                                                        callback,
   1304                                                        in,
   1305                                                        0,
   1306                                                        BYTES.length,
   1307                                                        0));
   1308                     for (int i = 0; i < BYTES.length; i++) {
   1309                         assertEquals(BYTES[i], in[i]);
   1310                     }
   1311                     super.afterHandshake(session, s, c, sock, fd, callback);
   1312                 }
   1313             };
   1314             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1315                 @Override
   1316                 public void afterHandshake(int session, int s, int c,
   1317                                            Socket sock, FileDescriptor fd,
   1318                                            SSLHandshakeCallbacks callback)
   1319                         throws Exception {
   1320                     NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length);
   1321                     super.afterHandshake(session, s, c, sock, fd, callback);
   1322                 }
   1323             };
   1324             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1325             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1326             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1327             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1328         }
   1329 
   1330         // timeout case
   1331         try {
   1332             Hooks cHooks = new Hooks() {
   1333                 @Override
   1334                 public void afterHandshake(int session, int s, int c,
   1335                                            Socket sock, FileDescriptor fd,
   1336                                            SSLHandshakeCallbacks callback)
   1337                         throws Exception {
   1338                     NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1);
   1339                     fail();
   1340                 }
   1341             };
   1342             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1343                 @Override
   1344                 public void afterHandshake(int session, int s, int c,
   1345                                            Socket sock, FileDescriptor fd,
   1346                                            SSLHandshakeCallbacks callback)
   1347                         throws Exception {
   1348                     NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
   1349                     super.afterHandshake(session, s, c, sock, fd, callback);
   1350                 }
   1351             };
   1352             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1353             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1354             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1355             fail();
   1356         } catch (ExecutionException expected) {
   1357             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
   1358         }
   1359     }
   1360 
   1361     public void test_SSL_write() throws Exception {
   1362         try {
   1363             NativeCrypto.SSL_write(NULL, null, null, null, 0, 0);
   1364             fail();
   1365         } catch (NullPointerException expected) {
   1366         }
   1367 
   1368         // null FileDescriptor
   1369         {
   1370             int c = NativeCrypto.SSL_CTX_new();
   1371             int s = NativeCrypto.SSL_new(c);
   1372             try {
   1373                 NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1);
   1374                 fail();
   1375             } catch (NullPointerException expected) {
   1376             }
   1377             NativeCrypto.SSL_free(s);
   1378             NativeCrypto.SSL_CTX_free(c);
   1379         }
   1380 
   1381         // null SSLHandshakeCallbacks
   1382         {
   1383             int c = NativeCrypto.SSL_CTX_new();
   1384             int s = NativeCrypto.SSL_new(c);
   1385             try {
   1386                 NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1);
   1387                 fail();
   1388             } catch (NullPointerException expected) {
   1389             }
   1390             NativeCrypto.SSL_free(s);
   1391             NativeCrypto.SSL_CTX_free(c);
   1392         }
   1393 
   1394         // null byte array
   1395         {
   1396             int c = NativeCrypto.SSL_CTX_new();
   1397             int s = NativeCrypto.SSL_new(c);
   1398             try {
   1399                 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1);
   1400                 fail();
   1401             } catch (NullPointerException expected) {
   1402             }
   1403             NativeCrypto.SSL_free(s);
   1404             NativeCrypto.SSL_CTX_free(c);
   1405         }
   1406 
   1407         // handshaking not yet performed
   1408         {
   1409             int c = NativeCrypto.SSL_CTX_new();
   1410             int s = NativeCrypto.SSL_new(c);
   1411             try {
   1412                 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1);
   1413                 fail();
   1414             } catch (SSLException expected) {
   1415             }
   1416             NativeCrypto.SSL_free(s);
   1417             NativeCrypto.SSL_CTX_free(c);
   1418         }
   1419 
   1420         // positively tested by test_SSL_read
   1421     }
   1422 
   1423     public void test_SSL_interrupt() throws Exception {
   1424         // SSL_interrupt is a rare case that tolerates a null SSL argument
   1425         NativeCrypto.SSL_interrupt(NULL);
   1426 
   1427         // also works without handshaking
   1428         {
   1429             int c = NativeCrypto.SSL_CTX_new();
   1430             int s = NativeCrypto.SSL_new(c);
   1431             NativeCrypto.SSL_interrupt(s);
   1432             NativeCrypto.SSL_free(s);
   1433             NativeCrypto.SSL_CTX_free(c);
   1434         }
   1435 
   1436         final ServerSocket listener = new ServerSocket(0);
   1437 
   1438         Hooks cHooks = new Hooks() {
   1439             @Override
   1440             public void afterHandshake(int session, int s, int c,
   1441                                        Socket sock, FileDescriptor fd,
   1442                                        SSLHandshakeCallbacks callback)
   1443                     throws Exception {
   1444                 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
   1445                 super.afterHandshake(session, s, c, sock, fd, callback);
   1446             }
   1447         };
   1448         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1449             @Override
   1450             public void afterHandshake(int session, final int s, int c,
   1451                                        Socket sock, FileDescriptor fd,
   1452                                        SSLHandshakeCallbacks callback)
   1453                     throws Exception {
   1454                 new Thread() {
   1455                     public void run() {
   1456                         try {
   1457                             Thread.sleep(1*1000);
   1458                             NativeCrypto.SSL_interrupt(s);
   1459                         } catch (Exception e) {
   1460                         }
   1461                     }
   1462                 }.start();
   1463                 assertEquals(-1, NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0));
   1464                 super.afterHandshake(session, s, c, sock, fd, callback);
   1465             }
   1466         };
   1467         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1468         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1469         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1470         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1471     }
   1472 
   1473     public void test_SSL_shutdown() throws Exception {
   1474 
   1475         // null FileDescriptor
   1476         try {
   1477             NativeCrypto.SSL_shutdown(NULL, null, DUMMY_CB);
   1478         } catch (NullPointerException expected) {
   1479         }
   1480 
   1481         // null SSLHandshakeCallbacks
   1482         try {
   1483             NativeCrypto.SSL_shutdown(NULL, INVALID_FD, null);
   1484         } catch (NullPointerException expected) {
   1485         }
   1486 
   1487         // SSL_shutdown is a rare case that tolerates a null SSL argument
   1488         NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB);
   1489 
   1490         // handshaking not yet performed
   1491         int c = NativeCrypto.SSL_CTX_new();
   1492         int s = NativeCrypto.SSL_new(c);
   1493         try {
   1494             NativeCrypto.SSL_shutdown(s, INVALID_FD, DUMMY_CB);
   1495         } catch (SSLProtocolException expected) {
   1496         }
   1497         NativeCrypto.SSL_free(s);
   1498         NativeCrypto.SSL_CTX_free(c);
   1499 
   1500         // positively tested elsewhere because handshake uses use
   1501         // SSL_shutdown to ensure SSL_SESSIONs are reused.
   1502     }
   1503 
   1504     public void test_SSL_free() throws Exception {
   1505         try {
   1506             NativeCrypto.SSL_free(NULL);
   1507             fail();
   1508         } catch (NullPointerException expected) {
   1509         }
   1510 
   1511         int c = NativeCrypto.SSL_CTX_new();
   1512         NativeCrypto.SSL_free(NativeCrypto.SSL_new(c));
   1513         NativeCrypto.SSL_CTX_free(c);
   1514 
   1515         // additional positive testing elsewhere because handshake
   1516         // uses use SSL_free to cleanup in afterHandshake.
   1517     }
   1518 
   1519     public void test_SSL_SESSION_session_id() throws Exception {
   1520         try {
   1521             NativeCrypto.SSL_SESSION_session_id(NULL);
   1522             fail();
   1523         } catch (NullPointerException expected) {
   1524         }
   1525 
   1526         final ServerSocket listener = new ServerSocket(0);
   1527 
   1528         Hooks cHooks = new Hooks() {
   1529             @Override
   1530             public void afterHandshake(int session, int s, int c,
   1531                                        Socket sock, FileDescriptor fd,
   1532                                        SSLHandshakeCallbacks callback)
   1533                     throws Exception {
   1534                 byte[] id = NativeCrypto.SSL_SESSION_session_id(session);
   1535                 assertNotNull(id);
   1536                 assertEquals(32, id.length);
   1537                 super.afterHandshake(session, s, c, sock, fd, callback);
   1538             }
   1539         };
   1540         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1541         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1542         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1543         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1544         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1545     }
   1546 
   1547     public void test_SSL_SESSION_get_time() throws Exception {
   1548         try {
   1549             NativeCrypto.SSL_SESSION_get_time(NULL);
   1550             fail();
   1551         } catch (NullPointerException expected) {
   1552         }
   1553 
   1554         final ServerSocket listener = new ServerSocket(0);
   1555 
   1556         {
   1557             Hooks cHooks = new Hooks() {
   1558                 @Override
   1559                 public void afterHandshake(int session, int s, int c,
   1560                                            Socket sock, FileDescriptor fd,
   1561                                            SSLHandshakeCallbacks callback)
   1562                         throws Exception {
   1563                     long time = NativeCrypto.SSL_SESSION_get_time(session);
   1564                     assertTrue(time != 0);
   1565                     assertTrue(time < System.currentTimeMillis());
   1566                     super.afterHandshake(session, s, c, sock, fd, callback);
   1567                 }
   1568             };
   1569             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1570             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1571             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1572             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1573             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1574         }
   1575     }
   1576 
   1577     public void test_SSL_SESSION_get_version() throws Exception {
   1578         try {
   1579             NativeCrypto.SSL_SESSION_get_version(NULL);
   1580             fail();
   1581         } catch (NullPointerException expected) {
   1582         }
   1583 
   1584         final ServerSocket listener = new ServerSocket(0);
   1585 
   1586         Hooks cHooks = new Hooks() {
   1587             @Override
   1588             public void afterHandshake(int session, int s, int c,
   1589                                        Socket sock, FileDescriptor fd,
   1590                                        SSLHandshakeCallbacks callback)
   1591                     throws Exception {
   1592                 String v = NativeCrypto.SSL_SESSION_get_version(session);
   1593                 assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v));
   1594                 super.afterHandshake(session, s, c, sock, fd, callback);
   1595             }
   1596         };
   1597         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1598         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1599         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1600         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1601         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1602     }
   1603 
   1604     public void test_SSL_SESSION_cipher() throws Exception {
   1605         try {
   1606             NativeCrypto.SSL_SESSION_cipher(NULL);
   1607             fail();
   1608         } catch (NullPointerException expected) {
   1609         }
   1610 
   1611         final ServerSocket listener = new ServerSocket(0);
   1612 
   1613         Hooks cHooks = new Hooks() {
   1614             @Override
   1615             public void afterHandshake(int session, int s, int c,
   1616                                        Socket sock, FileDescriptor fd,
   1617                                        SSLHandshakeCallbacks callback)
   1618                         throws Exception {
   1619                 String a = NativeCrypto.SSL_SESSION_cipher(session);
   1620                 assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a));
   1621                 super.afterHandshake(session, s, c, sock, fd, callback);
   1622             }
   1623         };
   1624         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1625         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1626         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1627         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1628         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1629     }
   1630 
   1631     public void test_SSL_SESSION_compress_meth_null() throws Exception {
   1632         try {
   1633             NativeCrypto.SSL_SESSION_compress_meth(NULL, NULL);
   1634             fail();
   1635         } catch (NullPointerException expected) {
   1636         }
   1637 
   1638         {
   1639             int c = NativeCrypto.SSL_CTX_new();
   1640             try {
   1641                 NativeCrypto.SSL_SESSION_compress_meth(c, NULL);
   1642             } catch (NullPointerException expected) {
   1643             }
   1644             NativeCrypto.SSL_CTX_free(c);
   1645         }
   1646     }
   1647 
   1648     public void test_SSL_SESSION_compress_meth_NULL() throws Exception {
   1649         final ServerSocket listener = new ServerSocket(0);
   1650 
   1651         Hooks cHooks = new Hooks() {
   1652             @Override
   1653             public void afterHandshake(int session, int s, int c,
   1654                                        Socket sock, FileDescriptor fd,
   1655                                        SSLHandshakeCallbacks callback)
   1656                     throws Exception {
   1657                 assertEquals("NULL", NativeCrypto.SSL_SESSION_compress_meth(c, session));
   1658                 super.afterHandshake(session, s, c, sock, fd, callback);
   1659             }
   1660         };
   1661         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1662         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1663         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1664         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1665         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1666     }
   1667 
   1668     public void test_SSL_SESSION_compress_meth_ZLIB() throws Exception {
   1669         final ServerSocket listener = new ServerSocket(0);
   1670 
   1671         Hooks cHooks = new Hooks() {
   1672             @Override
   1673             public int beforeHandshake(int c) throws SSLException {
   1674                 int s = super.beforeHandshake(c);
   1675                 NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION);
   1676                 return s;
   1677             }
   1678             @Override
   1679             public void afterHandshake(int session, int s, int c,
   1680                                        Socket sock, FileDescriptor fd,
   1681                                        SSLHandshakeCallbacks callback)
   1682                     throws Exception {
   1683                 assertEquals("ZLIB", NativeCrypto.SSL_SESSION_compress_meth(c, session));
   1684                 super.afterHandshake(session, s, c, sock, fd, callback);
   1685             }
   1686         };
   1687         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1688             @Override
   1689             public int beforeHandshake(int c) throws SSLException {
   1690                 int s = super.beforeHandshake(c);
   1691                 NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION);
   1692                 return s;
   1693             }
   1694         };
   1695         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1696         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1697         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1698         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1699     }
   1700 
   1701     public void test_SSL_SESSION_free() throws Exception {
   1702         try {
   1703             NativeCrypto.SSL_SESSION_free(NULL);
   1704             fail();
   1705         } catch (NullPointerException expected) {
   1706         }
   1707 
   1708         // additional positive testing elsewhere because handshake
   1709         // uses use SSL_SESSION_free to cleanup in afterHandshake.
   1710     }
   1711 
   1712     public void test_i2d_SSL_SESSION() throws Exception {
   1713         try {
   1714             NativeCrypto.i2d_SSL_SESSION(NULL);
   1715             fail();
   1716         } catch (NullPointerException expected) {
   1717         }
   1718 
   1719         final ServerSocket listener = new ServerSocket(0);
   1720 
   1721         Hooks cHooks = new Hooks() {
   1722             @Override
   1723             public void afterHandshake(int session, int s, int c,
   1724                                        Socket sock, FileDescriptor fd,
   1725                                        SSLHandshakeCallbacks callback)
   1726                     throws Exception {
   1727                 byte[] b = NativeCrypto.i2d_SSL_SESSION(session);
   1728                 assertNotNull(b);
   1729                 int session2 = NativeCrypto.d2i_SSL_SESSION(b);
   1730                 assertTrue(session2 != NULL);
   1731                 NativeCrypto.SSL_SESSION_free(session2);
   1732                 super.afterHandshake(session, s, c, sock, fd, callback);
   1733             }
   1734         };
   1735         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1736         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null);
   1737         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null);
   1738         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1739         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1740     }
   1741 
   1742     public void test_d2i_SSL_SESSION() throws Exception {
   1743         try {
   1744             NativeCrypto.d2i_SSL_SESSION(null);
   1745             fail();
   1746         } catch (NullPointerException expected) {
   1747         }
   1748 
   1749         assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[0]));
   1750         assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[1]));
   1751 
   1752         // positively testing by test_i2d_SSL_SESSION
   1753     }
   1754 
   1755     public void test_X509_NAME_hashes() {
   1756         // ensure these hash functions are stable over time since the
   1757         // /system/etc/security/cacerts CA filenames have to be
   1758         // consistent with the output.
   1759         X500Principal name = new X500Principal("CN=localhost");
   1760         assertEquals(-1372642656, NativeCrypto.X509_NAME_hash(name)); // SHA1
   1761         assertEquals(-1626170662, NativeCrypto.X509_NAME_hash_old(name)); // MD5
   1762     }
   1763 
   1764     public void test_ENGINE_by_id_Failure() throws Exception {
   1765         NativeCrypto.ENGINE_load_dynamic();
   1766 
   1767         try {
   1768             int engine = NativeCrypto.ENGINE_by_id("non-existent");
   1769             fail("Shouldn't load non-existent engine");
   1770         } catch (RuntimeException e) {
   1771             // Success
   1772         }
   1773     }
   1774 }
   1775