Home | History | Annotate | Download | only in conscrypt
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.conscrypt;
     18 
     19 import java.io.ByteArrayInputStream;
     20 import java.io.ByteArrayOutputStream;
     21 import java.io.FileDescriptor;
     22 import java.io.IOException;
     23 import java.io.UnsupportedEncodingException;
     24 import java.math.BigInteger;
     25 import java.net.ServerSocket;
     26 import java.net.Socket;
     27 import java.net.SocketException;
     28 import java.net.SocketTimeoutException;
     29 import java.security.KeyPair;
     30 import java.security.KeyPairGenerator;
     31 import java.security.KeyStore;
     32 import java.security.KeyStore.PrivateKeyEntry;
     33 import java.security.cert.Certificate;
     34 import java.security.cert.CertificateEncodingException;
     35 import java.security.cert.CertificateException;
     36 import java.security.cert.X509Certificate;
     37 import java.security.interfaces.ECPublicKey;
     38 import java.security.interfaces.RSAPrivateCrtKey;
     39 import java.security.interfaces.RSAPublicKey;
     40 import java.security.spec.ECPrivateKeySpec;
     41 import java.util.ArrayList;
     42 import java.util.Arrays;
     43 import java.util.HashSet;
     44 import java.util.List;
     45 import java.util.concurrent.Callable;
     46 import java.util.concurrent.ExecutionException;
     47 import java.util.concurrent.ExecutorService;
     48 import java.util.concurrent.Executors;
     49 import java.util.concurrent.Future;
     50 import java.util.concurrent.TimeUnit;
     51 
     52 import javax.net.ssl.SSLException;
     53 import javax.net.ssl.SSLHandshakeException;
     54 import javax.net.ssl.SSLProtocolException;
     55 import javax.security.auth.x500.X500Principal;
     56 
     57 import junit.framework.TestCase;
     58 import libcore.io.IoUtils;
     59 import libcore.java.security.StandardNames;
     60 import libcore.java.security.TestKeyStore;
     61 
     62 import org.conscrypt.NativeCrypto.SSLHandshakeCallbacks;
     63 import static org.conscrypt.NativeConstants.SSL_MODE_CBC_RECORD_SPLITTING;
     64 import static org.conscrypt.NativeConstants.SSL_MODE_HANDSHAKE_CUTTHROUGH;
     65 
     66 import static org.conscrypt.TestUtils.openTestFile;
     67 import static org.conscrypt.TestUtils.readTestFile;
     68 
     69 public class NativeCryptoTest extends TestCase {
     70     /** Corresponds to the native test library "libjavacoretests.so" */
     71     public static final String TEST_ENGINE_ID = "javacoretests";
     72 
     73     private static final long NULL = 0;
     74     private static final FileDescriptor INVALID_FD = new FileDescriptor();
     75     private static final SSLHandshakeCallbacks DUMMY_CB
     76             = new TestSSLHandshakeCallbacks(null, 0, null);
     77 
     78     private static final long TIMEOUT_SECONDS = 5;
     79 
     80     private static OpenSSLKey SERVER_PRIVATE_KEY;
     81     private static OpenSSLX509Certificate[] SERVER_CERTIFICATES_HOLDER;
     82     private static long[] SERVER_CERTIFICATES;
     83     private static OpenSSLKey CLIENT_PRIVATE_KEY;
     84     private static OpenSSLX509Certificate[] CLIENT_CERTIFICATES_HOLDER;
     85     private static long[] CLIENT_CERTIFICATES;
     86     private static byte[][] CA_PRINCIPALS;
     87     private static OpenSSLKey CHANNEL_ID_PRIVATE_KEY;
     88     private static byte[] CHANNEL_ID;
     89 
     90     @Override
     91     protected void tearDown() throws Exception {
     92         assertEquals(0, NativeCrypto.ERR_peek_last_error());
     93     }
     94 
     95     private static OpenSSLKey getServerPrivateKey() {
     96         initCerts();
     97         return SERVER_PRIVATE_KEY;
     98     }
     99 
    100     private static long[] getServerCertificates() {
    101         initCerts();
    102         return SERVER_CERTIFICATES;
    103     }
    104 
    105     private static OpenSSLKey getClientPrivateKey() {
    106         initCerts();
    107         return CLIENT_PRIVATE_KEY;
    108     }
    109 
    110     private static long[] getClientCertificates() {
    111         initCerts();
    112         return CLIENT_CERTIFICATES;
    113     }
    114 
    115     private static byte[][] getCaPrincipals() {
    116         initCerts();
    117         return CA_PRINCIPALS;
    118     }
    119 
    120     /**
    121      * Lazily create shared test certificates.
    122      */
    123     private static synchronized void initCerts() {
    124         if (SERVER_PRIVATE_KEY != null) {
    125             return;
    126         }
    127 
    128         try {
    129             PrivateKeyEntry serverPrivateKeyEntry
    130                     = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
    131             SERVER_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(serverPrivateKeyEntry.getPrivateKey());
    132             SERVER_CERTIFICATES_HOLDER = encodeCertificateList(
    133                     serverPrivateKeyEntry.getCertificateChain());
    134             SERVER_CERTIFICATES = getCertificateReferences(SERVER_CERTIFICATES_HOLDER);
    135 
    136             PrivateKeyEntry clientPrivateKeyEntry
    137                     = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
    138             CLIENT_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(clientPrivateKeyEntry.getPrivateKey());
    139             CLIENT_CERTIFICATES_HOLDER = encodeCertificateList(
    140                     clientPrivateKeyEntry.getCertificateChain());
    141             CLIENT_CERTIFICATES = getCertificateReferences(CLIENT_CERTIFICATES_HOLDER);
    142 
    143             KeyStore ks = TestKeyStore.getClient().keyStore;
    144             String caCertAlias = ks.aliases().nextElement();
    145             X509Certificate certificate = (X509Certificate) ks.getCertificate(caCertAlias);
    146             X500Principal principal = certificate.getIssuerX500Principal();
    147             CA_PRINCIPALS = new byte[][] { principal.getEncoded() };
    148             initChannelIdKey();
    149         } catch (Exception e) {
    150             throw new RuntimeException(e);
    151         }
    152     }
    153 
    154     private static long[] getCertificateReferences(OpenSSLX509Certificate[] certs) {
    155         final long[] certRefs = new long[certs.length];
    156         for (int i = 0; i < certs.length; i++) {
    157             certRefs[i] = certs[i].getContext();
    158         }
    159         return certRefs;
    160     }
    161 
    162     private static OpenSSLX509Certificate[] encodeCertificateList(Certificate[] chain)
    163             throws CertificateEncodingException {
    164         final OpenSSLX509Certificate[] openSslCerts = new OpenSSLX509Certificate[chain.length];
    165         for (int i = 0; i < chain.length; i++) {
    166             openSslCerts[i] = OpenSSLX509Certificate.fromCertificate(chain[i]);
    167         }
    168         return openSslCerts;
    169     }
    170 
    171     private static synchronized void initChannelIdKey() throws Exception {
    172         if (CHANNEL_ID_PRIVATE_KEY != null) {
    173             return;
    174         }
    175 
    176         // NIST P-256 aka SECG secp256r1 aka X9.62 prime256v1
    177         OpenSSLECGroupContext openSslSpec = OpenSSLECGroupContext.getCurveByName("prime256v1");
    178         BigInteger s = new BigInteger(
    179                 "229cdbbf489aea584828a261a23f9ff8b0f66f7ccac98bf2096ab3aee41497c5", 16);
    180         CHANNEL_ID_PRIVATE_KEY = new OpenSSLECPrivateKey(
    181                 new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec())).getOpenSSLKey();
    182 
    183         // Channel ID is the concatenation of the X and Y coordinates of the public key.
    184         CHANNEL_ID = new BigInteger(
    185                 "702b07871fd7955c320b26f15e244e47eed60272124c92b9ebecf0b42f90069b" +
    186                         "ab53592ebfeb4f167dbf3ce61513afb0e354c479b1c1b69874fa471293494f77",
    187                 16).toByteArray();
    188     }
    189 
    190     public static void assertEqualSessions(long expected, long actual) {
    191         assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected),
    192                               NativeCrypto.SSL_SESSION_session_id(actual));
    193     }
    194     public static void assertEqualByteArrays(byte[] expected, byte[] actual) {
    195         assertEquals(Arrays.toString(expected), Arrays.toString(actual));
    196     }
    197 
    198     public static void assertEqualPrincipals(byte[][] expected, byte[][] actual) {
    199         assertEqualByteArrays(expected, actual);
    200     }
    201 
    202     public static void assertEqualCertificateChains(long[] expected, long[] actual) {
    203         assertEquals(expected.length, actual.length);
    204         for (int i = 0; i < expected.length; i++) {
    205             NativeCrypto.X509_cmp(expected[i], actual[i]);
    206         }
    207     }
    208 
    209     public static void assertEqualByteArrays(byte[][] expected, byte[][] actual) {
    210         assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual));
    211     }
    212 
    213     public void test_EVP_PKEY_cmp() throws Exception {
    214         try {
    215             NativeCrypto.EVP_PKEY_cmp(null, null);
    216             fail("Should throw NullPointerException when arguments are NULL");
    217         } catch (NullPointerException expected) {
    218         }
    219 
    220         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
    221         kpg.initialize(512);
    222 
    223         KeyPair kp1 = kpg.generateKeyPair();
    224         RSAPrivateCrtKey privKey1 = (RSAPrivateCrtKey) kp1.getPrivate();
    225 
    226         KeyPair kp2 = kpg.generateKeyPair();
    227         RSAPrivateCrtKey privKey2 = (RSAPrivateCrtKey) kp2.getPrivate();
    228 
    229         NativeRef.EVP_PKEY pkey1, pkey1_copy, pkey2;
    230         pkey1 = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
    231                 privKey1.getModulus().toByteArray(),
    232                 privKey1.getPublicExponent().toByteArray(),
    233                 privKey1.getPrivateExponent().toByteArray(),
    234                 privKey1.getPrimeP().toByteArray(),
    235                 privKey1.getPrimeQ().toByteArray(),
    236                 privKey1.getPrimeExponentP().toByteArray(),
    237                 privKey1.getPrimeExponentQ().toByteArray(),
    238                 privKey1.getCrtCoefficient().toByteArray()));
    239         assertNotSame(NULL, pkey1);
    240 
    241         pkey1_copy = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
    242                 privKey1.getModulus().toByteArray(),
    243                 privKey1.getPublicExponent().toByteArray(),
    244                 privKey1.getPrivateExponent().toByteArray(),
    245                 privKey1.getPrimeP().toByteArray(),
    246                 privKey1.getPrimeQ().toByteArray(),
    247                 privKey1.getPrimeExponentP().toByteArray(),
    248                 privKey1.getPrimeExponentQ().toByteArray(),
    249                 privKey1.getCrtCoefficient().toByteArray()));
    250         assertNotSame(NULL, pkey1_copy);
    251 
    252         pkey2 = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
    253                 privKey2.getModulus().toByteArray(),
    254                 privKey2.getPublicExponent().toByteArray(),
    255                 privKey2.getPrivateExponent().toByteArray(),
    256                 privKey2.getPrimeP().toByteArray(),
    257                 privKey2.getPrimeQ().toByteArray(),
    258                 privKey2.getPrimeExponentP().toByteArray(),
    259                 privKey2.getPrimeExponentQ().toByteArray(),
    260                 privKey2.getCrtCoefficient().toByteArray()));
    261         assertNotSame(NULL, pkey2);
    262 
    263         try {
    264             NativeCrypto.EVP_PKEY_cmp(pkey1, null);
    265             fail("Should throw NullPointerException when arguments are NULL");
    266         } catch (NullPointerException expected) {
    267         }
    268 
    269         try {
    270             NativeCrypto.EVP_PKEY_cmp(null, null);
    271             fail("Should throw NullPointerException when arguments are NULL");
    272         } catch (NullPointerException expected) {
    273         }
    274 
    275         assertEquals("Same keys should be the equal", 1,
    276                 NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1));
    277 
    278         assertEquals("Same keys should be the equal", 1,
    279                 NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1_copy));
    280 
    281         assertEquals("Different keys should not be equal", 0,
    282                 NativeCrypto.EVP_PKEY_cmp(pkey1, pkey2));
    283     }
    284 
    285     public void test_SSL_CTX_new() throws Exception {
    286         long c = NativeCrypto.SSL_CTX_new();
    287         assertTrue(c != NULL);
    288         long c2 = NativeCrypto.SSL_CTX_new();
    289         assertTrue(c != c2);
    290         NativeCrypto.SSL_CTX_free(c);
    291         NativeCrypto.SSL_CTX_free(c2);
    292     }
    293 
    294     public void test_SSL_CTX_free() throws Exception {
    295         try {
    296             NativeCrypto.SSL_CTX_free(NULL);
    297             fail();
    298         } catch (NullPointerException expected) {
    299         }
    300 
    301         NativeCrypto.SSL_CTX_free(NativeCrypto.SSL_CTX_new());
    302     }
    303 
    304     public void test_SSL_CTX_set_session_id_context() throws Exception {
    305         byte[] empty = new byte[0];
    306         try {
    307             NativeCrypto.SSL_CTX_set_session_id_context(NULL, empty);
    308             fail();
    309         } catch (NullPointerException expected) {
    310         }
    311         long c = NativeCrypto.SSL_CTX_new();
    312         try {
    313             NativeCrypto.SSL_CTX_set_session_id_context(c, null);
    314             fail();
    315         } catch (NullPointerException expected) {
    316         }
    317         NativeCrypto.SSL_CTX_set_session_id_context(c, empty);
    318         NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[32]);
    319         try {
    320             NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[33]);
    321         } catch (IllegalArgumentException expected) {
    322         }
    323         NativeCrypto.SSL_CTX_free(c);
    324     }
    325 
    326     public void test_SSL_new() throws Exception {
    327         long c = NativeCrypto.SSL_CTX_new();
    328         long s = NativeCrypto.SSL_new(c);
    329 
    330         assertTrue(s != NULL);
    331         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
    332         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1) == 0);
    333         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1_1) == 0);
    334         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1_2) == 0);
    335 
    336         long s2 = NativeCrypto.SSL_new(c);
    337         assertTrue(s != s2);
    338         NativeCrypto.SSL_free(s2);
    339 
    340         NativeCrypto.SSL_free(s);
    341         NativeCrypto.SSL_CTX_free(c);
    342     }
    343 
    344     public void test_SSL_use_certificate() throws Exception {
    345         try {
    346             NativeCrypto.SSL_use_certificate(NULL, null);
    347             fail();
    348         } catch (NullPointerException expected) {
    349         }
    350 
    351         long c = NativeCrypto.SSL_CTX_new();
    352         long s = NativeCrypto.SSL_new(c);
    353 
    354         try {
    355             NativeCrypto.SSL_use_certificate(s, null);
    356             fail();
    357         } catch (NullPointerException expected) {
    358         }
    359 
    360         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    361 
    362         NativeCrypto.SSL_free(s);
    363         NativeCrypto.SSL_CTX_free(c);
    364     }
    365 
    366     public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
    367         initChannelIdKey();
    368 
    369         try {
    370             NativeCrypto.SSL_set1_tls_channel_id(NULL, null);
    371             fail();
    372         } catch (NullPointerException expected) {
    373         }
    374 
    375         long c = NativeCrypto.SSL_CTX_new();
    376         long s = NativeCrypto.SSL_new(c);
    377 
    378         try {
    379             NativeCrypto.SSL_set1_tls_channel_id(s, null);
    380             fail();
    381         } catch (NullPointerException expected) {
    382         }
    383 
    384         // Use the key natively. This works because the initChannelIdKey method ensures that the
    385         // key is backed by OpenSSL.
    386         NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY.getNativeRef());
    387 
    388         NativeCrypto.SSL_free(s);
    389         NativeCrypto.SSL_CTX_free(c);
    390     }
    391 
    392     public void test_SSL_use_PrivateKey() throws Exception {
    393         try {
    394             NativeCrypto.SSL_use_PrivateKey(NULL, null);
    395             fail();
    396         } catch (NullPointerException expected) {
    397         }
    398 
    399         long c = NativeCrypto.SSL_CTX_new();
    400         long s = NativeCrypto.SSL_new(c);
    401 
    402         try {
    403             NativeCrypto.SSL_use_PrivateKey(s, null);
    404             fail();
    405         } catch (NullPointerException expected) {
    406         }
    407 
    408         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
    409 
    410         NativeCrypto.SSL_free(s);
    411         NativeCrypto.SSL_CTX_free(c);
    412     }
    413 
    414     public void test_SSL_check_private_key_null() throws Exception {
    415         try {
    416             NativeCrypto.SSL_check_private_key(NULL);
    417             fail();
    418         } catch (NullPointerException expected) {
    419         }
    420     }
    421 
    422     public void test_SSL_check_private_key_no_key_no_cert() throws Exception {
    423         long c = NativeCrypto.SSL_CTX_new();
    424         long s = NativeCrypto.SSL_new(c);
    425 
    426         // neither private or certificate set
    427         try {
    428             NativeCrypto.SSL_check_private_key(s);
    429             fail();
    430         } catch (SSLException expected) {
    431         }
    432 
    433         NativeCrypto.SSL_free(s);
    434         NativeCrypto.SSL_CTX_free(c);
    435     }
    436 
    437     public void test_SSL_check_private_key_cert_then_key() throws Exception {
    438         long c = NativeCrypto.SSL_CTX_new();
    439         long s = NativeCrypto.SSL_new(c);
    440 
    441         // first certificate, then private
    442         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    443 
    444         try {
    445             NativeCrypto.SSL_check_private_key(s);
    446             fail();
    447         } catch (SSLException expected) {
    448         }
    449 
    450         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
    451         NativeCrypto.SSL_check_private_key(s);
    452 
    453         NativeCrypto.SSL_free(s);
    454         NativeCrypto.SSL_CTX_free(c);
    455     }
    456     public void test_SSL_check_private_key_key_then_cert() throws Exception {
    457         long c = NativeCrypto.SSL_CTX_new();
    458         long s = NativeCrypto.SSL_new(c);
    459 
    460         // first private, then certificate
    461         NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
    462 
    463         try {
    464             NativeCrypto.SSL_check_private_key(s);
    465             fail();
    466         } catch (SSLException expected) {
    467         }
    468 
    469         NativeCrypto.SSL_use_certificate(s, getServerCertificates());
    470         NativeCrypto.SSL_check_private_key(s);
    471 
    472         NativeCrypto.SSL_free(s);
    473         NativeCrypto.SSL_CTX_free(c);
    474     }
    475 
    476     public void test_SSL_get_mode() throws Exception {
    477         try {
    478             NativeCrypto.SSL_get_mode(NULL);
    479             fail();
    480         } catch (NullPointerException expected) {
    481         }
    482 
    483         long c = NativeCrypto.SSL_CTX_new();
    484         long s = NativeCrypto.SSL_new(c);
    485         assertTrue(NativeCrypto.SSL_get_mode(s) != 0);
    486         NativeCrypto.SSL_free(s);
    487         NativeCrypto.SSL_CTX_free(c);
    488     }
    489 
    490     public void test_SSL_set_mode_and_clear_mode() throws Exception {
    491         try {
    492             NativeCrypto.SSL_set_mode(NULL, 0);
    493             fail();
    494         } catch (NullPointerException expected) {
    495         }
    496 
    497         long c = NativeCrypto.SSL_CTX_new();
    498         long s = NativeCrypto.SSL_new(c);
    499         if (NativeCrypto.isBoringSSL) {
    500             // check SSL_MODE_HANDSHAKE_CUTTHROUGH on by default for BoringSSL
    501             assertEquals(SSL_MODE_HANDSHAKE_CUTTHROUGH,
    502                     NativeCrypto.SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
    503         } else {
    504             // check SSL_MODE_HANDSHAKE_CUTTHROUGH off by default for OpenSSL
    505             assertEquals(0, NativeCrypto.SSL_get_mode(s)
    506                     & SSL_MODE_HANDSHAKE_CUTTHROUGH);
    507         }
    508         // check SSL_MODE_CBC_RECORD_SPLITTING off by default
    509         assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_CBC_RECORD_SPLITTING);
    510 
    511         // set SSL_MODE_HANDSHAKE_CUTTHROUGH on
    512         NativeCrypto.SSL_set_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
    513         assertTrue((NativeCrypto.SSL_get_mode(s)
    514                 & SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0);
    515         // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off
    516         NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
    517         assertTrue((NativeCrypto.SSL_get_mode(s)
    518                     & SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0);
    519 
    520         NativeCrypto.SSL_free(s);
    521         NativeCrypto.SSL_CTX_free(c);
    522     }
    523 
    524     public void test_SSL_get_options() throws Exception {
    525         try {
    526             NativeCrypto.SSL_get_options(NULL);
    527             fail();
    528         } catch (NullPointerException expected) {
    529         }
    530 
    531         long c = NativeCrypto.SSL_CTX_new();
    532         long s = NativeCrypto.SSL_new(c);
    533         assertTrue(NativeCrypto.SSL_get_options(s) != 0);
    534         NativeCrypto.SSL_free(s);
    535         NativeCrypto.SSL_CTX_free(c);
    536     }
    537 
    538     public void test_SSL_set_options() throws Exception {
    539         try {
    540             NativeCrypto.SSL_set_options(NULL, 0);
    541             fail();
    542         } catch (NullPointerException expected) {
    543         }
    544 
    545         long c = NativeCrypto.SSL_CTX_new();
    546         long s = NativeCrypto.SSL_new(c);
    547         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
    548         NativeCrypto.SSL_set_options(s, NativeConstants.SSL_OP_NO_SSLv3);
    549         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) != 0);
    550         NativeCrypto.SSL_free(s);
    551         NativeCrypto.SSL_CTX_free(c);
    552     }
    553 
    554     public void test_SSL_clear_options() throws Exception {
    555         try {
    556             NativeCrypto.SSL_clear_options(NULL, 0);
    557             fail();
    558         } catch (NullPointerException expected) {
    559         }
    560 
    561         long c = NativeCrypto.SSL_CTX_new();
    562         long s = NativeCrypto.SSL_new(c);
    563         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
    564         NativeCrypto.SSL_set_options(s, NativeConstants.SSL_OP_NO_SSLv3);
    565         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) != 0);
    566         NativeCrypto.SSL_clear_options(s, NativeConstants.SSL_OP_NO_SSLv3);
    567         assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
    568         NativeCrypto.SSL_free(s);
    569         NativeCrypto.SSL_CTX_free(c);
    570     }
    571 
    572     public void test_SSL_set_cipher_lists() throws Exception {
    573         try {
    574             NativeCrypto.SSL_set_cipher_lists(NULL, null);
    575             fail("Exception not thrown for null ssl and null list");
    576         } catch (NullPointerException expected) {
    577         }
    578 
    579         long c = NativeCrypto.SSL_CTX_new();
    580         long s = NativeCrypto.SSL_new(c);
    581 
    582         try {
    583             NativeCrypto.SSL_set_cipher_lists(s, null);
    584             fail("Exception not thrown for null list");
    585         } catch (NullPointerException expected) {
    586         }
    587 
    588         // Explicitly checking that the empty list is allowed.
    589         // b/21816861
    590         NativeCrypto.SSL_set_cipher_lists(s, new String[]{});
    591 
    592         try {
    593             NativeCrypto.SSL_set_cipher_lists(s, new String[] { null });
    594             fail("Exception not thrown for list with null element");
    595         } catch (NullPointerException expected) {
    596         }
    597 
    598         // see OpenSSL ciphers man page
    599         String[] illegals = new String[] {
    600             // empty
    601             "",
    602             // never standardized
    603             "EXP1024-DES-CBC-SHA", "EXP1024-RC4-SHA", "DHE-DSS-RC4-SHA",
    604             // IDEA
    605             "IDEA-CBC-SHA", "IDEA-CBC-MD5"
    606         };
    607 
    608         for (String illegal : illegals) {
    609             try {
    610                 NativeCrypto.SSL_set_cipher_lists(s, new String[] { illegal });
    611                 fail("Exception now thrown for illegal cipher: " + illegal);
    612             } catch (IllegalArgumentException expected) {
    613             }
    614         }
    615 
    616         List<String> ciphers
    617                 = new ArrayList<String>(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.keySet());
    618         NativeCrypto.SSL_set_cipher_lists(s, ciphers.toArray(new String[ciphers.size()]));
    619 
    620         NativeCrypto.SSL_free(s);
    621         NativeCrypto.SSL_CTX_free(c);
    622     }
    623 
    624     public void test_SSL_set_verify() throws Exception {
    625         try {
    626             NativeCrypto.SSL_set_verify(NULL, 0);
    627             fail();
    628         } catch (NullPointerException expected) {
    629         }
    630 
    631         long c = NativeCrypto.SSL_CTX_new();
    632         long s = NativeCrypto.SSL_new(c);
    633         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
    634         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
    635         NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
    636         NativeCrypto.SSL_set_verify(s, (NativeCrypto.SSL_VERIFY_PEER
    637                                         | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT));
    638         NativeCrypto.SSL_free(s);
    639         NativeCrypto.SSL_CTX_free(c);
    640     }
    641 
    642     private static final boolean DEBUG = false;
    643 
    644     public static class Hooks {
    645         protected String negotiatedCipherSuite;
    646         private OpenSSLKey channelIdPrivateKey;
    647         protected boolean pskEnabled;
    648         protected byte[] pskKey;
    649         protected List<String> enabledCipherSuites;
    650 
    651         /**
    652          * @throws SSLException
    653          */
    654         public long getContext() throws SSLException {
    655             return NativeCrypto.SSL_CTX_new();
    656         }
    657         public long beforeHandshake(long context) throws SSLException {
    658             long s = NativeCrypto.SSL_new(context);
    659             // without this SSL_set_cipher_lists call the tests were
    660             // negotiating DHE-RSA-AES256-SHA by default which had
    661             // very slow ephemeral RSA key generation
    662             List<String> cipherSuites = new ArrayList<String>();
    663             if (enabledCipherSuites == null) {
    664                 cipherSuites.add("RC4-MD5");
    665                 if (pskEnabled) {
    666                     // In TLS-PSK the client indicates that PSK key exchange is desired by offering
    667                     // at least one PSK cipher suite.
    668                     cipherSuites.add(0, "PSK-AES128-CBC-SHA");
    669                 }
    670             } else {
    671                 cipherSuites.addAll(enabledCipherSuites);
    672             }
    673             NativeCrypto.SSL_set_cipher_lists(
    674                     s, cipherSuites.toArray(new String[cipherSuites.size()]));
    675 
    676             if (channelIdPrivateKey != null) {
    677                 NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey.getNativeRef());
    678             }
    679             return s;
    680         }
    681         public void configureCallbacks(
    682                 @SuppressWarnings("unused") TestSSLHandshakeCallbacks callbacks) {}
    683         public void clientCertificateRequested(@SuppressWarnings("unused") long s) {}
    684         public void afterHandshake(long session, long ssl, long context,
    685                                    Socket socket, FileDescriptor fd,
    686                                    SSLHandshakeCallbacks callback)
    687                 throws Exception {
    688             if (session != NULL) {
    689                 negotiatedCipherSuite = NativeCrypto.SSL_SESSION_cipher(session);
    690                 NativeCrypto.SSL_SESSION_free(session);
    691             }
    692             if (ssl != NULL) {
    693                 try {
    694                     NativeCrypto.SSL_shutdown(ssl, fd, callback);
    695                 } catch (IOException e) {
    696                 }
    697                 NativeCrypto.SSL_free(ssl);
    698             }
    699             if (context != NULL) {
    700                 NativeCrypto.SSL_CTX_free(context);
    701             }
    702             if (socket != null) {
    703                 socket.close();
    704             }
    705         }
    706     }
    707 
    708     public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks {
    709         private final Socket socket;
    710         private final long sslNativePointer;
    711         private final Hooks hooks;
    712 
    713         public TestSSLHandshakeCallbacks(Socket socket,
    714                                          long sslNativePointer,
    715                                          Hooks hooks) {
    716             this.socket = socket;
    717             this.sslNativePointer = sslNativePointer;
    718             this.hooks = hooks;
    719         }
    720 
    721         public long[] certificateChainRefs;
    722         public String authMethod;
    723         public boolean verifyCertificateChainCalled;
    724 
    725         @Override
    726         public void verifyCertificateChain(long sslSessionNativePtr, long[] certChainRefs,
    727                 String authMethod) throws CertificateException {
    728             if (DEBUG) {
    729                 System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
    730                                    + " verifyCertificateChain"
    731                                    + " sessionPtr=0x" + Long.toString(sslSessionNativePtr, 16)
    732                                    + " asn1DerEncodedCertificateChain="
    733                                    + Arrays.toString(certChainRefs)
    734                                    + " authMethod=" + authMethod);
    735             }
    736             this.certificateChainRefs = certChainRefs;
    737             this.authMethod = authMethod;
    738             this.verifyCertificateChainCalled = true;
    739         }
    740 
    741         public byte[] keyTypes;
    742         public byte[][] asn1DerEncodedX500Principals;
    743         public boolean clientCertificateRequestedCalled;
    744 
    745         @Override
    746         public void clientCertificateRequested(byte[] keyTypes,
    747                                                byte[][] asn1DerEncodedX500Principals) {
    748             if (DEBUG) {
    749                 System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
    750                                    + " clientCertificateRequested"
    751                                    + " keyTypes=" + keyTypes
    752                                    + " asn1DerEncodedX500Principals="
    753                                    + asn1DerEncodedX500Principals);
    754             }
    755             this.keyTypes = keyTypes;
    756             this.asn1DerEncodedX500Principals = asn1DerEncodedX500Principals;
    757             this.clientCertificateRequestedCalled = true;
    758             if (hooks != null ) {
    759                 hooks.clientCertificateRequested(sslNativePointer);
    760             }
    761         }
    762 
    763         public boolean handshakeCompletedCalled;
    764 
    765         @Override
    766         public void onSSLStateChange(long sslSessionNativePtr, int type, int val) {
    767             if (DEBUG) {
    768                 System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
    769                                    + " onSSLStateChange");
    770             }
    771             this.handshakeCompletedCalled = true;
    772         }
    773 
    774         public Socket getSocket() {
    775             return socket;
    776         }
    777 
    778         private boolean clientPSKKeyRequestedInvoked;
    779         private String clientPSKKeyRequestedIdentityHint;
    780         private int clientPSKKeyRequestedResult;
    781         private byte[] clientPSKKeyRequestedResultKey;
    782         private byte[] clientPSKKeyRequestedResultIdentity;
    783 
    784         @Override
    785         public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
    786             if (DEBUG) {
    787                 System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
    788                                    + " clientPSKKeyRequested"
    789                                    + " identityHint=" + identityHint
    790                                    + " identity capacity=" + identity.length
    791                                    + " key capacity=" + key.length);
    792             }
    793             clientPSKKeyRequestedInvoked = true;
    794             clientPSKKeyRequestedIdentityHint = identityHint;
    795             if (clientPSKKeyRequestedResultKey != null) {
    796                 System.arraycopy(
    797                         clientPSKKeyRequestedResultKey, 0,
    798                         key, 0,
    799                         clientPSKKeyRequestedResultKey.length);
    800             }
    801             if (clientPSKKeyRequestedResultIdentity != null) {
    802                 System.arraycopy(
    803                         clientPSKKeyRequestedResultIdentity, 0,
    804                         identity, 0,
    805                         Math.min(clientPSKKeyRequestedResultIdentity.length, identity.length));
    806             }
    807             return clientPSKKeyRequestedResult;
    808         }
    809 
    810         private boolean serverPSKKeyRequestedInvoked;
    811         private int serverPSKKeyRequestedResult;
    812         private byte[] serverPSKKeyRequestedResultKey;
    813         private String serverPSKKeyRequestedIdentityHint;
    814         private String serverPSKKeyRequestedIdentity;
    815         @Override
    816         public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
    817             if (DEBUG) {
    818                 System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
    819                                    + " serverPSKKeyRequested"
    820                                    + " identityHint=" + identityHint
    821                                    + " identity=" + identity
    822                                    + " key capacity=" + key.length);
    823             }
    824             serverPSKKeyRequestedInvoked = true;
    825             serverPSKKeyRequestedIdentityHint = identityHint;
    826             serverPSKKeyRequestedIdentity = identity;
    827             if (serverPSKKeyRequestedResultKey != null) {
    828                 System.arraycopy(
    829                         serverPSKKeyRequestedResultKey, 0,
    830                         key, 0,
    831                         serverPSKKeyRequestedResultKey.length);
    832             }
    833             return serverPSKKeyRequestedResult;
    834         }
    835     }
    836 
    837     public static class ClientHooks extends Hooks {
    838         protected String pskIdentity;
    839 
    840         @Override
    841         public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
    842             super.configureCallbacks(callbacks);
    843             if (pskEnabled) {
    844                 if (pskIdentity != null) {
    845                     // Create a NULL-terminated modified UTF-8 representation of pskIdentity.
    846                     byte[] b;
    847                     try {
    848                         b = pskIdentity.getBytes("UTF-8");
    849                     } catch (UnsupportedEncodingException e) {
    850                         throw new RuntimeException("UTF-8 encoding not supported", e);
    851                     }
    852                     callbacks.clientPSKKeyRequestedResultIdentity =
    853                             Arrays.copyOf(b, b.length + 1);
    854                 }
    855                 callbacks.clientPSKKeyRequestedResultKey = pskKey;
    856                 callbacks.clientPSKKeyRequestedResult = (pskKey != null) ? pskKey.length : 0;
    857             }
    858         }
    859 
    860         @Override
    861         public long beforeHandshake(long c) throws SSLException {
    862             long s = super.beforeHandshake(c);
    863             if (pskEnabled) {
    864                 NativeCrypto.set_SSL_psk_client_callback_enabled(s, true);
    865             }
    866             return s;
    867         }
    868     }
    869 
    870     public static class ServerHooks extends Hooks {
    871         private final OpenSSLKey privateKey;
    872         private final long[] certificates;
    873         private boolean channelIdEnabled;
    874         private byte[] channelIdAfterHandshake;
    875         private Throwable channelIdAfterHandshakeException;
    876 
    877         protected String pskIdentityHint;
    878 
    879         public ServerHooks() {
    880             this(null, null);
    881         }
    882 
    883         public ServerHooks(OpenSSLKey privateKey, long[] certificates) {
    884             this.privateKey = privateKey;
    885             this.certificates = certificates;
    886         }
    887 
    888         @Override
    889         public long beforeHandshake(long c) throws SSLException {
    890             long s = super.beforeHandshake(c);
    891             if (privateKey != null) {
    892                 NativeCrypto.SSL_use_PrivateKey(s, privateKey.getNativeRef());
    893             }
    894             if (certificates != null) {
    895                 NativeCrypto.SSL_use_certificate(s, certificates);
    896             }
    897             if (channelIdEnabled) {
    898                 NativeCrypto.SSL_enable_tls_channel_id(s);
    899             }
    900             if (pskEnabled) {
    901                 NativeCrypto.set_SSL_psk_server_callback_enabled(s, true);
    902                 NativeCrypto.SSL_use_psk_identity_hint(s, pskIdentityHint);
    903             }
    904             NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
    905             return s;
    906         }
    907 
    908         @Override
    909         public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
    910             super.configureCallbacks(callbacks);
    911             if (pskEnabled) {
    912                 callbacks.serverPSKKeyRequestedResultKey = pskKey;
    913                 callbacks.serverPSKKeyRequestedResult = (pskKey != null) ? pskKey.length : 0;
    914             }
    915         }
    916 
    917         @Override
    918         public void afterHandshake(long session, long ssl, long context,
    919                                    Socket socket, FileDescriptor fd,
    920                                    SSLHandshakeCallbacks callback)
    921                 throws Exception {
    922           if (channelIdEnabled) {
    923             try {
    924               channelIdAfterHandshake = NativeCrypto.SSL_get_tls_channel_id(ssl);
    925             } catch (Exception e) {
    926               channelIdAfterHandshakeException = e;
    927             }
    928           }
    929           super.afterHandshake(session, ssl, context, socket, fd, callback);
    930         }
    931 
    932         @Override
    933         public void clientCertificateRequested(long s) {
    934             fail("Server asked for client certificates");
    935         }
    936     }
    937 
    938     public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
    939             final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols,
    940             final byte[] alpnProtocols) {
    941         ExecutorService executor = Executors.newSingleThreadExecutor();
    942         Future<TestSSLHandshakeCallbacks> future = executor.submit(
    943                 new Callable<TestSSLHandshakeCallbacks>() {
    944             @Override public TestSSLHandshakeCallbacks call() throws Exception {
    945                 @SuppressWarnings("resource") // Socket needs to remain open after the handshake
    946                 Socket socket = (client
    947                                  ? new Socket(listener.getInetAddress(),
    948                                               listener.getLocalPort())
    949                                  : listener.accept());
    950                 if (timeout == -1) {
    951                     return new TestSSLHandshakeCallbacks(socket, 0, null);
    952                 }
    953                 FileDescriptor fd = socket.getFileDescriptor$();
    954                 long c = hooks.getContext();
    955                 long s = hooks.beforeHandshake(c);
    956                 TestSSLHandshakeCallbacks callback
    957                         = new TestSSLHandshakeCallbacks(socket, s, hooks);
    958                 hooks.configureCallbacks(callback);
    959                 if (DEBUG) {
    960                     System.out.println("ssl=0x" + Long.toString(s, 16)
    961                                        + " handshake"
    962                                        + " context=0x" + Long.toString(c, 16)
    963                                        + " socket=" + socket
    964                                        + " fd=" + fd
    965                                        + " timeout=" + timeout
    966                                        + " client=" + client);
    967                 }
    968                 long session = NULL;
    969                 try {
    970                     session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
    971                                                             npnProtocols, alpnProtocols);
    972                     if (DEBUG) {
    973                         System.out.println("ssl=0x" + Long.toString(s, 16)
    974                                            + " handshake"
    975                                            + " session=0x" + Long.toString(session, 16));
    976                     }
    977                 } finally {
    978                     // Ensure afterHandshake is called to free resources
    979                     hooks.afterHandshake(session, s, c, socket, fd, callback);
    980                 }
    981                 return callback;
    982             }
    983         });
    984         executor.shutdown();
    985         return future;
    986     }
    987 
    988     public void test_SSL_do_handshake_NULL_SSL() throws Exception {
    989         try {
    990             NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null, null);
    991             fail();
    992         } catch (NullPointerException expected) {
    993         }
    994     }
    995 
    996     public void test_SSL_do_handshake_null_args() throws Exception {
    997         long c = NativeCrypto.SSL_CTX_new();
    998         long s = NativeCrypto.SSL_new(c);
    999 
   1000         try {
   1001             NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null, null);
   1002             fail();
   1003         } catch (NullPointerException expected) {
   1004         }
   1005 
   1006         try {
   1007             NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null, null);
   1008             fail();
   1009         } catch (NullPointerException expected) {
   1010         }
   1011 
   1012         NativeCrypto.SSL_free(s);
   1013         NativeCrypto.SSL_CTX_free(c);
   1014     }
   1015 
   1016     public void test_SSL_do_handshake_normal() throws Exception {
   1017         // normal client and server case
   1018         final ServerSocket listener = new ServerSocket(0);
   1019         Hooks cHooks = new Hooks();
   1020         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1021         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1022         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1023         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1024         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1025         assertTrue(clientCallback.verifyCertificateChainCalled);
   1026         assertEqualCertificateChains(getServerCertificates(),
   1027                                      clientCallback.certificateChainRefs);
   1028         assertEquals("RSA", clientCallback.authMethod);
   1029         assertFalse(serverCallback.verifyCertificateChainCalled);
   1030         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1031         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1032         assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
   1033         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1034         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1035         assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
   1036         assertTrue(clientCallback.handshakeCompletedCalled);
   1037         assertTrue(serverCallback.handshakeCompletedCalled);
   1038     }
   1039 
   1040     public void test_SSL_do_handshake_optional_client_certificate() throws Exception {
   1041         // optional client certificate case
   1042         final ServerSocket listener = new ServerSocket(0);
   1043 
   1044         Hooks cHooks = new Hooks() {
   1045             @Override
   1046             public void clientCertificateRequested(long s) {
   1047                 super.clientCertificateRequested(s);
   1048                 NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey().getNativeRef());
   1049                 NativeCrypto.SSL_use_certificate(s, getClientCertificates());
   1050             }
   1051         };
   1052         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1053             @Override
   1054             public long beforeHandshake(long c) throws SSLException {
   1055                 long s = super.beforeHandshake(c);
   1056                 NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
   1057                 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
   1058                 return s;
   1059             }
   1060         };
   1061         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1062         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1063         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1064         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1065         assertTrue(clientCallback.verifyCertificateChainCalled);
   1066         assertEqualCertificateChains(getServerCertificates(),
   1067                                      clientCallback.certificateChainRefs);
   1068         assertEquals("RSA", clientCallback.authMethod);
   1069         assertTrue(serverCallback.verifyCertificateChainCalled);
   1070         assertEqualCertificateChains(getClientCertificates(),
   1071                 serverCallback.certificateChainRefs);
   1072         assertEquals("RSA", serverCallback.authMethod);
   1073 
   1074         assertTrue(clientCallback.clientCertificateRequestedCalled);
   1075         assertNotNull(clientCallback.keyTypes);
   1076         assertEquals(new HashSet<String>(Arrays.asList("EC", "RSA")),
   1077                 SSLParametersImpl.getSupportedClientKeyTypes(clientCallback.keyTypes));
   1078         assertEqualPrincipals(getCaPrincipals(),
   1079                               clientCallback.asn1DerEncodedX500Principals);
   1080         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1081 
   1082         assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
   1083         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1084         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1085         assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
   1086 
   1087         assertTrue(clientCallback.handshakeCompletedCalled);
   1088         assertTrue(serverCallback.handshakeCompletedCalled);
   1089     }
   1090 
   1091     public void test_SSL_do_handshake_missing_required_certificate() throws Exception {
   1092         // required client certificate negative case
   1093         final ServerSocket listener = new ServerSocket(0);
   1094         try {
   1095             Hooks cHooks = new Hooks();
   1096             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1097                 @Override
   1098                 public long beforeHandshake(long c) throws SSLException {
   1099                     long s = super.beforeHandshake(c);
   1100                     NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
   1101                     NativeCrypto.SSL_set_verify(s,
   1102                                                 NativeCrypto.SSL_VERIFY_PEER
   1103                                                 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
   1104                     return s;
   1105                 }
   1106             };
   1107             @SuppressWarnings("unused")
   1108             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   1109                     null);
   1110             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   1111                     null);
   1112             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1113             fail();
   1114         } catch (ExecutionException expected) {
   1115             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1116         }
   1117     }
   1118 
   1119     /**
   1120      * Usually if a RuntimeException is thrown by the
   1121      * clientCertificateRequestedCalled callback, the caller sees it
   1122      * during the call to NativeCrypto_SSL_do_handshake.  However, IIS
   1123      * does not request client certs until after the initial
   1124      * handshake. It does an SSL renegotiation, which means we need to
   1125      * be able to deliver the callback's exception in cases like
   1126      * SSL_read, SSL_write, and SSL_shutdown.
   1127      */
   1128     public void test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate()
   1129             throws Exception {
   1130         final ServerSocket listener = new ServerSocket(0);
   1131 
   1132         Hooks cHooks = new Hooks() {
   1133             @Override
   1134             public long beforeHandshake(long context) throws SSLException {
   1135                 long s = super.beforeHandshake(context);
   1136                 NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
   1137                 return s;
   1138             }
   1139             @Override
   1140             public void afterHandshake(long session, long s, long c,
   1141                                        Socket sock, FileDescriptor fd,
   1142                                        SSLHandshakeCallbacks callback)
   1143                     throws Exception {
   1144                 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
   1145                 fail();
   1146                 super.afterHandshake(session, s, c, sock, fd, callback);
   1147             }
   1148             @Override
   1149             public void clientCertificateRequested(long s) {
   1150                 super.clientCertificateRequested(s);
   1151                 throw new RuntimeException("expected");
   1152             }
   1153         };
   1154         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1155             @Override
   1156             public void afterHandshake(long session, long s, long c,
   1157                                        Socket sock, FileDescriptor fd,
   1158                                        SSLHandshakeCallbacks callback)
   1159                     throws Exception {
   1160                 try {
   1161                     NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
   1162                     NativeCrypto.SSL_set_options(
   1163                             s, NativeConstants.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
   1164                     NativeCrypto.SSL_renegotiate(s);
   1165                     NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1,
   1166                                            (int) ((TIMEOUT_SECONDS * 1000) / 2));
   1167                 } catch (IOException expected) {
   1168                 } finally {
   1169                     super.afterHandshake(session, s, c, sock, fd, callback);
   1170                 }
   1171             }
   1172         };
   1173         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1174         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1175         try {
   1176             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1177         } catch (ExecutionException e) {
   1178             if (!"expected".equals(e.getCause().getMessage())) {
   1179                 throw e;
   1180             }
   1181         }
   1182         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1183     }
   1184 
   1185     public void test_SSL_do_handshake_client_timeout() throws Exception {
   1186         // client timeout
   1187         final ServerSocket listener = new ServerSocket(0);
   1188         Socket serverSocket = null;
   1189         try {
   1190             Hooks cHooks = new Hooks();
   1191             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1192             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null,
   1193                     null);
   1194             Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null,
   1195                     null);
   1196             serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
   1197             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1198             fail();
   1199         } catch (ExecutionException expected) {
   1200             if (SocketTimeoutException.class != expected.getCause().getClass()) {
   1201                 expected.printStackTrace();
   1202             }
   1203             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
   1204         } finally {
   1205             // Manually close peer socket when testing timeout
   1206             IoUtils.closeQuietly(serverSocket);
   1207         }
   1208     }
   1209 
   1210     public void test_SSL_do_handshake_server_timeout() throws Exception {
   1211         // server timeout
   1212         final ServerSocket listener = new ServerSocket(0);
   1213         Socket clientSocket = null;
   1214         try {
   1215             Hooks cHooks = new Hooks();
   1216             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1217             Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null, null);
   1218             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null, null);
   1219             clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
   1220             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1221             fail();
   1222         } catch (ExecutionException expected) {
   1223             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
   1224         } finally {
   1225             // Manually close peer socket when testing timeout
   1226             IoUtils.closeQuietly(clientSocket);
   1227         }
   1228     }
   1229 
   1230     public void test_SSL_do_handshake_with_channel_id_normal() throws Exception {
   1231         initChannelIdKey();
   1232 
   1233         // Normal handshake with TLS Channel ID.
   1234         final ServerSocket listener = new ServerSocket(0);
   1235         Hooks cHooks = new Hooks();
   1236         cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
   1237         // TLS Channel ID currently requires ECDHE-based key exchanges.
   1238         cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
   1239         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1240         sHooks.channelIdEnabled = true;
   1241         sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
   1242         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1243         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1244         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1245         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1246         assertTrue(clientCallback.verifyCertificateChainCalled);
   1247         assertEqualCertificateChains(getServerCertificates(),
   1248                                      clientCallback.certificateChainRefs);
   1249         assertEquals("ECDHE_RSA", clientCallback.authMethod);
   1250         assertFalse(serverCallback.verifyCertificateChainCalled);
   1251         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1252         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1253         assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
   1254         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1255         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1256         assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
   1257         assertTrue(clientCallback.handshakeCompletedCalled);
   1258         assertTrue(serverCallback.handshakeCompletedCalled);
   1259         assertNull(sHooks.channelIdAfterHandshakeException);
   1260         assertEqualByteArrays(CHANNEL_ID, sHooks.channelIdAfterHandshake);
   1261     }
   1262 
   1263     public void test_SSL_do_handshake_with_channel_id_not_supported_by_server() throws Exception {
   1264         initChannelIdKey();
   1265 
   1266         // Client tries to use TLS Channel ID but the server does not enable/offer the extension.
   1267         final ServerSocket listener = new ServerSocket(0);
   1268         Hooks cHooks = new Hooks();
   1269         cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
   1270         // TLS Channel ID currently requires ECDHE-based key exchanges.
   1271         cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
   1272         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1273         sHooks.channelIdEnabled = false;
   1274         sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
   1275         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1276         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1277         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1278         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1279         assertTrue(clientCallback.verifyCertificateChainCalled);
   1280         assertEqualCertificateChains(getServerCertificates(),
   1281                                      clientCallback.certificateChainRefs);
   1282         assertEquals("ECDHE_RSA", clientCallback.authMethod);
   1283         assertFalse(serverCallback.verifyCertificateChainCalled);
   1284         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1285         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1286         assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
   1287         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1288         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1289         assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
   1290         assertTrue(clientCallback.handshakeCompletedCalled);
   1291         assertTrue(serverCallback.handshakeCompletedCalled);
   1292         assertNull(sHooks.channelIdAfterHandshakeException);
   1293         assertNull(sHooks.channelIdAfterHandshake);
   1294     }
   1295 
   1296     public void test_SSL_do_handshake_with_channel_id_not_enabled_by_client() throws Exception {
   1297         initChannelIdKey();
   1298 
   1299         // Client does not use TLS Channel ID when the server has the extension enabled/offered.
   1300         final ServerSocket listener = new ServerSocket(0);
   1301         Hooks cHooks = new Hooks();
   1302         cHooks.channelIdPrivateKey = null;
   1303         // TLS Channel ID currently requires ECDHE-based key exchanges.
   1304         cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
   1305         ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1306         sHooks.channelIdEnabled = true;
   1307         sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
   1308         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1309         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1310         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1311         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1312         assertTrue(clientCallback.verifyCertificateChainCalled);
   1313         assertEqualCertificateChains(getServerCertificates(),
   1314                                      clientCallback.certificateChainRefs);
   1315         assertEquals("ECDHE_RSA", clientCallback.authMethod);
   1316         assertFalse(serverCallback.verifyCertificateChainCalled);
   1317         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1318         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1319         assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
   1320         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1321         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1322         assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
   1323         assertTrue(clientCallback.handshakeCompletedCalled);
   1324         assertTrue(serverCallback.handshakeCompletedCalled);
   1325         assertNull(sHooks.channelIdAfterHandshakeException);
   1326         assertNull(sHooks.channelIdAfterHandshake);
   1327     }
   1328 
   1329     public void test_SSL_do_handshake_with_psk_normal() throws Exception {
   1330         // normal TLS-PSK client and server case
   1331         final ServerSocket listener = new ServerSocket(0);
   1332         Hooks cHooks = new ClientHooks();
   1333         ServerHooks sHooks = new ServerHooks();
   1334         cHooks.pskEnabled = true;
   1335         sHooks.pskEnabled = true;
   1336         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1337         sHooks.pskKey = cHooks.pskKey;
   1338         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1339         Future<TestSSLHandshakeCallbacks> server =
   1340                 handshake(listener, 0, false, sHooks, null, null);
   1341         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1342         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1343         assertFalse(clientCallback.verifyCertificateChainCalled);
   1344         assertFalse(serverCallback.verifyCertificateChainCalled);
   1345         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1346         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1347         assertTrue(clientCallback.handshakeCompletedCalled);
   1348         assertTrue(serverCallback.handshakeCompletedCalled);
   1349         assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
   1350         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1351         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1352         assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
   1353         assertContains(cHooks.negotiatedCipherSuite, "PSK");
   1354         assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
   1355         assertNull(clientCallback.clientPSKKeyRequestedIdentityHint);
   1356         assertNull(serverCallback.serverPSKKeyRequestedIdentityHint);
   1357         assertEquals("", serverCallback.serverPSKKeyRequestedIdentity);
   1358     }
   1359 
   1360     public void test_SSL_do_handshake_with_psk_with_identity_and_hint() throws Exception {
   1361         // normal TLS-PSK client and server case where the server provides the client with a PSK
   1362         // identity hint, and the client provides the server with a PSK identity.
   1363         final ServerSocket listener = new ServerSocket(0);
   1364         ClientHooks cHooks = new ClientHooks();
   1365         ServerHooks sHooks = new ServerHooks();
   1366         cHooks.pskEnabled = true;
   1367         sHooks.pskEnabled = true;
   1368         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1369         sHooks.pskKey = cHooks.pskKey;
   1370         sHooks.pskIdentityHint = "Some non-ASCII characters: \u00c4\u0332";
   1371         cHooks.pskIdentity = "More non-ASCII characters: \u00f5\u044b";
   1372         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1373         Future<TestSSLHandshakeCallbacks> server =
   1374                 handshake(listener, 0, false, sHooks, null, null);
   1375         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1376         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1377         assertFalse(clientCallback.verifyCertificateChainCalled);
   1378         assertFalse(serverCallback.verifyCertificateChainCalled);
   1379         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1380         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1381         assertTrue(clientCallback.handshakeCompletedCalled);
   1382         assertTrue(serverCallback.handshakeCompletedCalled);
   1383         assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
   1384         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1385         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1386         assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
   1387         assertContains(cHooks.negotiatedCipherSuite, "PSK");
   1388         assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
   1389         assertEquals(sHooks.pskIdentityHint, clientCallback.clientPSKKeyRequestedIdentityHint);
   1390         assertEquals(sHooks.pskIdentityHint, serverCallback.serverPSKKeyRequestedIdentityHint);
   1391         assertEquals(cHooks.pskIdentity, serverCallback.serverPSKKeyRequestedIdentity);
   1392     }
   1393 
   1394     public void test_SSL_do_handshake_with_psk_with_identity_and_hint_of_max_length()
   1395             throws Exception {
   1396         // normal TLS-PSK client and server case where the server provides the client with a PSK
   1397         // identity hint, and the client provides the server with a PSK identity.
   1398         final ServerSocket listener = new ServerSocket(0);
   1399         ClientHooks cHooks = new ClientHooks();
   1400         ServerHooks sHooks = new ServerHooks();
   1401         cHooks.pskEnabled = true;
   1402         sHooks.pskEnabled = true;
   1403         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1404         sHooks.pskKey = cHooks.pskKey;
   1405         sHooks.pskIdentityHint = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
   1406                 + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx";
   1407         cHooks.pskIdentity = "123456789012345678901234567890123456789012345678901234567890"
   1408                 + "12345678901234567890123456789012345678901234567890123456789012345678";
   1409         assertEquals(PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES, sHooks.pskIdentityHint.length());
   1410         assertEquals(PSKKeyManager.MAX_IDENTITY_LENGTH_BYTES, cHooks.pskIdentity.length());
   1411         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1412         Future<TestSSLHandshakeCallbacks> server =
   1413                 handshake(listener, 0, false, sHooks, null, null);
   1414         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1415         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1416         assertFalse(clientCallback.verifyCertificateChainCalled);
   1417         assertFalse(serverCallback.verifyCertificateChainCalled);
   1418         assertFalse(clientCallback.clientCertificateRequestedCalled);
   1419         assertFalse(serverCallback.clientCertificateRequestedCalled);
   1420         assertTrue(clientCallback.handshakeCompletedCalled);
   1421         assertTrue(serverCallback.handshakeCompletedCalled);
   1422         assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
   1423         assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
   1424         assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
   1425         assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
   1426         assertContains(cHooks.negotiatedCipherSuite, "PSK");
   1427         assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
   1428         assertEquals(sHooks.pskIdentityHint, clientCallback.clientPSKKeyRequestedIdentityHint);
   1429         assertEquals(sHooks.pskIdentityHint, serverCallback.serverPSKKeyRequestedIdentityHint);
   1430         assertEquals(cHooks.pskIdentity, serverCallback.serverPSKKeyRequestedIdentity);
   1431     }
   1432 
   1433     public void test_SSL_do_handshake_with_psk_key_mismatch() throws Exception {
   1434         final ServerSocket listener = new ServerSocket(0);
   1435         ClientHooks cHooks = new ClientHooks();
   1436         ServerHooks sHooks = new ServerHooks();
   1437         cHooks.pskEnabled = true;
   1438         sHooks.pskEnabled = true;
   1439         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1440         sHooks.pskKey = "1, 2, 3, 3, Testing...".getBytes("UTF-8");
   1441         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1442         Future<TestSSLHandshakeCallbacks> server =
   1443                 handshake(listener, 0, false, sHooks, null, null);
   1444         try {
   1445             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1446             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1447             fail();
   1448         } catch (ExecutionException expected) {
   1449             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1450         }
   1451     }
   1452 
   1453     public void test_SSL_do_handshake_with_psk_with_no_client_key() throws Exception {
   1454         final ServerSocket listener = new ServerSocket(0);
   1455         ClientHooks cHooks = new ClientHooks();
   1456         ServerHooks sHooks = new ServerHooks();
   1457         cHooks.pskEnabled = true;
   1458         sHooks.pskEnabled = true;
   1459         cHooks.pskKey = null;
   1460         sHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1461         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1462         Future<TestSSLHandshakeCallbacks> server =
   1463                 handshake(listener, 0, false, sHooks, null, null);
   1464         try {
   1465             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1466             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1467             fail();
   1468         } catch (ExecutionException expected) {
   1469             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1470         }
   1471     }
   1472 
   1473     public void test_SSL_do_handshake_with_psk_with_no_server_key() throws Exception {
   1474         final ServerSocket listener = new ServerSocket(0);
   1475         ClientHooks cHooks = new ClientHooks();
   1476         ServerHooks sHooks = new ServerHooks();
   1477         cHooks.pskEnabled = true;
   1478         sHooks.pskEnabled = true;
   1479         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1480         sHooks.pskKey = null;
   1481         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1482         Future<TestSSLHandshakeCallbacks> server =
   1483                 handshake(listener, 0, false, sHooks, null, null);
   1484         try {
   1485             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1486             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1487             fail();
   1488         } catch (ExecutionException expected) {
   1489             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1490         }
   1491     }
   1492 
   1493     public void test_SSL_do_handshake_with_psk_key_too_long() throws Exception {
   1494         final ServerSocket listener = new ServerSocket(0);
   1495         ClientHooks cHooks = new ClientHooks() {
   1496             @Override
   1497             public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
   1498                 super.configureCallbacks(callbacks);
   1499                 callbacks.clientPSKKeyRequestedResult = PSKKeyManager.MAX_KEY_LENGTH_BYTES + 1;
   1500             }
   1501         };
   1502         ServerHooks sHooks = new ServerHooks();
   1503         cHooks.pskEnabled = true;
   1504         sHooks.pskEnabled = true;
   1505         cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
   1506         sHooks.pskKey = cHooks.pskKey;
   1507         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1508         Future<TestSSLHandshakeCallbacks> server =
   1509                 handshake(listener, 0, false, sHooks, null, null);
   1510         try {
   1511             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1512             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1513             fail();
   1514         } catch (ExecutionException expected) {
   1515             assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1516         }
   1517     }
   1518 
   1519     public void test_SSL_do_handshake_with_ocsp_response() throws Exception {
   1520         // This is only implemented for BoringSSL
   1521         if (!NativeCrypto.isBoringSSL) {
   1522             return;
   1523         }
   1524 
   1525         final byte[] OCSP_TEST_DATA = new byte[] { 1, 2, 3, 4};
   1526 
   1527         final ServerSocket listener = new ServerSocket(0);
   1528         Hooks cHooks = new Hooks() {
   1529             @Override
   1530             public long beforeHandshake(long c) throws SSLException {
   1531                 long s = super.beforeHandshake(c);
   1532                 NativeCrypto.SSL_enable_ocsp_stapling(s);
   1533                 return s;
   1534             }
   1535 
   1536             @Override
   1537             public void afterHandshake(long session, long ssl, long context, Socket socket,
   1538                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1539                 assertEqualByteArrays(OCSP_TEST_DATA, NativeCrypto.SSL_get_ocsp_response(ssl));
   1540                 super.afterHandshake(session, ssl, context, socket, fd, callback);
   1541             }
   1542         };
   1543 
   1544         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1545             @Override
   1546             public long beforeHandshake(long c) throws SSLException {
   1547                 NativeCrypto.SSL_CTX_set_ocsp_response(c, OCSP_TEST_DATA);
   1548                 return super.beforeHandshake(c);
   1549             }
   1550         };
   1551 
   1552         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1553         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1554         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1555         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1556 
   1557         assertTrue(clientCallback.handshakeCompletedCalled);
   1558         assertTrue(serverCallback.handshakeCompletedCalled);
   1559     }
   1560 
   1561     public void test_SSL_do_handshake_with_sct_extension() throws Exception {
   1562         // This is only implemented for BoringSSL
   1563         if (!NativeCrypto.isBoringSSL) {
   1564             return;
   1565         }
   1566 
   1567         final byte[] SCT_TEST_DATA = new byte[] { 1, 2, 3, 4};
   1568 
   1569         final ServerSocket listener = new ServerSocket(0);
   1570         Hooks cHooks = new Hooks() {
   1571             @Override
   1572             public long beforeHandshake(long c) throws SSLException {
   1573                 long s = super.beforeHandshake(c);
   1574                 NativeCrypto.SSL_enable_signed_cert_timestamps(s);
   1575                 return s;
   1576             }
   1577 
   1578             @Override
   1579             public void afterHandshake(long session, long ssl, long context, Socket socket,
   1580                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1581                 assertEqualByteArrays(SCT_TEST_DATA,
   1582                         NativeCrypto.SSL_get_signed_cert_timestamp_list(ssl));
   1583                 super.afterHandshake(session, ssl, context, socket, fd, callback);
   1584             }
   1585         };
   1586 
   1587         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1588             @Override
   1589             public long beforeHandshake(long c) throws SSLException {
   1590                 NativeCrypto.SSL_CTX_set_signed_cert_timestamp_list(c, SCT_TEST_DATA);
   1591                 return super.beforeHandshake(c);
   1592             }
   1593         };
   1594 
   1595         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1596         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1597         TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1598         TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1599 
   1600         assertTrue(clientCallback.handshakeCompletedCalled);
   1601         assertTrue(serverCallback.handshakeCompletedCalled);
   1602     }
   1603 
   1604     public void test_SSL_use_psk_identity_hint() throws Exception {
   1605         long c = NativeCrypto.SSL_CTX_new();
   1606         long s = NativeCrypto.SSL_new(c);
   1607         try {
   1608             NativeCrypto.SSL_use_psk_identity_hint(s, null);
   1609             NativeCrypto.SSL_use_psk_identity_hint(s, "test");
   1610 
   1611             try {
   1612                 // 800 characters is much longer than the permitted maximum.
   1613                 StringBuilder pskIdentityHint = new StringBuilder();
   1614                 for (int i = 0; i < 160; i++) {
   1615                     pskIdentityHint.append(" long");
   1616                 }
   1617                 assertTrue(pskIdentityHint.length() > PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES);
   1618                 NativeCrypto.SSL_use_psk_identity_hint(s, pskIdentityHint.toString());
   1619                 fail();
   1620             } catch (SSLException expected) {
   1621             }
   1622         } finally {
   1623             NativeCrypto.SSL_free(s);
   1624             NativeCrypto.SSL_CTX_free(c);
   1625         }
   1626     }
   1627 
   1628     public void test_SSL_set_session() throws Exception {
   1629         try {
   1630             NativeCrypto.SSL_set_session(NULL, NULL);
   1631             fail();
   1632         } catch (NullPointerException expected) {
   1633         }
   1634 
   1635         {
   1636             long c = NativeCrypto.SSL_CTX_new();
   1637             long s = NativeCrypto.SSL_new(c);
   1638             NativeCrypto.SSL_set_session(s, NULL);
   1639             NativeCrypto.SSL_free(s);
   1640             NativeCrypto.SSL_CTX_free(c);
   1641         }
   1642 
   1643         {
   1644             final long clientContext = NativeCrypto.SSL_CTX_new();
   1645             final long serverContext = NativeCrypto.SSL_CTX_new();
   1646             final ServerSocket listener = new ServerSocket(0);
   1647             final long[] clientSession = new long[] { NULL };
   1648             final long[] serverSession = new long[] { NULL };
   1649             {
   1650                 Hooks cHooks = new Hooks() {
   1651                     @Override
   1652                     public long getContext() throws SSLException {
   1653                         return clientContext;
   1654                     }
   1655                     @Override
   1656                     public void afterHandshake(long session, long s, long c,
   1657                                                Socket sock, FileDescriptor fd,
   1658                                                SSLHandshakeCallbacks callback)
   1659                             throws Exception {
   1660                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
   1661                         clientSession[0] = session;
   1662                     }
   1663                 };
   1664                 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1665                     @Override
   1666                     public long getContext() throws SSLException {
   1667                         return serverContext;
   1668                     }
   1669                     @Override
   1670                     public void afterHandshake(long session, long s, long c,
   1671                                                Socket sock, FileDescriptor fd,
   1672                                                SSLHandshakeCallbacks callback)
   1673                             throws Exception {
   1674                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
   1675                         serverSession[0] = session;
   1676                     }
   1677                 };
   1678                 Future<TestSSLHandshakeCallbacks> client
   1679                         = handshake(listener, 0, true, cHooks, null, null);
   1680                 Future<TestSSLHandshakeCallbacks> server
   1681                         = handshake(listener, 0, false, sHooks, null, null);
   1682                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1683                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1684             }
   1685             assertEqualSessions(clientSession[0], serverSession[0]);
   1686             {
   1687                 Hooks cHooks = new Hooks() {
   1688                     @Override
   1689                     public long getContext() throws SSLException {
   1690                         return clientContext;
   1691                     }
   1692                     @Override
   1693                     public long beforeHandshake(long c) throws SSLException {
   1694                         long s = NativeCrypto.SSL_new(clientContext);
   1695                         NativeCrypto.SSL_set_session(s, clientSession[0]);
   1696                         return s;
   1697                     }
   1698                     @Override
   1699                     public void afterHandshake(long session, long s, long c,
   1700                                                Socket sock, FileDescriptor fd,
   1701                                                SSLHandshakeCallbacks callback)
   1702                             throws Exception {
   1703                         assertEqualSessions(clientSession[0], session);
   1704                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
   1705                     }
   1706                 };
   1707                 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1708                     @Override
   1709                     public long getContext() throws SSLException {
   1710                         return serverContext;
   1711                     }
   1712                     @Override
   1713                     public void afterHandshake(long session, long s, long c,
   1714                                                Socket sock, FileDescriptor fd,
   1715                                                SSLHandshakeCallbacks callback)
   1716                             throws Exception {
   1717                         assertEqualSessions(serverSession[0], session);
   1718                         super.afterHandshake(NULL, s, NULL, sock, fd, callback);
   1719                     }
   1720                 };
   1721                 Future<TestSSLHandshakeCallbacks> client
   1722                         = handshake(listener, 0, true, cHooks, null, null);
   1723                 Future<TestSSLHandshakeCallbacks> server
   1724                         = handshake(listener, 0, false, sHooks, null, null);
   1725                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1726                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1727             }
   1728             NativeCrypto.SSL_SESSION_free(clientSession[0]);
   1729             NativeCrypto.SSL_SESSION_free(serverSession[0]);
   1730             NativeCrypto.SSL_CTX_free(serverContext);
   1731             NativeCrypto.SSL_CTX_free(clientContext);
   1732         }
   1733     }
   1734 
   1735     public void test_SSL_set_session_creation_enabled() throws Exception {
   1736         try {
   1737             NativeCrypto.SSL_set_session_creation_enabled(NULL, false);
   1738             fail();
   1739         } catch (NullPointerException expected) {
   1740         }
   1741 
   1742         {
   1743             long c = NativeCrypto.SSL_CTX_new();
   1744             long s = NativeCrypto.SSL_new(c);
   1745             NativeCrypto.SSL_set_session_creation_enabled(s, false);
   1746             NativeCrypto.SSL_set_session_creation_enabled(s, true);
   1747             NativeCrypto.SSL_free(s);
   1748             NativeCrypto.SSL_CTX_free(c);
   1749         }
   1750 
   1751         final ServerSocket listener = new ServerSocket(0);
   1752 
   1753         // negative test case for SSL_set_session_creation_enabled(false) on client
   1754         {
   1755             Hooks cHooks = new Hooks() {
   1756                 @Override
   1757                 public long beforeHandshake(long c) throws SSLException {
   1758                     long s = super.beforeHandshake(c);
   1759                     NativeCrypto.SSL_set_session_creation_enabled(s, false);
   1760                     return s;
   1761                 }
   1762             };
   1763             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   1764             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   1765                     null);
   1766             @SuppressWarnings("unused")
   1767             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   1768                     null);
   1769             try {
   1770                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1771                 fail();
   1772             } catch (ExecutionException expected) {
   1773                 assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1774             }
   1775             try {
   1776                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1777                 fail();
   1778             } catch (ExecutionException expected) {
   1779                 assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1780             }
   1781         }
   1782 
   1783         // negative test case for SSL_set_session_creation_enabled(false) on server
   1784         {
   1785             Hooks cHooks = new Hooks();
   1786             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1787                 @Override
   1788                 public long beforeHandshake(long c) throws SSLException {
   1789                     long s = super.beforeHandshake(c);
   1790                     NativeCrypto.SSL_set_session_creation_enabled(s, false);
   1791                     return s;
   1792                 }
   1793             };
   1794             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   1795                     null);
   1796             @SuppressWarnings("unused")
   1797             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   1798                     null);
   1799             try {
   1800                 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1801                 fail();
   1802             } catch (ExecutionException expected) {
   1803                 assertEquals(SSLHandshakeException.class, expected.getCause().getClass());
   1804             }
   1805             try {
   1806                 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1807                 fail();
   1808             } catch (ExecutionException expected) {
   1809                 assertEquals(SSLProtocolException.class, expected.getCause().getClass());
   1810             }
   1811         }
   1812     }
   1813 
   1814     public void test_SSL_set_tlsext_host_name() throws Exception {
   1815         // NULL SSL
   1816         try {
   1817             NativeCrypto.SSL_set_tlsext_host_name(NULL, null);
   1818             fail();
   1819         } catch (NullPointerException expected) {
   1820         }
   1821 
   1822         final String hostname = "www.android.com";
   1823 
   1824         {
   1825             long c = NativeCrypto.SSL_CTX_new();
   1826             long s = NativeCrypto.SSL_new(c);
   1827 
   1828             // null hostname
   1829             try {
   1830                 NativeCrypto.SSL_set_tlsext_host_name(s, null);
   1831                 fail();
   1832             } catch (NullPointerException expected) {
   1833             }
   1834 
   1835             // too long hostname
   1836             try {
   1837                 char[] longHostname = new char[256];
   1838                 Arrays.fill(longHostname, 'w');
   1839                 NativeCrypto.SSL_set_tlsext_host_name(s, new String(longHostname));
   1840                 fail();
   1841             } catch (SSLException expected) {
   1842             }
   1843 
   1844             assertNull(NativeCrypto.SSL_get_servername(s));
   1845             NativeCrypto.SSL_set_tlsext_host_name(s, new String(hostname));
   1846             assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
   1847 
   1848             NativeCrypto.SSL_free(s);
   1849             NativeCrypto.SSL_CTX_free(c);
   1850         }
   1851 
   1852         final ServerSocket listener = new ServerSocket(0);
   1853 
   1854         // normal
   1855         Hooks cHooks = new Hooks() {
   1856             @Override
   1857             public long beforeHandshake(long c) throws SSLException {
   1858                 long s = super.beforeHandshake(c);
   1859                 NativeCrypto.SSL_set_tlsext_host_name(s, hostname);
   1860                 return s;
   1861             }
   1862         };
   1863         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1864             @Override
   1865             public void afterHandshake(long session, long s, long c,
   1866                                        Socket sock, FileDescriptor fd,
   1867                                        SSLHandshakeCallbacks callback)
   1868                     throws Exception {
   1869                 assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
   1870                 super.afterHandshake(session, s, c, sock, fd, callback);
   1871             }
   1872         };
   1873         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   1874         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   1875         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1876         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1877     }
   1878 
   1879     public void test_SSL_NpnNegotiateSuccess() throws Exception {
   1880         final byte[] clientNpnProtocols = new byte[] {
   1881                 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
   1882                 3, 'f', 'o', 'o',
   1883                 6, 's', 'p', 'd', 'y', '/', '2',
   1884         };
   1885         final byte[] serverNpnProtocols = new byte[] {
   1886                 6, 's', 'p', 'd', 'y', '/', '2',
   1887                 3, 'f', 'o', 'o',
   1888                 3, 'b', 'a', 'r',
   1889         };
   1890 
   1891         Hooks cHooks = new Hooks() {
   1892             @Override public long beforeHandshake(long context) throws SSLException {
   1893                 NativeCrypto.SSL_CTX_enable_npn(context);
   1894                 return super.beforeHandshake(context);
   1895             }
   1896             @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
   1897                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1898                 byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
   1899                 assertEquals("spdy/2", new String(negotiated));
   1900                 /*
   1901                  * False Start (a.k.a. handshake cut-through):
   1902                  * In BoringSSL, this is enabled unconditionally since it
   1903                  * implements the check internally.
   1904                  */
   1905                 assertTrue("NPN should enable cutthrough on the client",
   1906                         0 != (NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH));
   1907                 NativeCrypto.SSL_write(ssl, fd, callback, new byte[] { 42 }, 0, 1,
   1908                         (int) ((TIMEOUT_SECONDS * 1000) / 2));
   1909                 super.afterHandshake(session, ssl, context, socket, fd, callback);
   1910             }
   1911         };
   1912         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1913             @Override public long beforeHandshake(long context) throws SSLException {
   1914                 NativeCrypto.SSL_CTX_enable_npn(context);
   1915                 return super.beforeHandshake(context);
   1916             }
   1917             @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
   1918                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1919                 byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
   1920                 assertEquals("spdy/2", new String(negotiated));
   1921                 if (!NativeCrypto.isBoringSSL) {
   1922                     /*
   1923                      * False Start (a.k.a. handshake cut-through):
   1924                      * In BoringSSL, this is enabled unconditionally since it
   1925                      * implements the check internally.
   1926                      */
   1927                     assertEquals("NPN should not enable cutthrough on the server",
   1928                             0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
   1929                 }
   1930                 byte[] buffer = new byte[1];
   1931                 NativeCrypto.SSL_read(ssl, fd, callback, buffer, 0, 1, 0);
   1932                 assertEquals(42, buffer[0]);
   1933                 super.afterHandshake(session, ssl, c, sock, fd, callback);
   1934             }
   1935         };
   1936 
   1937         ServerSocket listener = new ServerSocket(0);
   1938         Future<TestSSLHandshakeCallbacks> client
   1939                 = handshake(listener, 0, true, cHooks, clientNpnProtocols, null);
   1940         Future<TestSSLHandshakeCallbacks> server
   1941                 = handshake(listener, 0, false, sHooks, serverNpnProtocols, null);
   1942         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1943         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   1944     }
   1945 
   1946     public void test_SSL_AlpnNegotiateSuccess() throws Exception {
   1947         final byte[] clientAlpnProtocols = new byte[] {
   1948                 8, 'h', 't', 't', 'p', '/', '1', '.', '1',
   1949                 3, 'f', 'o', 'o',
   1950                 6, 's', 'p', 'd', 'y', '/', '2',
   1951         };
   1952         final byte[] serverAlpnProtocols = new byte[] {
   1953                 6, 's', 'p', 'd', 'y', '/', '2',
   1954                 3, 'f', 'o', 'o',
   1955                 3, 'b', 'a', 'r',
   1956         };
   1957 
   1958         Hooks cHooks = new Hooks() {
   1959             @Override public long beforeHandshake(long context) throws SSLException {
   1960                 long sslContext = super.beforeHandshake(context);
   1961                 NativeCrypto.SSL_set_alpn_protos(sslContext, clientAlpnProtocols);
   1962                 return sslContext;
   1963             }
   1964             @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
   1965                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1966                 byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
   1967                 assertEquals("spdy/2", new String(negotiated));
   1968                 if (!NativeCrypto.isBoringSSL) {
   1969                     /*
   1970                      * False Start (a.k.a. handshake cut-through):
   1971                      * There is no callback on the client, so we can't enable
   1972                      * cut-through on OpenSSL. In BoringSSL, this is enabled
   1973                      * unconditionally since it implements the check internally.
   1974                      */
   1975                     assertEquals("ALPN should not enable cutthrough on the client", 0,
   1976                             NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
   1977                 }
   1978                 super.afterHandshake(session, ssl, context, socket, fd, callback);
   1979             }
   1980         };
   1981         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   1982             @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
   1983                     FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
   1984                 byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
   1985                 assertEquals("spdy/2", new String(negotiated));
   1986                 if (!NativeCrypto.isBoringSSL) {
   1987                     /*
   1988                      * False Start (a.k.a. handshake cut-through):
   1989                      * In BoringSSL, this is enabled unconditionally since it
   1990                      * implements the check internally.
   1991                      */
   1992                     assertEquals("ALPN should not enable cutthrough on the server",
   1993                             0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
   1994                 }
   1995                 super.afterHandshake(session, ssl, c, sock, fd, callback);
   1996             }
   1997         };
   1998 
   1999         ServerSocket listener = new ServerSocket(0);
   2000         Future<TestSSLHandshakeCallbacks> client
   2001                 = handshake(listener, 0, true, cHooks, null, null);
   2002         Future<TestSSLHandshakeCallbacks> server
   2003                 = handshake(listener, 0, false, sHooks, null, serverAlpnProtocols);
   2004         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2005         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2006     }
   2007 
   2008     public void test_SSL_get_servername_null() throws Exception {
   2009         // NULL SSL
   2010         try {
   2011             NativeCrypto.SSL_get_servername(NULL);
   2012             fail();
   2013         } catch (NullPointerException expected) {
   2014         }
   2015 
   2016         long c = NativeCrypto.SSL_CTX_new();
   2017         long s = NativeCrypto.SSL_new(c);
   2018         assertNull(NativeCrypto.SSL_get_servername(s));
   2019         NativeCrypto.SSL_free(s);
   2020         NativeCrypto.SSL_CTX_free(c);
   2021 
   2022         // additional positive testing by test_SSL_set_tlsext_host_name
   2023     }
   2024 
   2025     public void test_SSL_renegotiate() throws Exception {
   2026         try {
   2027             NativeCrypto.SSL_renegotiate(NULL);
   2028             fail();
   2029         } catch (NullPointerException expected) {
   2030         }
   2031 
   2032         final ServerSocket listener = new ServerSocket(0);
   2033         Hooks cHooks = new Hooks() {
   2034             @Override
   2035             public void afterHandshake(long session, long s, long c,
   2036                                        Socket sock, FileDescriptor fd,
   2037                                        SSLHandshakeCallbacks callback)
   2038                     throws Exception {
   2039                 byte[] buffer = new byte[1];
   2040                 NativeCrypto.SSL_read(s, fd, callback, buffer, 0, 1, 0);
   2041                 assertEquals(42, buffer[0]);
   2042                 super.afterHandshake(session, s, c, sock, fd, callback);
   2043             }
   2044         };
   2045         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   2046             @Override
   2047             public void afterHandshake(long session, long s, long c,
   2048                                        Socket sock, FileDescriptor fd,
   2049                                        SSLHandshakeCallbacks callback)
   2050                 throws Exception {
   2051                 NativeCrypto.SSL_renegotiate(s);
   2052                 NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1, 0);
   2053                 super.afterHandshake(session, s, c, sock, fd, callback);
   2054             }
   2055         };
   2056         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2057         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2058         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2059         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2060     }
   2061 
   2062     public void test_SSL_get_certificate() throws Exception {
   2063         try {
   2064             NativeCrypto.SSL_get_certificate(NULL);
   2065             fail();
   2066         } catch (NullPointerException expected) {
   2067         }
   2068 
   2069         final ServerSocket listener = new ServerSocket(0);
   2070         Hooks cHooks = new Hooks() {
   2071             @Override
   2072             public void afterHandshake(long session, long s, long c,
   2073                                        Socket sock, FileDescriptor fd,
   2074                                        SSLHandshakeCallbacks callback)
   2075                 throws Exception {
   2076                 assertNull(NativeCrypto.SSL_get_certificate(s));
   2077                 super.afterHandshake(session, s, c, sock, fd, callback);
   2078             }
   2079         };
   2080         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   2081             @Override
   2082             public void afterHandshake(long session, long s, long c,
   2083                                        Socket sock, FileDescriptor fd,
   2084                                        SSLHandshakeCallbacks callback)
   2085                     throws Exception {
   2086                 assertEqualCertificateChains(
   2087                                              getServerCertificates(),
   2088                                              NativeCrypto.SSL_get_certificate(s));
   2089                 super.afterHandshake(session, s, c, sock, fd, callback);
   2090             }
   2091         };
   2092         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2093         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2094         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2095         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2096     }
   2097 
   2098     public void test_SSL_get_peer_cert_chain() throws Exception {
   2099         try {
   2100             NativeCrypto.SSL_get_peer_cert_chain(NULL);
   2101             fail();
   2102         } catch (NullPointerException expected) {
   2103         }
   2104 
   2105         final ServerSocket listener = new ServerSocket(0);
   2106 
   2107         Hooks cHooks = new Hooks() {
   2108             @Override
   2109             public void afterHandshake(long session, long s, long c,
   2110                                        Socket sock, FileDescriptor fd,
   2111                                        SSLHandshakeCallbacks callback)
   2112                     throws Exception {
   2113                 long[] cc = NativeCrypto.SSL_get_peer_cert_chain(s);
   2114                 assertEqualCertificateChains(getServerCertificates(), cc);
   2115                 for (long ref : cc) {
   2116                     NativeCrypto.X509_free(ref);
   2117                 }
   2118                 super.afterHandshake(session, s, c, sock, fd, callback);
   2119             }
   2120         };
   2121         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2122         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2123         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2124         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2125         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2126     }
   2127 
   2128     final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 };
   2129 
   2130     public void test_SSL_read() throws Exception {
   2131 
   2132         // NULL ssl
   2133         try {
   2134             NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0);
   2135             fail();
   2136         } catch (NullPointerException expected) {
   2137         }
   2138 
   2139         // null FileDescriptor
   2140         {
   2141             long c = NativeCrypto.SSL_CTX_new();
   2142             long s = NativeCrypto.SSL_new(c);
   2143             try {
   2144                 NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0);
   2145                 fail();
   2146             } catch (NullPointerException expected) {
   2147             }
   2148             NativeCrypto.SSL_free(s);
   2149             NativeCrypto.SSL_CTX_free(c);
   2150         }
   2151 
   2152         // null SSLHandshakeCallbacks
   2153         {
   2154             long c = NativeCrypto.SSL_CTX_new();
   2155             long s = NativeCrypto.SSL_new(c);
   2156             try {
   2157                 NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0);
   2158                 fail();
   2159             } catch (NullPointerException expected) {
   2160             }
   2161             NativeCrypto.SSL_free(s);
   2162             NativeCrypto.SSL_CTX_free(c);
   2163         }
   2164 
   2165         // null byte array
   2166         {
   2167             long c = NativeCrypto.SSL_CTX_new();
   2168             long s = NativeCrypto.SSL_new(c);
   2169             try {
   2170                 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0);
   2171                 fail();
   2172             } catch (NullPointerException expected) {
   2173             }
   2174             NativeCrypto.SSL_free(s);
   2175             NativeCrypto.SSL_CTX_free(c);
   2176         }
   2177 
   2178         // handshaking not yet performed
   2179         {
   2180             long c = NativeCrypto.SSL_CTX_new();
   2181             long s = NativeCrypto.SSL_new(c);
   2182             try {
   2183                 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
   2184                 fail();
   2185             } catch (SSLException expected) {
   2186             }
   2187             NativeCrypto.SSL_free(s);
   2188             NativeCrypto.SSL_CTX_free(c);
   2189         }
   2190 
   2191         final ServerSocket listener = new ServerSocket(0);
   2192 
   2193         // normal case
   2194         {
   2195             Hooks cHooks = new Hooks() {
   2196                 @Override
   2197                 public void afterHandshake(long session, long s, long c,
   2198                                            Socket sock, FileDescriptor fd,
   2199                                            SSLHandshakeCallbacks callback)
   2200                         throws Exception {
   2201                     byte[] in = new byte[256];
   2202                     assertEquals(BYTES.length,
   2203                                  NativeCrypto.SSL_read(s,
   2204                                                        fd,
   2205                                                        callback,
   2206                                                        in,
   2207                                                        0,
   2208                                                        BYTES.length,
   2209                                                        0));
   2210                     for (int i = 0; i < BYTES.length; i++) {
   2211                         assertEquals(BYTES[i], in[i]);
   2212                     }
   2213                     super.afterHandshake(session, s, c, sock, fd, callback);
   2214                 }
   2215             };
   2216             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   2217                 @Override
   2218                 public void afterHandshake(long session, long s, long c,
   2219                                            Socket sock, FileDescriptor fd,
   2220                                            SSLHandshakeCallbacks callback)
   2221                         throws Exception {
   2222                     NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length, 0);
   2223                     super.afterHandshake(session, s, c, sock, fd, callback);
   2224                 }
   2225             };
   2226             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   2227                     null);
   2228             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   2229                     null);
   2230             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2231             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2232         }
   2233 
   2234         // timeout case
   2235         try {
   2236             Hooks cHooks = new Hooks() {
   2237                 @Override
   2238                 public void afterHandshake(long session, long s, long c,
   2239                                            Socket sock, FileDescriptor fd,
   2240                                            SSLHandshakeCallbacks callback)
   2241                         throws Exception {
   2242                     NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1);
   2243                     fail();
   2244                 }
   2245             };
   2246             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   2247                 @Override
   2248                 public void afterHandshake(long session, long s, long c,
   2249                                            Socket sock, FileDescriptor fd,
   2250                                            SSLHandshakeCallbacks callback)
   2251                         throws Exception {
   2252                     NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
   2253                     super.afterHandshake(session, s, c, sock, fd, callback);
   2254                 }
   2255             };
   2256             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   2257                     null);
   2258             @SuppressWarnings("unused")
   2259             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   2260                     null);
   2261             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2262             fail();
   2263         } catch (ExecutionException expected) {
   2264             assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
   2265         }
   2266     }
   2267 
   2268     public void test_SSL_write() throws Exception {
   2269         try {
   2270             NativeCrypto.SSL_write(NULL, null, null, null, 0, 0, 0);
   2271             fail();
   2272         } catch (NullPointerException expected) {
   2273         }
   2274 
   2275         // null FileDescriptor
   2276         {
   2277             long c = NativeCrypto.SSL_CTX_new();
   2278             long s = NativeCrypto.SSL_new(c);
   2279             try {
   2280                 NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1, 0);
   2281                 fail();
   2282             } catch (NullPointerException expected) {
   2283             }
   2284             NativeCrypto.SSL_free(s);
   2285             NativeCrypto.SSL_CTX_free(c);
   2286         }
   2287 
   2288         // null SSLHandshakeCallbacks
   2289         {
   2290             long c = NativeCrypto.SSL_CTX_new();
   2291             long s = NativeCrypto.SSL_new(c);
   2292             try {
   2293                 NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1, 0);
   2294                 fail();
   2295             } catch (NullPointerException expected) {
   2296             }
   2297             NativeCrypto.SSL_free(s);
   2298             NativeCrypto.SSL_CTX_free(c);
   2299         }
   2300 
   2301         // null byte array
   2302         {
   2303             long c = NativeCrypto.SSL_CTX_new();
   2304             long s = NativeCrypto.SSL_new(c);
   2305             try {
   2306                 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1, 0);
   2307                 fail();
   2308             } catch (NullPointerException expected) {
   2309             }
   2310             NativeCrypto.SSL_free(s);
   2311             NativeCrypto.SSL_CTX_free(c);
   2312         }
   2313 
   2314         // handshaking not yet performed
   2315         {
   2316             long c = NativeCrypto.SSL_CTX_new();
   2317             long s = NativeCrypto.SSL_new(c);
   2318             try {
   2319                 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
   2320                 fail();
   2321             } catch (SSLException expected) {
   2322             }
   2323             NativeCrypto.SSL_free(s);
   2324             NativeCrypto.SSL_CTX_free(c);
   2325         }
   2326 
   2327         // positively tested by test_SSL_read
   2328     }
   2329 
   2330     public void test_SSL_interrupt() throws Exception {
   2331         // SSL_interrupt is a rare case that tolerates a null SSL argument
   2332         NativeCrypto.SSL_interrupt(NULL);
   2333 
   2334         // also works without handshaking
   2335         {
   2336             long c = NativeCrypto.SSL_CTX_new();
   2337             long s = NativeCrypto.SSL_new(c);
   2338             NativeCrypto.SSL_interrupt(s);
   2339             NativeCrypto.SSL_free(s);
   2340             NativeCrypto.SSL_CTX_free(c);
   2341         }
   2342 
   2343         final ServerSocket listener = new ServerSocket(0);
   2344 
   2345         Hooks cHooks = new Hooks() {
   2346             @Override
   2347             public void afterHandshake(long session, long s, long c,
   2348                                        Socket sock, FileDescriptor fd,
   2349                                        SSLHandshakeCallbacks callback)
   2350                     throws Exception {
   2351                 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
   2352                 super.afterHandshake(session, s, c, sock, fd, callback);
   2353             }
   2354         };
   2355         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
   2356             @Override
   2357             public void afterHandshake(long session, final long s, long c,
   2358                                        Socket sock, FileDescriptor fd,
   2359                                        SSLHandshakeCallbacks callback)
   2360                     throws Exception {
   2361                 new Thread() {
   2362                     @Override
   2363                     public void run() {
   2364                         try {
   2365                             Thread.sleep(1*1000);
   2366                             NativeCrypto.SSL_interrupt(s);
   2367                         } catch (Exception e) {
   2368                         }
   2369                     }
   2370                 }.start();
   2371                 assertEquals(-1, NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0));
   2372                 super.afterHandshake(session, s, c, sock, fd, callback);
   2373             }
   2374         };
   2375         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2376         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2377         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2378         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2379     }
   2380 
   2381     private static abstract class SSLSessionWrappedTask {
   2382         public abstract void run(long sslSession) throws Exception;
   2383     }
   2384 
   2385     private void wrapWithSSLSession(SSLSessionWrappedTask task) throws Exception {
   2386         long c = NativeCrypto.SSL_CTX_new();
   2387         long s = NativeCrypto.SSL_new(c);
   2388         try {
   2389             task.run(s);
   2390         } finally {
   2391             NativeCrypto.SSL_free(s);
   2392             NativeCrypto.SSL_CTX_free(c);
   2393         }
   2394     }
   2395 
   2396     public void test_SSL_shutdown() throws Exception {
   2397 
   2398         // null FileDescriptor
   2399         wrapWithSSLSession(new SSLSessionWrappedTask() {
   2400             @Override
   2401             public void run(long sslSession) throws Exception {
   2402                 try {
   2403                     NativeCrypto.SSL_shutdown(sslSession, null, DUMMY_CB);
   2404                     fail();
   2405                 } catch (NullPointerException expected) {
   2406                 }
   2407             }
   2408         });
   2409 
   2410         // null SSLHandshakeCallbacks
   2411         wrapWithSSLSession(new SSLSessionWrappedTask() {
   2412             @Override
   2413             public void run(long sslSession) throws Exception {
   2414                 try {
   2415                     NativeCrypto.SSL_shutdown(sslSession, INVALID_FD, null);
   2416                     fail();
   2417                 } catch (NullPointerException expected) {
   2418                 }
   2419             }
   2420         });
   2421 
   2422         // SSL_shutdown is a rare case that tolerates a null SSL argument
   2423         NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB);
   2424 
   2425         // handshaking not yet performed
   2426         wrapWithSSLSession(new SSLSessionWrappedTask() {
   2427             @Override
   2428             public void run(long sslSession) throws Exception {
   2429                 try {
   2430                     NativeCrypto.SSL_shutdown(sslSession, INVALID_FD, DUMMY_CB);
   2431                     fail();
   2432                 } catch (SocketException expected) {
   2433                 }
   2434             }
   2435         });
   2436 
   2437         // positively tested elsewhere because handshake uses use
   2438         // SSL_shutdown to ensure SSL_SESSIONs are reused.
   2439     }
   2440 
   2441     public void test_SSL_free() throws Exception {
   2442         try {
   2443             NativeCrypto.SSL_free(NULL);
   2444             fail();
   2445         } catch (NullPointerException expected) {
   2446         }
   2447 
   2448         long c = NativeCrypto.SSL_CTX_new();
   2449         NativeCrypto.SSL_free(NativeCrypto.SSL_new(c));
   2450         NativeCrypto.SSL_CTX_free(c);
   2451 
   2452         // additional positive testing elsewhere because handshake
   2453         // uses use SSL_free to cleanup in afterHandshake.
   2454     }
   2455 
   2456     public void test_SSL_SESSION_session_id() throws Exception {
   2457         try {
   2458             NativeCrypto.SSL_SESSION_session_id(NULL);
   2459             fail();
   2460         } catch (NullPointerException expected) {
   2461         }
   2462 
   2463         final ServerSocket listener = new ServerSocket(0);
   2464 
   2465         Hooks cHooks = new Hooks() {
   2466             @Override
   2467             public void afterHandshake(long session, long s, long c,
   2468                                        Socket sock, FileDescriptor fd,
   2469                                        SSLHandshakeCallbacks callback)
   2470                     throws Exception {
   2471                 byte[] id = NativeCrypto.SSL_SESSION_session_id(session);
   2472                 assertNotNull(id);
   2473                 assertEquals(32, id.length);
   2474                 super.afterHandshake(session, s, c, sock, fd, callback);
   2475             }
   2476         };
   2477         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2478         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2479         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2480         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2481         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2482     }
   2483 
   2484     public void test_SSL_SESSION_get_time() throws Exception {
   2485         try {
   2486             NativeCrypto.SSL_SESSION_get_time(NULL);
   2487             fail();
   2488         } catch (NullPointerException expected) {
   2489         }
   2490 
   2491         final ServerSocket listener = new ServerSocket(0);
   2492 
   2493         {
   2494             Hooks cHooks = new Hooks() {
   2495                 @Override
   2496                 public void afterHandshake(long session, long s, long c,
   2497                                            Socket sock, FileDescriptor fd,
   2498                                            SSLHandshakeCallbacks callback)
   2499                         throws Exception {
   2500                     long time = NativeCrypto.SSL_SESSION_get_time(session);
   2501                     assertTrue(time != 0);
   2502                     assertTrue(time < System.currentTimeMillis());
   2503                     super.afterHandshake(session, s, c, sock, fd, callback);
   2504                 }
   2505             };
   2506             Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2507             Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
   2508                     null);
   2509             Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
   2510                     null);
   2511             client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2512             server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2513         }
   2514     }
   2515 
   2516     public void test_SSL_SESSION_get_version() throws Exception {
   2517         try {
   2518             NativeCrypto.SSL_SESSION_get_version(NULL);
   2519             fail();
   2520         } catch (NullPointerException expected) {
   2521         }
   2522 
   2523         final ServerSocket listener = new ServerSocket(0);
   2524 
   2525         Hooks cHooks = new Hooks() {
   2526             @Override
   2527             public void afterHandshake(long session, long s, long c,
   2528                                        Socket sock, FileDescriptor fd,
   2529                                        SSLHandshakeCallbacks callback)
   2530                     throws Exception {
   2531                 String v = NativeCrypto.SSL_SESSION_get_version(session);
   2532                 assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v));
   2533                 super.afterHandshake(session, s, c, sock, fd, callback);
   2534             }
   2535         };
   2536         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2537         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2538         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2539         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2540         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2541     }
   2542 
   2543     public void test_SSL_SESSION_cipher() throws Exception {
   2544         try {
   2545             NativeCrypto.SSL_SESSION_cipher(NULL);
   2546             fail();
   2547         } catch (NullPointerException expected) {
   2548         }
   2549 
   2550         final ServerSocket listener = new ServerSocket(0);
   2551 
   2552         Hooks cHooks = new Hooks() {
   2553             @Override
   2554             public void afterHandshake(long session, long s, long c,
   2555                                        Socket sock, FileDescriptor fd,
   2556                                        SSLHandshakeCallbacks callback)
   2557                         throws Exception {
   2558                 String a = NativeCrypto.SSL_SESSION_cipher(session);
   2559                 assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a));
   2560                 super.afterHandshake(session, s, c, sock, fd, callback);
   2561             }
   2562         };
   2563         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2564         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2565         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2566         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2567         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2568     }
   2569 
   2570     public void test_SSL_SESSION_free() throws Exception {
   2571         try {
   2572             NativeCrypto.SSL_SESSION_free(NULL);
   2573             fail();
   2574         } catch (NullPointerException expected) {
   2575         }
   2576 
   2577         // additional positive testing elsewhere because handshake
   2578         // uses use SSL_SESSION_free to cleanup in afterHandshake.
   2579     }
   2580 
   2581     public void test_i2d_SSL_SESSION() throws Exception {
   2582         try {
   2583             NativeCrypto.i2d_SSL_SESSION(NULL);
   2584             fail();
   2585         } catch (NullPointerException expected) {
   2586         }
   2587 
   2588         final ServerSocket listener = new ServerSocket(0);
   2589 
   2590         Hooks cHooks = new Hooks() {
   2591             @Override
   2592             public void afterHandshake(long session, long s, long c,
   2593                                        Socket sock, FileDescriptor fd,
   2594                                        SSLHandshakeCallbacks callback)
   2595                     throws Exception {
   2596                 byte[] b = NativeCrypto.i2d_SSL_SESSION(session);
   2597                 assertNotNull(b);
   2598                 long session2 = NativeCrypto.d2i_SSL_SESSION(b);
   2599                 assertTrue(session2 != NULL);
   2600 
   2601                 // Make sure d2i_SSL_SESSION retores SSL_SESSION_cipher value http://b/7091840
   2602                 assertTrue(NativeCrypto.SSL_SESSION_cipher(session2) != null);
   2603                 assertEquals(NativeCrypto.SSL_SESSION_cipher(session),
   2604                              NativeCrypto.SSL_SESSION_cipher(session2));
   2605 
   2606                 NativeCrypto.SSL_SESSION_free(session2);
   2607                 super.afterHandshake(session, s, c, sock, fd, callback);
   2608             }
   2609         };
   2610         Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
   2611         Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
   2612         Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
   2613         client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2614         server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
   2615     }
   2616 
   2617     public void test_d2i_SSL_SESSION() throws Exception {
   2618         try {
   2619             NativeCrypto.d2i_SSL_SESSION(null);
   2620             fail();
   2621         } catch (NullPointerException expected) {
   2622         }
   2623 
   2624         try {
   2625             NativeCrypto.d2i_SSL_SESSION(new byte[0]);
   2626             fail("Should throw IOException with invalid SSL_SESSION data");
   2627         } catch (IOException expected) {
   2628         }
   2629 
   2630         try {
   2631             NativeCrypto.d2i_SSL_SESSION(new byte[1]);
   2632             fail("Should throw IOException with invalid SSL_SESSION data");
   2633         } catch (IOException expected) {
   2634         }
   2635 
   2636         // positive testing by test_i2d_SSL_SESSION
   2637     }
   2638 
   2639     public void test_X509_NAME_hashes() {
   2640         // ensure these hash functions are stable over time since the
   2641         // /system/etc/security/cacerts CA filenames have to be
   2642         // consistent with the output.
   2643         X500Principal name = new X500Principal("CN=localhost");
   2644         assertEquals(-1372642656, NativeCrypto.X509_NAME_hash(name)); // SHA1
   2645         assertEquals(-1626170662, NativeCrypto.X509_NAME_hash_old(name)); // MD5
   2646     }
   2647 
   2648     public void test_RAND_bytes_Success() throws Exception {
   2649         byte[] output = new byte[128];
   2650         NativeCrypto.RAND_bytes(output);
   2651 
   2652         boolean isZero = true;
   2653         for (int i = 0; i < output.length; i++) {
   2654             isZero &= (output[i] == 0);
   2655         }
   2656 
   2657         assertFalse("Random output was zero. This is a very low probability event (1 in 2^128) "
   2658                 + "and probably indicates an error.", isZero);
   2659     }
   2660 
   2661     public void test_RAND_bytes_Null_Failure() throws Exception {
   2662         byte[] output = null;
   2663         try {
   2664             NativeCrypto.RAND_bytes(output);
   2665             fail("Should be an error on null buffer input");
   2666         } catch (RuntimeException expected) {
   2667         }
   2668     }
   2669 
   2670     public void test_EVP_get_digestbyname() throws Exception {
   2671         assertTrue(NativeCrypto.EVP_get_digestbyname("sha256") != NULL);
   2672 
   2673         try {
   2674             NativeCrypto.EVP_get_digestbyname(null);
   2675             fail();
   2676         } catch (NullPointerException expected) {
   2677         }
   2678 
   2679         try {
   2680             NativeCrypto.EVP_get_digestbyname("");
   2681             NativeCrypto.EVP_get_digestbyname("foobar");
   2682             fail();
   2683         } catch (RuntimeException expected) {
   2684         }
   2685     }
   2686 
   2687     public void test_EVP_DigestSignInit() throws Exception {
   2688         KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
   2689         kpg.initialize(512);
   2690 
   2691         KeyPair kp = kpg.generateKeyPair();
   2692         RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) kp.getPrivate();
   2693 
   2694         NativeRef.EVP_PKEY pkey;
   2695         pkey = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
   2696                 privKey.getModulus().toByteArray(),
   2697                 privKey.getPublicExponent().toByteArray(),
   2698                 privKey.getPrivateExponent().toByteArray(),
   2699                 privKey.getPrimeP().toByteArray(),
   2700                 privKey.getPrimeQ().toByteArray(),
   2701                 privKey.getPrimeExponentP().toByteArray(),
   2702                 privKey.getPrimeExponentQ().toByteArray(),
   2703                 privKey.getCrtCoefficient().toByteArray()));
   2704         assertNotNull(pkey);
   2705 
   2706         final NativeRef.EVP_MD_CTX ctx = new NativeRef.EVP_MD_CTX(NativeCrypto.EVP_MD_CTX_create());
   2707         long evpMd = NativeCrypto.EVP_get_digestbyname("sha256");
   2708         NativeCrypto.EVP_DigestSignInit(ctx, evpMd, pkey);
   2709 
   2710         try {
   2711             NativeCrypto.EVP_DigestSignInit(ctx, 0, pkey);
   2712             fail();
   2713         } catch (RuntimeException expected) {
   2714         }
   2715 
   2716         try {
   2717             NativeCrypto.EVP_DigestSignInit(ctx, evpMd, null);
   2718             fail();
   2719         } catch (RuntimeException expected) {
   2720         }
   2721     }
   2722 
   2723     public void test_get_RSA_private_params() throws Exception {
   2724         try {
   2725             NativeCrypto.get_RSA_private_params(null);
   2726         } catch (NullPointerException expected) {
   2727         }
   2728 
   2729         try {
   2730             NativeCrypto.get_RSA_private_params(null);
   2731         } catch (NullPointerException expected) {
   2732         }
   2733 
   2734         // Test getting params for the wrong kind of key.
   2735         final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
   2736         assertFalse(groupCtx == NULL);
   2737         NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupCtx);
   2738         NativeRef.EVP_PKEY ctx = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
   2739         try {
   2740             NativeCrypto.get_RSA_private_params(ctx);
   2741             fail();
   2742         } catch (RuntimeException expected) {
   2743         }
   2744     }
   2745 
   2746     public void test_get_RSA_public_params() throws Exception {
   2747         try {
   2748             NativeCrypto.get_RSA_public_params(null);
   2749         } catch (NullPointerException expected) {
   2750         }
   2751 
   2752         try {
   2753             NativeCrypto.get_RSA_public_params(null);
   2754         } catch (NullPointerException expected) {
   2755         }
   2756 
   2757         // Test getting params for the wrong kind of key.
   2758         final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
   2759         assertFalse(groupCtx == NULL);
   2760         NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupCtx);
   2761         NativeRef.EVP_PKEY ctx = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
   2762         try {
   2763             NativeCrypto.get_RSA_public_params(ctx);
   2764             fail();
   2765         } catch (RuntimeException expected) {
   2766         }
   2767     }
   2768 
   2769     public void test_RSA_size_null_key_Failure() throws Exception {
   2770         try {
   2771             NativeCrypto.RSA_size(null);
   2772             fail("Expecting null pointer exception for RSA_size with null key");
   2773         } catch (NullPointerException expected) {}
   2774     }
   2775 
   2776     public void test_RSA_private_encrypt_null_key_Failure() throws Exception {
   2777         try {
   2778             NativeCrypto.RSA_private_encrypt(0, new byte[0], new byte[0],
   2779                     null, 0);
   2780             fail("Expecting null pointer exception for RSA_private encrypt with null key");
   2781         } catch (NullPointerException expected) {}
   2782     }
   2783 
   2784     public void test_RSA_private_decrypt_null_key_Failure() throws Exception {
   2785         try {
   2786             NativeCrypto.RSA_private_decrypt(0, new byte[0], new byte[0],
   2787  null, 0);
   2788             fail("Expecting null pointer exception for RSA_private_decrypt with null key");
   2789         } catch (NullPointerException expected) {}
   2790     }
   2791 
   2792     public void test_RSA_public_encrypt_null_key_Failure() throws Exception {
   2793         try {
   2794             NativeCrypto.RSA_public_encrypt(0, new byte[0], new byte[0], null,
   2795                     0);
   2796             fail("Expecting null pointer exception for RSA_public encrypt with null key");
   2797         } catch (NullPointerException expected) {}
   2798     }
   2799 
   2800     public void test_RSA_public_decrypt_null_key_Failure() throws Exception {
   2801         try {
   2802             NativeCrypto.RSA_public_decrypt(0, new byte[0], new byte[0], null,
   2803                     0);
   2804             fail("Expecting null pointer exception for RSA_public decrypt with null key");
   2805         } catch (NullPointerException expected) {}
   2806     }
   2807 
   2808     /*
   2809      * Test vector generation:
   2810      * openssl rand -hex 16
   2811      */
   2812     private static final byte[] AES_128_KEY = new byte[] {
   2813             (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2,
   2814             (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29,
   2815             (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f,
   2816     };
   2817 
   2818     public void testEC_GROUP() throws Exception {
   2819         /* Test using NIST's P-256 curve */
   2820         check_EC_GROUP(NativeCrypto.EC_CURVE_GFP, "prime256v1",
   2821                 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
   2822                 "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
   2823                 "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
   2824                 "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
   2825                 "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
   2826                 "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
   2827                 1L);
   2828     }
   2829 
   2830     private void check_EC_GROUP(int type, String name, String pStr, String aStr, String bStr,
   2831             String xStr, String yStr, String nStr, long hLong) throws Exception {
   2832         long groupRef = NativeCrypto.EC_GROUP_new_by_curve_name(name);
   2833         assertFalse(groupRef == NULL);
   2834         NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupRef);
   2835         assertEquals(NativeCrypto.OBJ_txt2nid_longName(name),
   2836                 NativeCrypto.EC_GROUP_get_curve_name(group));
   2837         assertEquals(type, NativeCrypto.get_EC_GROUP_type(group));
   2838 
   2839         // prime
   2840         BigInteger p = new BigInteger(pStr, 16);
   2841         // first coefficient
   2842         BigInteger a = new BigInteger(aStr, 16);
   2843         // second coefficient
   2844         BigInteger b = new BigInteger(bStr, 16);
   2845         // x affine coordinate of generator
   2846         BigInteger x = new BigInteger(xStr, 16);
   2847         // y affine coordinate of generator
   2848         BigInteger y = new BigInteger(yStr, 16);
   2849         // order of the generator
   2850         BigInteger n = new BigInteger(nStr, 16);
   2851         // cofactor of generator
   2852         BigInteger h = BigInteger.valueOf(hLong);
   2853 
   2854         byte[][] pab = NativeCrypto.EC_GROUP_get_curve(group);
   2855         assertEquals(3, pab.length);
   2856 
   2857         BigInteger p2 = new BigInteger(pab[0]);
   2858         assertEquals(p, p2);
   2859 
   2860         BigInteger a2 = new BigInteger(pab[1]);
   2861         assertEquals(a, a2);
   2862 
   2863         BigInteger b2 = new BigInteger(pab[2]);
   2864         assertEquals(b, b2);
   2865 
   2866         NativeRef.EC_POINT point = new NativeRef.EC_POINT(
   2867                 NativeCrypto.EC_GROUP_get_generator(group));
   2868 
   2869         byte[][] xy = NativeCrypto.EC_POINT_get_affine_coordinates(group, point);
   2870         assertEquals(2, xy.length);
   2871 
   2872         BigInteger x2 = new BigInteger(xy[0]);
   2873         assertEquals(x, x2);
   2874 
   2875         BigInteger y2 = new BigInteger(xy[1]);
   2876         assertEquals(y, y2);
   2877 
   2878         BigInteger n2 = new BigInteger(NativeCrypto.EC_GROUP_get_order(group));
   2879         assertEquals(n, n2);
   2880 
   2881         BigInteger h2 = new BigInteger(NativeCrypto.EC_GROUP_get_cofactor(group));
   2882         assertEquals(h, h2);
   2883 
   2884         NativeRef.EVP_PKEY key1 = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
   2885         NativeRef.EC_GROUP groupTmp = new NativeRef.EC_GROUP(NativeCrypto.EC_KEY_get1_group(key1));
   2886         assertEquals(NativeCrypto.EC_GROUP_get_curve_name(group),
   2887                 NativeCrypto.EC_GROUP_get_curve_name(groupTmp));
   2888     }
   2889 
   2890     public void test_EC_KEY_get_private_key_null_key_Failure() throws Exception {
   2891         try {
   2892             NativeCrypto.EC_KEY_get_private_key(null);
   2893             fail();
   2894         } catch (NullPointerException expected) {}
   2895     }
   2896 
   2897     public void test_EC_KEY_get_public_key_null_key_Failure() throws Exception {
   2898         try {
   2899             NativeCrypto.EC_KEY_get_public_key(null);
   2900             fail();
   2901         } catch (NullPointerException expected) {}
   2902     }
   2903 
   2904     public void test_ECKeyPairGenerator_CurvesAreValid() throws Exception {
   2905         OpenSSLECKeyPairGenerator.assertCurvesAreValid();
   2906     }
   2907 
   2908     public void test_ECDH_compute_key_null_key_Failure() throws Exception {
   2909         final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
   2910         assertFalse(groupCtx == NULL);
   2911         NativeRef.EC_GROUP groupRef = new NativeRef.EC_GROUP(groupCtx);
   2912         NativeRef.EVP_PKEY pkey1Ref = new NativeRef.EVP_PKEY(
   2913                 NativeCrypto.EC_KEY_generate_key(groupRef));
   2914         NativeRef.EVP_PKEY pkey2Ref = new NativeRef.EVP_PKEY(
   2915                 NativeCrypto.EC_KEY_generate_key(groupRef));
   2916 
   2917         byte[] out = new byte[128];
   2918         int outOffset = 0;
   2919         // Assert that the method under test works fine with the two
   2920         // non-null keys
   2921         NativeCrypto.ECDH_compute_key(out, outOffset, pkey1Ref, pkey2Ref);
   2922 
   2923         // Assert that it fails when only the first key is null
   2924         try {
   2925             NativeCrypto.ECDH_compute_key(out, outOffset, null, pkey2Ref);
   2926             fail();
   2927         } catch (NullPointerException expected) {
   2928         }
   2929 
   2930         // Assert that it fails when only the second key is null
   2931         try {
   2932             NativeCrypto.ECDH_compute_key(out, outOffset, pkey1Ref, null);
   2933             fail();
   2934         } catch (NullPointerException expected) {
   2935         }
   2936     }
   2937 
   2938     public void test_EVP_CipherInit_ex_Null_Failure() throws Exception {
   2939         final NativeRef.EVP_CIPHER_CTX ctx = new NativeRef.EVP_CIPHER_CTX(
   2940                 NativeCrypto.EVP_CIPHER_CTX_new());
   2941         final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
   2942 
   2943         try {
   2944             NativeCrypto.EVP_CipherInit_ex(null, evpCipher, null, null, true);
   2945             fail("Null context should throw NullPointerException");
   2946         } catch (NullPointerException expected) {
   2947         }
   2948 
   2949         /* Initialize encrypting. */
   2950         NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, true);
   2951         NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, true);
   2952 
   2953         /* Initialize decrypting. */
   2954         NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, false);
   2955         NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, false);
   2956     }
   2957 
   2958     public void test_EVP_CipherInit_ex_Success() throws Exception {
   2959         final NativeRef.EVP_CIPHER_CTX ctx = new NativeRef.EVP_CIPHER_CTX(
   2960                 NativeCrypto.EVP_CIPHER_CTX_new());
   2961         final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
   2962         NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, AES_128_KEY, null, true);
   2963     }
   2964 
   2965     public void test_EVP_CIPHER_iv_length() throws Exception {
   2966         long aes128ecb = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
   2967         assertEquals(0, NativeCrypto.EVP_CIPHER_iv_length(aes128ecb));
   2968 
   2969         long aes128cbc = NativeCrypto.EVP_get_cipherbyname("aes-128-cbc");
   2970         assertEquals(16, NativeCrypto.EVP_CIPHER_iv_length(aes128cbc));
   2971     }
   2972 
   2973     public void test_OpenSSLKey_toJava() throws Exception {
   2974         OpenSSLKey key1;
   2975 
   2976         BigInteger e = BigInteger.valueOf(65537);
   2977         key1 = new OpenSSLKey(NativeCrypto.RSA_generate_key_ex(1024, e.toByteArray()));
   2978         assertTrue(key1.getPublicKey() instanceof RSAPublicKey);
   2979 
   2980         final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
   2981         assertFalse(groupCtx == NULL);
   2982         NativeRef.EC_GROUP group1 = new NativeRef.EC_GROUP(groupCtx);
   2983         key1 = new OpenSSLKey(NativeCrypto.EC_KEY_generate_key(group1));
   2984         assertTrue(key1.getPublicKey() instanceof ECPublicKey);
   2985     }
   2986 
   2987     public void test_create_BIO_InputStream() throws Exception {
   2988         byte[] actual = "Test".getBytes();
   2989         ByteArrayInputStream is = new ByteArrayInputStream(actual);
   2990 
   2991         @SuppressWarnings("resource")
   2992         OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
   2993         try {
   2994             byte[] buffer = new byte[1024];
   2995             int numRead = NativeCrypto.BIO_read(bis.getBioContext(), buffer);
   2996             assertEquals(actual.length, numRead);
   2997             assertEquals(Arrays.toString(actual),
   2998                     Arrays.toString(Arrays.copyOfRange(buffer, 0, numRead)));
   2999         } finally {
   3000             bis.release();
   3001         }
   3002     }
   3003 
   3004     public void test_create_BIO_OutputStream() throws Exception {
   3005         byte[] actual = "Test".getBytes();
   3006         ByteArrayOutputStream os = new ByteArrayOutputStream();
   3007 
   3008         long ctx = NativeCrypto.create_BIO_OutputStream(os);
   3009         try {
   3010             NativeCrypto.BIO_write(ctx, actual, 0, actual.length);
   3011             assertEquals(actual.length, os.size());
   3012             assertEquals(Arrays.toString(actual), Arrays.toString(os.toByteArray()));
   3013         } finally {
   3014             NativeCrypto.BIO_free_all(ctx);
   3015         }
   3016     }
   3017 
   3018     public void test_get_ocsp_single_extension() throws Exception {
   3019         // This is only implemented for BoringSSL
   3020         if (!NativeCrypto.isBoringSSL) {
   3021             return;
   3022         }
   3023 
   3024         final String OCSP_SCT_LIST_OID = "1.3.6.1.4.1.11129.2.4.5";
   3025 
   3026         byte[] ocspResponse = readTestFile("ocsp-response.der");
   3027         byte[] expected = readTestFile("ocsp-response-sct-extension.der");
   3028         OpenSSLX509Certificate certificate = OpenSSLX509Certificate.fromX509PemInputStream(
   3029                                                 openTestFile("cert-ct-poisoned.pem"));
   3030         OpenSSLX509Certificate issuer = OpenSSLX509Certificate.fromX509PemInputStream(
   3031                                                 openTestFile("ca-cert.pem"));
   3032 
   3033         byte[] extension = NativeCrypto.get_ocsp_single_extension(ocspResponse, OCSP_SCT_LIST_OID,
   3034                                                                   certificate.getContext(),
   3035                                                                   issuer.getContext());
   3036 
   3037         assertEqualByteArrays(expected, extension);
   3038     }
   3039 
   3040     private static void assertContains(String actualValue, String expectedSubstring) {
   3041         if (actualValue == null) {
   3042             return;
   3043         }
   3044         if (actualValue.contains(expectedSubstring)) {
   3045             return;
   3046         }
   3047         fail("\"" + actualValue + "\" does not contain \"" + expectedSubstring + "\"");
   3048     }
   3049 }
   3050