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