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