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