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