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