NativeCryptoTest.java revision f087968310bb5233b76ad42841eb07e3c327f40f
1860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root/*
2860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Copyright (C) 2010 The Android Open Source Project
3860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
4860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * you may not use this file except in compliance with the License.
6860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * You may obtain a copy of the License at
7860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
8860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root *
10860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * Unless required by applicable law or agreed to in writing, software
11860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * See the License for the specific language governing permissions and
14860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root * limitations under the License.
15860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root */
16860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
17860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpackage org.conscrypt;
18860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
19860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport dalvik.system.BaseDexClassLoader;
20860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.ByteArrayInputStream;
21860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.ByteArrayOutputStream;
22860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.FileDescriptor;
23860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.IOException;
24860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.math.BigInteger;
25860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.ServerSocket;
26860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.Socket;
27860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.SocketTimeoutException;
28860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyPair;
29860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyPairGenerator;
30860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyStore;
31860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyStore.PrivateKeyEntry;
320e9746b7b132058651155b33f219c7789997985bKenny Rootimport java.security.cert.Certificate;
330e9746b7b132058651155b33f219c7789997985bKenny Rootimport java.security.cert.CertificateEncodingException;
34860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.CertificateException;
35860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.X509Certificate;
36860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.DSAPublicKey;
37860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.ECPublicKey;
38860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.RSAPrivateCrtKey;
39860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.RSAPublicKey;
40860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.spec.ECPrivateKeySpec;
41860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.ArrayList;
42860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.Arrays;
43860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.List;
44860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Callable;
45860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.ExecutionException;
46860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.ExecutorService;
47860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Executors;
48860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Future;
49860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.TimeUnit;
50860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.SSLException;
51860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.SSLProtocolException;
52860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.security.auth.x500.X500Principal;
53860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport junit.framework.TestCase;
54860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.io.IoUtils;
55860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.java.security.StandardNames;
56860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.java.security.TestKeyStore;
57860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport org.conscrypt.NativeCrypto.SSLHandshakeCallbacks;
58f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubinimport static org.conscrypt.NativeCrypto.SSL_MODE_CBC_RECORD_SPLITTING;
59860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport static org.conscrypt.NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH;
60860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
61860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpublic class NativeCryptoTest extends TestCase {
62860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /** Corresponds to the native test library "libjavacoretests.so" */
63860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static final String TEST_ENGINE_ID = "javacoretests";
64860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
65860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final long NULL = 0;
66860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final FileDescriptor INVALID_FD = new FileDescriptor();
67860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final SSLHandshakeCallbacks DUMMY_CB
68860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            = new TestSSLHandshakeCallbacks(null, 0, null);
69860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
70860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final long TIMEOUT_SECONDS = 5;
71860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
721ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey SERVER_PRIVATE_KEY;
730e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] SERVER_CERTIFICATES_HOLDER;
740e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] SERVER_CERTIFICATES;
751ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey CLIENT_PRIVATE_KEY;
760e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] CLIENT_CERTIFICATES_HOLDER;
770e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] CLIENT_CERTIFICATES;
78860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[][] CA_PRINCIPALS;
791ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey CHANNEL_ID_PRIVATE_KEY;
80860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[] CHANNEL_ID;
81860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
82860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    @Override
83860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    protected void tearDown() throws Exception {
84860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.ERR_peek_last_error());
85860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
86860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
871ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey getServerPrivateKey() {
88860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
89860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return SERVER_PRIVATE_KEY;
90860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
91860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
920e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getServerCertificates() {
93860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
94860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return SERVER_CERTIFICATES;
95860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
96860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
971ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey getClientPrivateKey() {
98860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
99860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CLIENT_PRIVATE_KEY;
100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1020e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getClientCertificates() {
103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CLIENT_CERTIFICATES;
105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[][] getCaPrincipals() {
108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CA_PRINCIPALS;
110860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
111860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Lazily create shared test certificates.
114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static synchronized void initCerts() {
116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (SERVER_PRIVATE_KEY != null) {
117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return;
118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            PrivateKeyEntry serverPrivateKeyEntry
122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
1231ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            SERVER_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(serverPrivateKeyEntry.getPrivateKey());
1240e9746b7b132058651155b33f219c7789997985bKenny Root            SERVER_CERTIFICATES_HOLDER = encodeCertificateList(
125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    serverPrivateKeyEntry.getCertificateChain());
1260e9746b7b132058651155b33f219c7789997985bKenny Root            SERVER_CERTIFICATES = getCertificateReferences(SERVER_CERTIFICATES_HOLDER);
127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            PrivateKeyEntry clientPrivateKeyEntry
129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
1301ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            CLIENT_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(clientPrivateKeyEntry.getPrivateKey());
1310e9746b7b132058651155b33f219c7789997985bKenny Root            CLIENT_CERTIFICATES_HOLDER = encodeCertificateList(
132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    clientPrivateKeyEntry.getCertificateChain());
1330e9746b7b132058651155b33f219c7789997985bKenny Root            CLIENT_CERTIFICATES = getCertificateReferences(CLIENT_CERTIFICATES_HOLDER);
134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            KeyStore ks = TestKeyStore.getClient().keyStore;
136860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            String caCertAlias = ks.aliases().nextElement();
137860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            X509Certificate certificate = (X509Certificate) ks.getCertificate(caCertAlias);
138860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            X500Principal principal = certificate.getIssuerX500Principal();
139860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            CA_PRINCIPALS = new byte[][] { principal.getEncoded() };
140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            initChannelIdKey();
141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (Exception e) {
142860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            throw new RuntimeException(e);
143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1460e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getCertificateReferences(OpenSSLX509Certificate[] certs) {
1470e9746b7b132058651155b33f219c7789997985bKenny Root        final long[] certRefs = new long[certs.length];
1480e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < certs.length; i++) {
1490e9746b7b132058651155b33f219c7789997985bKenny Root            certRefs[i] = certs[i].getContext();
1500e9746b7b132058651155b33f219c7789997985bKenny Root        }
1510e9746b7b132058651155b33f219c7789997985bKenny Root        return certRefs;
1520e9746b7b132058651155b33f219c7789997985bKenny Root    }
1530e9746b7b132058651155b33f219c7789997985bKenny Root
1540e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] encodeCertificateList(Certificate[] chain)
1550e9746b7b132058651155b33f219c7789997985bKenny Root            throws CertificateEncodingException {
1560e9746b7b132058651155b33f219c7789997985bKenny Root        final OpenSSLX509Certificate[] openSslCerts = new OpenSSLX509Certificate[chain.length];
1570e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < chain.length; i++) {
1580e9746b7b132058651155b33f219c7789997985bKenny Root            openSslCerts[i] = OpenSSLX509Certificate.fromCertificate(chain[i]);
1590e9746b7b132058651155b33f219c7789997985bKenny Root        }
1600e9746b7b132058651155b33f219c7789997985bKenny Root        return openSslCerts;
1610e9746b7b132058651155b33f219c7789997985bKenny Root    }
1620e9746b7b132058651155b33f219c7789997985bKenny Root
163860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static synchronized void initChannelIdKey() throws Exception {
164860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (CHANNEL_ID_PRIVATE_KEY != null) {
165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return;
166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NIST P-256 aka SECG secp256r1 aka X9.62 prime256v1
169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        OpenSSLECGroupContext openSslSpec = OpenSSLECGroupContext.getCurveByName("prime256v1");
170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        BigInteger s = new BigInteger(
171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "229cdbbf489aea584828a261a23f9ff8b0f66f7ccac98bf2096ab3aee41497c5", 16);
172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        CHANNEL_ID_PRIVATE_KEY = new OpenSSLECPrivateKey(
1731ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec())).getOpenSSLKey();
174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Channel ID is the concatenation of the X and Y coordinates of the public key.
176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        CHANNEL_ID = new BigInteger(
177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "702b07871fd7955c320b26f15e244e47eed60272124c92b9ebecf0b42f90069b" +
178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        "ab53592ebfeb4f167dbf3ce61513afb0e354c479b1c1b69874fa471293494f77",
179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                16).toByteArray();
180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualSessions(long expected, long actual) {
183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected),
184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                              NativeCrypto.SSL_SESSION_session_id(actual));
185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualByteArrays(byte[] expected, byte[] actual) {
187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.toString(expected), Arrays.toString(actual));
188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualPrincipals(byte[][] expected, byte[][] actual) {
191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(expected, actual);
192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1930e9746b7b132058651155b33f219c7789997985bKenny Root
1940e9746b7b132058651155b33f219c7789997985bKenny Root    public static void assertEqualCertificateChains(long[] expected, long[] actual) {
1950e9746b7b132058651155b33f219c7789997985bKenny Root        assertEquals(expected.length, actual.length);
1960e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < expected.length; i++) {
1970e9746b7b132058651155b33f219c7789997985bKenny Root            NativeCrypto.X509_cmp(expected[i], actual[i]);
1980e9746b7b132058651155b33f219c7789997985bKenny Root        }
199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2000e9746b7b132058651155b33f219c7789997985bKenny Root
201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualByteArrays(byte[][] expected, byte[][] actual) {
202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual));
203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_PKEY_cmp() throws Exception {
206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_PKEY_cmp(NULL, NULL);
208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Should throw NullPointerException when arguments are NULL");
209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
212860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        kpg.initialize(512);
214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPair kp1 = kpg.generateKeyPair();
216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        RSAPrivateCrtKey privKey1 = (RSAPrivateCrtKey) kp1.getPrivate();
217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPair kp2 = kpg.generateKeyPair();
219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        RSAPrivateCrtKey privKey2 = (RSAPrivateCrtKey) kp2.getPrivate();
220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long pkey1 = 0, pkey1_copy = 0, pkey2 = 0;
222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            pkey1 = NativeCrypto.EVP_PKEY_new_RSA(privKey1.getModulus().toByteArray(),
224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPublicExponent().toByteArray(),
225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPrivateExponent().toByteArray(),
226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPrimeP().toByteArray(),
227860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPrimeQ().toByteArray(),
228860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPrimeExponentP().toByteArray(),
229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getPrimeExponentQ().toByteArray(),
230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        privKey1.getCrtCoefficient().toByteArray());
231860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNotSame(NULL, pkey1);
232860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
233860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            pkey1_copy = NativeCrypto.EVP_PKEY_new_RSA(privKey1.getModulus().toByteArray(),
234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPublicExponent().toByteArray(),
235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPrivateExponent().toByteArray(),
236860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPrimeP().toByteArray(),
237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPrimeQ().toByteArray(),
238860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPrimeExponentP().toByteArray(),
239860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getPrimeExponentQ().toByteArray(),
240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey1.getCrtCoefficient().toByteArray());
241860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNotSame(NULL, pkey1_copy);
242860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
243860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            pkey2 = NativeCrypto.EVP_PKEY_new_RSA(privKey2.getModulus().toByteArray(),
244860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPublicExponent().toByteArray(),
245860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPrivateExponent().toByteArray(),
246860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPrimeP().toByteArray(),
247860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPrimeQ().toByteArray(),
248860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPrimeExponentP().toByteArray(),
249860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getPrimeExponentQ().toByteArray(),
250860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    privKey2.getCrtCoefficient().toByteArray());
251860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNotSame(NULL, pkey2);
252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
253860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
254860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_cmp(pkey1, NULL);
255860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail("Should throw NullPointerException when arguments are NULL");
256860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
257860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
258860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
259860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
260860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_cmp(NULL, pkey1);
261860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail("Should throw NullPointerException when arguments are NULL");
262860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
263860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
264860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
265860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals("Same keys should be the equal", 1,
266860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1));
267860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
268860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals("Same keys should be the equal", 1,
269860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1_copy));
270860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
271860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals("Different keys should not be equal", 0,
272860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_cmp(pkey1, pkey2));
273860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
274860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (pkey1 != 0) {
275860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(pkey1);
276860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
277860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (pkey1_copy != 0) {
278860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(pkey1_copy);
279860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
280860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (pkey2 != 0) {
281860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(pkey2);
282860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
283860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
284860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
285860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
286860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_new() throws Exception {
287860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
288860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(c != NULL);
289860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c2 = NativeCrypto.SSL_CTX_new();
290860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(c != c2);
291860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
292860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c2);
293860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
294860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
295860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_free() throws Exception {
296860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
297860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(NULL);
298860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
299860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
300860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
301860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
302860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(NativeCrypto.SSL_CTX_new());
303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
304860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
305860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_set_session_id_context() throws Exception {
306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] empty = new byte[0];
307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
308860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(NULL, empty);
309860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
310860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
311860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
312860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
313860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
314860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(c, null);
315860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
316860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
317860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_set_session_id_context(c, empty);
319860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[32]);
320860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
321860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[33]);
322860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (IllegalArgumentException expected) {
323860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
324860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
325860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
326860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
327860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_new() throws Exception {
328860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
329860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
330860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
331860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(s != NULL);
332860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & 0x01000000L) != 0); // SSL_OP_NO_SSLv2
333860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
334860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1) == 0);
335860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1_1) == 0);
336860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1_2) == 0);
337860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
338860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s2 = NativeCrypto.SSL_new(c);
339860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(s != s2);
340860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s2);
341860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
342860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
343860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
344860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
345860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
346860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_certificate() throws Exception {
347860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
348860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_use_certificate(NULL, null);
349860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
350860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
351860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
352860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
353860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
354860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
356860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
357860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_use_certificate(s, null);
358860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
359860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
360860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
361860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
362860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
363860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
364860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
365860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
366860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
367860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
368860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
36997d151b258d226b3afc1b3588171b283ec3f8046Kenny Root        initChannelIdKey();
37097d151b258d226b3afc1b3588171b283ec3f8046Kenny Root
371860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
3721ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            NativeCrypto.SSL_set1_tls_channel_id(NULL, NULL);
373860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
374860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
375860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
376860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
377860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
378860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
379860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
380860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
3811ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            NativeCrypto.SSL_set1_tls_channel_id(s, NULL);
382860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
383860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
384860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
385860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
386860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Use the key natively. This works because the initChannelIdKey method ensures that the
387860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // key is backed by OpenSSL.
3881ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY.getPkeyContext());
389860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
390860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
391860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
392860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
393860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
394860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_PrivateKey() throws Exception {
395860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
3961ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            NativeCrypto.SSL_use_PrivateKey(NULL, NULL);
397860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
398860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
399860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
400860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
401860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
402860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
403860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
404860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
4051ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            NativeCrypto.SSL_use_PrivateKey(s, NULL);
406860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
407860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
408860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
409860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
4101ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
411860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
412860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
413860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
414860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
415860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
416860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_null() throws Exception {
417860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
418860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(NULL);
419860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
420860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
421860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
422860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
423860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
424860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_no_key_no_cert() throws Exception {
425860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
426860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
427860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
428860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // neither private or certificate set
429860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
430860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
431860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
432860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
433860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
434860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
435860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
436860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
437860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
438860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
439860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_cert_then_key() throws Exception {
440860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
441860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
442860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
443860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // first certificate, then private
444860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
445860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
446860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
447860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
448860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
449860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
450860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
451860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
4521ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
453860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_check_private_key(s);
454860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
455860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
456860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
457860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
458860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_key_then_cert() throws Exception {
459860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
460860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
461860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
462860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // first private, then certificate
4631ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getPkeyContext());
464860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
465860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
466860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
467860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
468860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
469860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
470860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
471860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
472860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_check_private_key(s);
473860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
474860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
475860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
476860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
477860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
478860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_mode() throws Exception {
479860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
480860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_mode(NULL);
481860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
482860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
483860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
484860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
485860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
486860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
487860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.SSL_get_mode(s) != 0);
488860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
489860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
490860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
491860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
492860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_mode_and_clear_mode() throws Exception {
493860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
494860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_mode(NULL, 0);
495860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
496860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
497860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
498860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
499860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
500860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
501860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // check SSL_MODE_HANDSHAKE_CUTTHROUGH off by default
502860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
503f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin        // check SSL_MODE_CBC_RECORD_SPLITTING off by default
504f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin        assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_CBC_RECORD_SPLITTING);
505f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin
506860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // set SSL_MODE_HANDSHAKE_CUTTHROUGH on
507860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
508860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_mode(s)
509860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                & SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0);
510860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off
511860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
512860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_mode(s)
513860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    & SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0);
514860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
515860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
516860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
517860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
518860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
519860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_options() throws Exception {
520860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
521860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_options(NULL);
522860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
523860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
524860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
525860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
526860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
527860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
528860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.SSL_get_options(s) != 0);
529860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
530860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
531860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
532860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_options() throws Exception {
534860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
535860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_options(NULL, 0);
536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
537860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
538860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
539860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0);
545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_clear_options() throws Exception {
550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_clear_options(NULL, 0);
552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
553860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
554860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
555860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
556860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
557860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0);
561860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_SSLv3);
562860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0);
563860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
565860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
566860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_cipher_lists() throws Exception {
568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(NULL, null);
570860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
571860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
574860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
578860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(s, null);
579860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
580860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_cipher_lists(s, new String[] {});
584860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
585860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
586860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(s, new String[] { null });
587860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
589860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
590860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
591860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // see OpenSSL ciphers man page
592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        String[] illegals = new String[] {
593860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // empty
594860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "",
595860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // never standardized
596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "EXP1024-DES-CBC-SHA", "EXP1024-RC4-SHA", "DHE-DSS-RC4-SHA",
597860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // IDEA
598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "IDEA-CBC-SHA", "IDEA-CBC-MD5"
599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
600860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
601860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        for (String illegal : illegals) {
602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_cipher_lists(s, new String[] { illegal });
604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail(illegal);
605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (IllegalArgumentException expected) {
606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
607860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
608860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
609860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        List<String> ciphers
610860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                = new ArrayList<String>(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.keySet());
611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_cipher_lists(s, ciphers.toArray(new String[ciphers.size()]));
612860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
613860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
614860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_verify() throws Exception {
618860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
619860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_verify(NULL, 0);
620860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
621860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
622860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
623860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
624860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
625860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
626860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
627860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
628860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
629860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, (NativeCrypto.SSL_VERIFY_PEER
630860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                        | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT));
631860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
632860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
633860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
634860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
635860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final boolean DEBUG = false;
636860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
637860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class Hooks {
6381ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        private OpenSSLKey channelIdPrivateKey;
639860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
640860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long getContext() throws SSLException {
641860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return NativeCrypto.SSL_CTX_new();
642860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
643860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long beforeHandshake(long context) throws SSLException {
644860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(context);
645860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // without this SSL_set_cipher_lists call the tests were
646860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // negotiating DHE-RSA-AES256-SHA by default which had
647860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // very slow ephemeral RSA key generation
648860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(s, new String[] { "RC4-MD5" });
649860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
650860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (channelIdPrivateKey != null) {
6511ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey.getPkeyContext());
652860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
653860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return s;
654860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
655860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void clientCertificateRequested(long s) {}
656860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void afterHandshake(long session, long ssl, long context,
657860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   Socket socket, FileDescriptor fd,
658860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   SSLHandshakeCallbacks callback)
659860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
660860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (session != NULL) {
661860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_SESSION_free(session);
662860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
663860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (ssl != NULL) {
664860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
665860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_shutdown(ssl, fd, callback);
666860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } catch (IOException e) {
667860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
668860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_free(ssl);
669860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
670860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (context != NULL) {
671860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_free(context);
672860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
673860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (socket != null) {
674860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                socket.close();
675860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
676860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
677860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
678860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
679860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks {
680860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final Socket socket;
681860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final long sslNativePointer;
682860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final Hooks hooks;
683860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
684860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public TestSSLHandshakeCallbacks(Socket socket,
685860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                         long sslNativePointer,
686860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                         Hooks hooks) {
687860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.socket = socket;
688860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.sslNativePointer = sslNativePointer;
689860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.hooks = hooks;
690860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
691860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
6920e9746b7b132058651155b33f219c7789997985bKenny Root        public long[] certificateChainRefs;
693860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public String authMethod;
694860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean verifyCertificateChainCalled;
695860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
6960e9746b7b132058651155b33f219c7789997985bKenny Root        public void verifyCertificateChain(long[] certChainRefs, String authMethod)
697860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws CertificateException {
698860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
699860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
700860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " verifyCertificateChain"
701860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " asn1DerEncodedCertificateChain="
7020e9746b7b132058651155b33f219c7789997985bKenny Root                                   + Arrays.toString(certChainRefs)
703860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " authMethod=" + authMethod);
704860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
7050e9746b7b132058651155b33f219c7789997985bKenny Root            this.certificateChainRefs = certChainRefs;
706860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.authMethod = authMethod;
707860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.verifyCertificateChainCalled = true;
708860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
709860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
710860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public byte[] keyTypes;
711860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public byte[][] asn1DerEncodedX500Principals;
712860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean clientCertificateRequestedCalled;
713860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void clientCertificateRequested(byte[] keyTypes,
714860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               byte[][] asn1DerEncodedX500Principals) {
715860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
716860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
717860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " clientCertificateRequested"
718860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " keyTypes=" + keyTypes
719860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " asn1DerEncodedX500Principals="
720860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + asn1DerEncodedX500Principals);
721860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
722860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.keyTypes = keyTypes;
723860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.asn1DerEncodedX500Principals = asn1DerEncodedX500Principals;
724860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.clientCertificateRequestedCalled = true;
725860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (hooks != null ) {
726860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                hooks.clientCertificateRequested(sslNativePointer);
727860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
728860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
729860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
730860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean handshakeCompletedCalled;
731860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void handshakeCompleted() {
732860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
733860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
734860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " handshakeCompleted");
735860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
736860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.handshakeCompletedCalled = true;
737860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
738860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
739860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public Socket getSocket() {
740860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return socket;
741860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
742860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
743860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
744860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class ServerHooks extends Hooks {
7451ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        private final OpenSSLKey privateKey;
7460e9746b7b132058651155b33f219c7789997985bKenny Root        private final long[] certificates;
747860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private boolean channelIdEnabled;
748860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private byte[] channelIdAfterHandshake;
749860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private Throwable channelIdAfterHandshakeException;
750860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
7510e9746b7b132058651155b33f219c7789997985bKenny Root        public ServerHooks(OpenSSLKey privateKey, long[] certificates) {
752860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.privateKey = privateKey;
753860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.certificates = certificates;
754860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
755860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
756860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        @Override
757860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long beforeHandshake(long c) throws SSLException {
758860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = super.beforeHandshake(c);
759860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (privateKey != null) {
7601ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                NativeCrypto.SSL_use_PrivateKey(s, privateKey.getPkeyContext());
761860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
762860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (certificates != null) {
763860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_use_certificate(s, certificates);
764860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
765860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (channelIdEnabled) {
766860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_enable_tls_channel_id(s);
767860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
768860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return s;
769860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
770860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
771860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        @Override
772860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void afterHandshake(long session, long ssl, long context,
773860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   Socket socket, FileDescriptor fd,
774860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   SSLHandshakeCallbacks callback)
775860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
776860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          if (channelIdEnabled) {
777860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
778860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root              channelIdAfterHandshake = NativeCrypto.SSL_get_tls_channel_id(ssl);
779860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (Exception e) {
780860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root              channelIdAfterHandshakeException = e;
781860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
782860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          }
783860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          super.afterHandshake(session, ssl, context, socket, fd, callback);
784860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
785860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
786860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void clientCertificateRequested(long s) {
787860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Server asked for client certificates");
788860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
789860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
790860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
791860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
7926fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols,
7936fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            final byte[] alpnProtocols) {
794860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
795860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> future = executor.submit(
796860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                new Callable<TestSSLHandshakeCallbacks>() {
797860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public TestSSLHandshakeCallbacks call() throws Exception {
798860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Socket socket = (client
799860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 ? new Socket(listener.getInetAddress(),
800860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                              listener.getLocalPort())
801860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 : listener.accept());
802860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (timeout == -1) {
803860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return new TestSSLHandshakeCallbacks(socket, 0, null);
804860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
805860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                FileDescriptor fd = socket.getFileDescriptor$();
806860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long c = hooks.getContext();
807860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = hooks.beforeHandshake(c);
808860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                TestSSLHandshakeCallbacks callback
809860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        = new TestSSLHandshakeCallbacks(socket, s, hooks);
810860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (DEBUG) {
811860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    System.out.println("ssl=0x" + Long.toString(s, 16)
812860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " handshake"
813860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " context=0x" + Long.toString(c, 16)
814860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " socket=" + socket
815860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " fd=" + fd
816860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " timeout=" + timeout
817860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " client=" + client);
818860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
819860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long session = NULL;
820860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
821860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
8226fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                                                            npnProtocols, alpnProtocols);
823860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    if (DEBUG) {
824860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        System.out.println("ssl=0x" + Long.toString(s, 16)
825860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           + " handshake"
826860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           + " session=0x" + Long.toString(session, 16));
827860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
828860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } finally {
829860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    // Ensure afterHandshake is called to free resources
830860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    hooks.afterHandshake(session, s, c, socket, fd, callback);
831860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
832860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return callback;
833860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
834860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        });
835860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        executor.shutdown();
836860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return future;
837860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
838860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
839860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_NULL_SSL() throws Exception {
840860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
8416fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null, null);
842860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
843860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
844860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
845860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
846860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
847860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_null_args() throws Exception {
848860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
849860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
850860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
851860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
8526fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null, null);
853860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
854860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
855860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
856860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
857860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
8586fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null, null);
859860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
860860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
861860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
862860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
863860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
864860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
865860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
866860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
867860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_normal() throws Exception {
868860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal client and server case
869860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
870860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
871860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
8726fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
8736fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
874860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
875860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
876860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
877860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
8780e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
879860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
880860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
881860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
882860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
883860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
884860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
885860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
886860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
887860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_optional_client_certificate() throws Exception {
888860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // optional client certificate case
889860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
890860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
891860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
892860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
893860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void clientCertificateRequested(long s) {
894860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.clientCertificateRequested(s);
8951ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey().getPkeyContext());
896860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_use_certificate(s, getClientCertificates());
897860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
898860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
899860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
900860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
901860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long c) throws SSLException {
902860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(c);
903860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
904860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
905860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
906860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
907860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
9086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
9096fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
910860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
911860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
912860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
913860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
9140e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
915860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
916860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.verifyCertificateChainCalled);
917860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getClientCertificates(),
9180e9746b7b132058651155b33f219c7789997985bKenny Root                serverCallback.certificateChainRefs);
919860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", serverCallback.authMethod);
920860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
921860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.clientCertificateRequestedCalled);
922860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNotNull(clientCallback.keyTypes);
923860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // this depends on the SSL_set_cipher_lists call in beforeHandshake
924860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // the three returned are the non-ephemeral cases.
925860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(3, clientCallback.keyTypes.length);
926860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[0]));
927860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("DSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[1]));
928860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("EC", CipherSuite.getClientKeyType(clientCallback.keyTypes[2]));
929860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualPrincipals(getCaPrincipals(),
930860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                              clientCallback.asn1DerEncodedX500Principals);
931860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
932860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
933860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
934860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
935860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
936860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
937860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_missing_required_certificate() throws Exception {
938860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // required client certificate negative case
939860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
940860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
941860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
942860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
943860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
944860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
945860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
946860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
947860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_verify(s,
948860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                NativeCrypto.SSL_VERIFY_PEER
949860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
950860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
951860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
952860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
9536fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
9546fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
9556fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
9566fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
957860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
958860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
959860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
960860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
961860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
962860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
963860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
964860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
965860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Usually if a RuntimeException is thrown by the
966860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * clientCertificateRequestedCalled callback, the caller sees it
967860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * during the call to NativeCrypto_SSL_do_handshake.  However, IIS
968860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * does not request client certs until after the initial
969860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * handshake. It does an SSL renegotiation, which means we need to
970860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * be able to deliver the callback's exception in cases like
971860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * SSL_read, SSL_write, and SSL_shutdown.
972860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
973860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate()
974860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            throws Exception {
975860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
976860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
977860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
978860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
979860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long context) throws SSLException {
980860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(context);
981860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
982860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
983860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
984860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
985860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
986860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
987860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
988860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
989860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
990860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
991860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
992860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
993860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
994860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void clientCertificateRequested(long s) {
995860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.clientCertificateRequested(s);
996860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throw new RuntimeException("expected");
997860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
998860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
999860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1000860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1001860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1002860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1003860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1004860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1005860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
1006860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
1007860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_options(
1008860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            s, NativeCrypto.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
1009860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_renegotiate(s);
1010860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1,
1011860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           (int) ((TIMEOUT_SECONDS * 1000) / 2));
1012860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } catch (IOException expected) {
1013860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } finally {
1014860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1015860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1016860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1017860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
10186fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
10196fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1020860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1021860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1022860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException e) {
1023860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (!"expected".equals(e.getCause().getMessage())) {
1024860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throw e;
1025860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1026860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1027860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1028860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1029860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1030860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_client_timeout() throws Exception {
1031860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // client timeout
1032860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1033860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Socket serverSocket = null;
1034860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1035860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1036860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
10376fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null,
10386fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
10396fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null,
10406fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1041860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
1042860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1043860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1044860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1045860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (SocketTimeoutException.class != expected.getCause().getClass()) {
1046860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                expected.printStackTrace();
1047860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1048860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
1049860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
1050860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // Manually close peer socket when testing timeout
1051860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            IoUtils.closeQuietly(serverSocket);
1052860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1053860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1054860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1055860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_server_timeout() throws Exception {
1056860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // server timeout
1057860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1058860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Socket clientSocket = null;
1059860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1060860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1061860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
10626fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null, null);
10636fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null, null);
1064860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
1065860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1066860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1067860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1068860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
1069860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
1070860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // Manually close peer socket when testing timeout
1071860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            IoUtils.closeQuietly(clientSocket);
1072860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1073860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1074860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1075860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_normal() throws Exception {
1076860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1077860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1078860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Normal handshake with TLS Channel ID.
1079860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1080860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1081860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
1082860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1083860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = true;
10846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
10856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1086860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1087860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1088860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1089860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
10900e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1091860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
1092860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1093860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1094860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
1095860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1096860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1097860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1098860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(CHANNEL_ID, sHooks.channelIdAfterHandshake);
1099860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_not_supported_by_server() throws Exception {
1102860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Client tries to use TLS Channel ID but the server does not enable/offer the extension.
1105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
1108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = false;
11106fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
11116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
11160e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
1118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
1121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshake);
1125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_not_enabled_by_client() throws Exception {
1128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Client does not use TLS Channel ID when the server has the extension enabled/offered.
1131860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = null;
1134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = true;
11366fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
11376fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1138860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1139860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
11420e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
1144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
1147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshake);
1151860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1152860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1153860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_session() throws Exception {
1154860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1155860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session(NULL, NULL);
1156860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1157860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1158860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1159860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1160860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1161860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1162860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1163860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session(s, NULL);
1164860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long clientContext = NativeCrypto.SSL_CTX_new();
1170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long serverContext = NativeCrypto.SSL_CTX_new();
1171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final ServerSocket listener = new ServerSocket(0);
1172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long[] clientSession = new long[] { NULL };
1173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long[] serverSession = new long[] { NULL };
1174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            {
1175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks cHooks = new Hooks() {
1176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return clientContext;
1179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        clientSession[0] = session;
1187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return serverContext;
1193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1198860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1200860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        serverSession[0] = session;
1201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> client
12046fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, true, cHooks, null, null);
1205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> server
12066fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, false, sHooks, null, null);
1207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEqualSessions(clientSession[0], serverSession[0]);
1211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            {
1212860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks cHooks = new Hooks() {
1213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return clientContext;
1216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long beforeHandshake(long c) throws SSLException {
1219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        long s = NativeCrypto.SSL_new(clientContext);
1220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        NativeCrypto.SSL_set_session(s, clientSession[0]);
1221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return s;
1222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1227860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1228860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEqualSessions(clientSession[0], session);
1229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1231860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1232860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1233860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return serverContext;
1236860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1238860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1239860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1241860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1242860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEqualSessions(serverSession[0], session);
1243860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1244860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1245860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1246860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> client
12476fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, true, cHooks, null, null);
1248860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> server
12496fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, false, sHooks, null, null);
1250860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1251860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1253860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(clientSession[0]);
1254860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(serverSession[0]);
1255860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(serverContext);
1256860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(clientContext);
1257860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1258860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1259860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1260860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_session_creation_enabled() throws Exception {
1261860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1262860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(NULL, false);
1263860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1264860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1265860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1266860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1267860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1268860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1269860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1270860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(s, false);
1271860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(s, true);
1272860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1273860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1274860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1275860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1276860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1277860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1278860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // negative test case for SSL_set_session_creation_enabled(false) on client
1279860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1280860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
1281860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1282860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
1283860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
1284860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_session_creation_enabled(s, false);
1285860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
1286860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1287860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1288860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
12896fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
12906fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
12916fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
12926fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1293860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1294860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1295860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1296860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1297860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1298860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1299860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // negative test case for SSL_set_session_creation_enabled(false) on server
1300860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1301860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1302860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1304860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
1305860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
1306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_session_creation_enabled(s, false);
1307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
1308860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1309860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
13106fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
13116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
13126fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
13136fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1314860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1315860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1316860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1317860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1319860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1320860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1321860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_tlsext_host_name() throws Exception {
1322860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL SSL
1323860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1324860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_tlsext_host_name(NULL, null);
1325860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1326860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1327860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1328860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1329860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final String hostname = "www.android.com";
1330860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1331860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1332860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1333860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1334860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1335860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // null hostname
1336860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1337860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, null);
1338860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1339860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1340860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1341860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1342860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // too long hostname
1343860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1344860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                char[] longHostname = new char[256];
1345860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Arrays.fill(longHostname, 'w');
1346860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, new String(longHostname));
1347860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1348860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
1349860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1350860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1351860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNull(NativeCrypto.SSL_get_servername(s));
1352860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_tlsext_host_name(s, new String(hostname));
1353860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
1354860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1356860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1357860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1358860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1359860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1360860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1361860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal
1362860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1363860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1364860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long c) throws SSLException {
1365860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(c);
1366860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, hostname);
1367860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
1368860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1369860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1370860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1371860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1372860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1373860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1374860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1375860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1376860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
1377860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1378860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1379860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
13806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
13816fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1382860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1383860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1384860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1385860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1386860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_NpnNegotiateSuccess() throws Exception {
1387860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] clientNpnProtocols = new byte[] {
1388860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                8, 'h', 't', 't', 'p', '/', '1', '.', '1',
1389860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'f', 'o', 'o',
1390860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
1391860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1392860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] serverNpnProtocols = new byte[] {
1393860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
1394860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'f', 'o', 'o',
1395860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'b', 'a', 'r',
1396860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1397860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1398860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1399860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
1400860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_enable_npn(context);
1401860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return super.beforeHandshake(context);
1402860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1403860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
1404860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
1405860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
1406860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("spdy/2", new String(negotiated));
1407860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue("NPN should enable cutthrough on the client",
1408860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        0 != (NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH));
1409860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, ssl, context, socket, fd, callback);
1410860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1411860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1412860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1413860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
1414860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_enable_npn(context);
1415860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return super.beforeHandshake(context);
1416860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1417860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
1418860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
1419860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
1420860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("spdy/2", new String(negotiated));
1421860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("NPN should not enable cutthrough on the server",
1422860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
1423860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, ssl, c, sock, fd, callback);
1424860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1425860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1426860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1427860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerSocket listener = new ServerSocket(0);
1428860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> client
14296fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, true, cHooks, clientNpnProtocols, null);
1430860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> server
14316fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, false, sHooks, serverNpnProtocols, null);
14326fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
14336fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
14346fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    }
14356fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
14366fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public void test_SSL_AlpnNegotiateSuccess() throws Exception {
14376fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        final byte[] clientAlpnProtocols = new byte[] {
14386fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                8, 'h', 't', 't', 'p', '/', '1', '.', '1',
14396fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'f', 'o', 'o',
14406fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
14416fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
14426fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        final byte[] serverAlpnProtocols = new byte[] {
14436fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
14446fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'f', 'o', 'o',
14456fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'b', 'a', 'r',
14466fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
14476fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
14486fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Hooks cHooks = new Hooks() {
14496fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
14506fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                NativeCrypto.SSL_CTX_set_alpn_protos(context, clientAlpnProtocols);
14516fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                return super.beforeHandshake(context);
14526fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
14536fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
14546fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
14556fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
14566fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("spdy/2", new String(negotiated));
14576fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                /*
14586fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 * There is no callback on the client, so we can't enable
14596fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 * cut-through
14606fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 */
14616fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("ALPN should not enable cutthrough on the client", 0,
14626fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
14636fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                super.afterHandshake(session, ssl, context, socket, fd, callback);
14646fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
14656fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
14666fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
14676fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
14686fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
14696fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
14706fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("spdy/2", new String(negotiated));
14716fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("ALPN should not enable cutthrough on the server",
14726fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
14736fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                super.afterHandshake(session, ssl, c, sock, fd, callback);
14746fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
14756fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
14766fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
14776fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        ServerSocket listener = new ServerSocket(0);
14786fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client
14796fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, true, cHooks, null, null);
14806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server
14816fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, false, sHooks, null, serverAlpnProtocols);
1482860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1483860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1484860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1485860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1486860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_servername_null() throws Exception {
1487860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL SSL
1488860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1489860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_servername(NULL);
1490860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1491860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1492860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1493860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1494860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
1495860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
1496860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(NativeCrypto.SSL_get_servername(s));
1497860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
1498860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
1499860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1500860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing by test_SSL_set_tlsext_host_name
1501860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1502860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1503860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_renegotiate() throws Exception {
1504860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1505860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_renegotiate(NULL);
1506860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1507860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1508860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1509860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1510860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1511860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1512860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1513860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1514860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1515860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1516860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1517860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] buffer = new byte[1];
1518860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, buffer, 0, 1, 0);
1519860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(42, buffer[0]);
1520860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1521860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1522860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1523860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1524860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1525860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1526860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1527860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1528860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
1529860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_renegotiate(s);
1530860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1, 0);
1531860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1532860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
15346fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
15356fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1537860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1538860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1539860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_certificate() throws Exception {
1541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_certificate(NULL);
1543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1553860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
1554860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNull(NativeCrypto.SSL_get_certificate(s));
1555860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1556860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1557860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1561860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1562860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1563860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEqualCertificateChains(
1565860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                             getServerCertificates(),
1566860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                             NativeCrypto.SSL_get_certificate(s));
1567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
15706fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
15716fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1574860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_peer_cert_chain() throws Exception {
1577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1578860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_peer_cert_chain(NULL);
1579860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1580860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1584860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1585860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1586860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1587860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1589860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1590860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
15910e9746b7b132058651155b33f219c7789997985bKenny Root                long[] cc = NativeCrypto.SSL_get_peer_cert_chain(s);
1592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEqualCertificateChains(getServerCertificates(), cc);
15930e9746b7b132058651155b33f219c7789997985bKenny Root                for (long ref : cc) {
15940e9746b7b132058651155b33f219c7789997985bKenny Root                    NativeCrypto.X509_free(ref);
15950e9746b7b132058651155b33f219c7789997985bKenny Root                }
1596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1597860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
16006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
16016fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 };
1607860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1608860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_read() throws Exception {
1609860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1610860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL ssl
1611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1612860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0);
1613860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1614860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null FileDescriptor
1618860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1619860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1620860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1621860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1622860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0);
1623860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1624860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1625860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1626860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1627860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1628860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1629860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1630860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
1631860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1632860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1633860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1634860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1635860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0);
1636860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1637860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1638860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1639860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1640860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1641860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1642860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1643860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null byte array
1644860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1645860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1646860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1647860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1648860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0);
1649860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1650860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1651860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1652860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1653860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1654860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1655860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1656860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
1657860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1658860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1659860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1660860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1661860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
1662860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1663860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
1664860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1665860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1666860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1667860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1668860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1669860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1670860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1671860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal case
1672860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1673860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
1674860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1675860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
1676860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
1677860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
1678860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
1679860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    byte[] in = new byte[256];
1680860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertEquals(BYTES.length,
1681860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 NativeCrypto.SSL_read(s,
1682860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       fd,
1683860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       callback,
1684860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       in,
1685860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       0,
1686860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       BYTES.length,
1687860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       0));
1688860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    for (int i = 0; i < BYTES.length; i++) {
1689860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEquals(BYTES[i], in[i]);
1690860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1691860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1692860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1693860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1694860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1695860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1696860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
1697860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
1698860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
1699860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
1700860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length, 0);
1701860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1702860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1703860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
17046fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
17056fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
17066fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
17076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1708860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1709860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1710860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1711860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1712860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // timeout case
1713860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1714860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
1715860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1716860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
1717860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
1718860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
1719860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
1720860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1);
1721860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    fail();
1722860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1723860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1724860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1725860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1726860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
1727860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
1728860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
1729860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
1730860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
1731860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1732860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1733860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
17346fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
17356fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
17366fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
17376fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1738860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1739860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1740860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1741860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
1742860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1743860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1744860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1745860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_write() throws Exception {
1746860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1747860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_write(NULL, null, null, null, 0, 0, 0);
1748860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1749860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1750860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1751860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1752860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null FileDescriptor
1753860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1754860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1755860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1756860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1757860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1, 0);
1758860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1759860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1760860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1761860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1762860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1763860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1764860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1765860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
1766860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1767860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1768860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1769860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1770860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1, 0);
1771860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1772860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1773860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1774860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1775860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1776860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1777860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1778860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null byte array
1779860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1780860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1781860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1782860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1783860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1, 0);
1784860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1785860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1786860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1787860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1788860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1789860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1790860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1791860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
1792860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1793860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1794860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1795860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1796860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
1797860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1798860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
1799860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1800860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1801860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1802860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1803860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1804860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positively tested by test_SSL_read
1805860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1806860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1807860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_interrupt() throws Exception {
1808860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_interrupt is a rare case that tolerates a null SSL argument
1809860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_interrupt(NULL);
1810860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1811860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // also works without handshaking
1812860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1813860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1814860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1815860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_interrupt(s);
1816860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1817860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1818860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1819860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1820860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1821860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1822860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1823860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1824860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1825860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1826860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1827860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1828860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
1829860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1830860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1831860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1832860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1833860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1834860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, final long s, long c,
1835860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1836860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1837860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1838860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                new Thread() {
1839860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void run() {
1840860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        try {
1841860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            Thread.sleep(1*1000);
1842860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            NativeCrypto.SSL_interrupt(s);
1843860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        } catch (Exception e) {
1844860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        }
1845860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1846860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }.start();
1847860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(-1, NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0));
1848860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1849860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1850860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
18516fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
18526fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1853860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1854860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1855860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1856860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1857860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_shutdown() throws Exception {
1858860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1859860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null FileDescriptor
1860860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1861860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_shutdown(NULL, null, DUMMY_CB);
1862860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1863860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1864860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1865860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
1866860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1867860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_shutdown(NULL, INVALID_FD, null);
1868860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1869860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1870860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1871860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_shutdown is a rare case that tolerates a null SSL argument
1872860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB);
1873860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1874860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
1875860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
1876860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
1877860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1878860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_shutdown(s, INVALID_FD, DUMMY_CB);
1879860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLProtocolException expected) {
1880860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1881860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
1882860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
1883860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1884860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positively tested elsewhere because handshake uses use
1885860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_shutdown to ensure SSL_SESSIONs are reused.
1886860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1887860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1888860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_free() throws Exception {
1889860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1890860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(NULL);
1891860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1892860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1893860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1894860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1895860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
1896860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(NativeCrypto.SSL_new(c));
1897860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
1898860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1899860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing elsewhere because handshake
1900860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // uses use SSL_free to cleanup in afterHandshake.
1901860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1902860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1903860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_session_id() throws Exception {
1904860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1905860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_session_id(NULL);
1906860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1907860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1908860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1909860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1910860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1911860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1912860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1913860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1914860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1915860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1916860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1917860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1918860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] id = NativeCrypto.SSL_SESSION_session_id(session);
1919860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNotNull(id);
1920860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(32, id.length);
1921860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1922860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1923860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1924860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
19256fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
19266fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1927860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1928860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1929860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1930860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1931860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_get_time() throws Exception {
1932860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1933860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_get_time(NULL);
1934860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1935860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1936860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1937860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1938860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1939860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1940860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1941860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
1942860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1943860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
1944860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
1945860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
1946860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
1947860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long time = NativeCrypto.SSL_SESSION_get_time(session);
1948860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertTrue(time != 0);
1949860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertTrue(time < System.currentTimeMillis());
1950860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1951860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1952860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1953860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
19546fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
19556fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
19566fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
19576fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1958860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1959860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1960860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1961860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1962860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1963860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_get_version() throws Exception {
1964860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1965860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_get_version(NULL);
1966860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1967860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1968860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1969860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1970860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1971860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1972860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1973860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1974860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1975860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1976860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1977860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1978860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                String v = NativeCrypto.SSL_SESSION_get_version(session);
1979860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v));
1980860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1981860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1982860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1983860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
19846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
19856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1986860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1987860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1988860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1989860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1990860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_cipher() throws Exception {
1991860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1992860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_cipher(NULL);
1993860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1994860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1995860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1996860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1997860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1998860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1999860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2000860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2001860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2002860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2003860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2004860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2005860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                String a = NativeCrypto.SSL_SESSION_cipher(session);
2006860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a));
2007860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2008860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2009860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2010860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
20116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
20126fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2013860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2014860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2015860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2016860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2017860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_free() throws Exception {
2018860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2019860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(NULL);
2020860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2021860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2022860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2023860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2024860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing elsewhere because handshake
2025860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // uses use SSL_SESSION_free to cleanup in afterHandshake.
2026860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2027860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2028860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_i2d_SSL_SESSION() throws Exception {
2029860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2030860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.i2d_SSL_SESSION(NULL);
2031860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2032860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2033860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2034860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2035860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2036860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2037860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2038860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2039860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2040860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2041860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2042860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2043860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] b = NativeCrypto.i2d_SSL_SESSION(session);
2044860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNotNull(b);
2045860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long session2 = NativeCrypto.d2i_SSL_SESSION(b);
2046860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(session2 != NULL);
2047860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2048860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                // Make sure d2i_SSL_SESSION retores SSL_SESSION_cipher value http://b/7091840
2049860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(NativeCrypto.SSL_SESSION_cipher(session2) != null);
2050860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(NativeCrypto.SSL_SESSION_cipher(session),
2051860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                             NativeCrypto.SSL_SESSION_cipher(session2));
2052860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2053860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_SESSION_free(session2);
2054860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2055860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2056860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2057860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
20586fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
20596fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2060860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2061860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2062860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2063860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2064860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_d2i_SSL_SESSION() throws Exception {
2065860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2066860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.d2i_SSL_SESSION(null);
2067860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2068860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2069860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2070860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2071860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[0]));
2072860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[1]));
2073860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2074860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positive testing by test_i2d_SSL_SESSION
2075860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2076860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2077860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_X509_NAME_hashes() {
2078860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // ensure these hash functions are stable over time since the
2079860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // /system/etc/security/cacerts CA filenames have to be
2080860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // consistent with the output.
2081860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X500Principal name = new X500Principal("CN=localhost");
2082860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(-1372642656, NativeCrypto.X509_NAME_hash(name)); // SHA1
2083860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(-1626170662, NativeCrypto.X509_NAME_hash_old(name)); // MD5
2084860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2085860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2086860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_ENGINE_by_id_Failure() throws Exception {
2087860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.ENGINE_load_dynamic();
2088860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2089860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long engine = NativeCrypto.ENGINE_by_id("non-existent");
2090860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (engine != 0) {
2091860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.ENGINE_finish(engine);
2092860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("should not acquire reference to non-existent engine");
2093860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2094860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2095860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2096860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
2097860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Loads the test OpenSSL ENGINE. If it's already loaded, returns
2098860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * immediately.
2099860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
2100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void loadTestEngine() throws Exception {
2101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long testEngine = NativeCrypto.ENGINE_by_id(TEST_ENGINE_ID);
2102860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (testEngine != 0) {
2103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.ENGINE_finish(testEngine);
2104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return;
2105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.ENGINE_load_dynamic();
2108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long dynEngine = NativeCrypto.ENGINE_by_id("dynamic");
2109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2110860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            ClassLoader loader = NativeCryptoTest.class.getClassLoader();
2111860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final String libraryPaths;
2113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (loader instanceof BaseDexClassLoader) {
2114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                libraryPaths = ((BaseDexClassLoader) loader).getLdLibraryPath();
2115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } else {
2116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                libraryPaths = System.getProperty("java.library.path");
2117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNotNull(libraryPaths);
2119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            String[] libraryPathArray = libraryPaths.split(":");
2121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            for (String path : libraryPathArray) {
2122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(1, NativeCrypto.ENGINE_ctrl_cmd_string(dynEngine, "DIR_ADD", path, 0));
2123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // We must add this to the list of ENGINEs
2126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(1, NativeCrypto.ENGINE_ctrl_cmd_string(dynEngine, "LIST_ADD", "2", 0));
2127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // Do a direct load of the ENGINE.
2129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(1,
2130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.ENGINE_ctrl_cmd_string(dynEngine, "ID", TEST_ENGINE_ID, 0));
2131860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(1, NativeCrypto.ENGINE_ctrl_cmd_string(dynEngine, "LOAD", null, 0));
2132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.ENGINE_finish(dynEngine);
2134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2136860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        testEngine = NativeCrypto.ENGINE_by_id(TEST_ENGINE_ID);
2137860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (testEngine == 0) {
2138860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("could not load test engine");
2139860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.ENGINE_finish(testEngine);
2141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2142860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_ENGINE_by_id_TestEngine() throws Exception {
2144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        loadTestEngine();
2145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long engine = NativeCrypto.ENGINE_by_id(TEST_ENGINE_ID);
2147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(engine != 0);
2148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.ENGINE_add(engine);
2149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long pkey = NULL;
2151860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2152860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final String rsaPem =
2153860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                      "-----BEGIN RSA PRIVATE KEY-----\n"
2154860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "MIICXAIBAAKBgQCvvsYz1VKhU9PT0NHlotX22tcCjeaiVFNg0JrkjoK2XuMb+7a6\n"
2155860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "R5bzgIr24+OnBB0LqgaKnHwxZTA73lo/Wy/Ms5Kvg4yX9UMkNE+PvH5vzcQBbFdI\n"
2156860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "lwETFPvFokHO5OyOcEY+iVWG2fDloteH2JsrKYLh9Sx3Br5pHFCCm5qT5wIDAQAB\n"
2157860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "AoGAWDxoNs371pPH3qkROUIwOuhU2ytziDzeP9V8bxQ9/GJXlE0kyRH4b/kxzBNO\n"
2158860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "0SP3kUukTSOUFxi+xtA0b2rQ7Be2txtjzW1TGOHSCWbFrJAdTqeBcmQJSaZay8n1\n"
2159860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "LOpk4/zvBl7VScBth1IgXP44v6lOzthsrDhMlUYs07ymwYECQQDonaLOhkmVThPa\n"
2160860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "CIThdE5CN/wF5UDzGOz+ZBz3dt8D8QQMu0aZaPzibq9BC462j/fWeWS5OFzbq2+T\n"
2161860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "+cor3nwPAkEAwWmTQdra6GMPEc40zNsM5ehF2FjOpX8aU8267eG56y0Y+GbHx2BN\n"
2162860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "zAHfPxGBBH8cZ0cLhk4RSo/po7Vv+cRyqQJAAQz1N0mT+4Cmxk1TjFEiKVpnYP9w\n"
2163860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "E6kBKQT6vINk7negNQ6Dex3mRn+Jexm6Q0jTLbzOn6eJg9R6ZIi0SQ5wMQJAKX2n\n"
2164860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "fGohqdaORgiRZRzcsHlaemXatsAEetPYdO2Gf7/l6mvKEahEKC6CoLn1jmxiQHmK\n"
2165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "LF6U8QTcXyUuB0uwOQJBAIwWWjQGGc2sAQ1HW0C2wwCQbWneeBkiRBedonDBHtiB\n"
2166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "Wz0zS2CMCtBPNeHQmmsXH2Ca+ADdh53sKTuperLiuiw=\n"
2167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    + "-----END RSA PRIVATE KEY-----";
2168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            pkey = NativeCrypto.ENGINE_load_private_key(engine, rsaPem);
2169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(pkey != 0);
2170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (pkey != NULL) {
2172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(pkey);
2173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.ENGINE_free(engine);
2176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.ENGINE_finish(engine);
2177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_RAND_bytes_Success() throws Exception {
2181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] output = new byte[128];
2182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.RAND_bytes(output);
2183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        boolean isZero = true;
2185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        for (int i = 0; i < output.length; i++) {
2186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            isZero &= (output[i] == 0);
2187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse("Random output was zero. This is a very low probability event (1 in 2^128) "
2190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                + "and probably indicates an error.", isZero);
2191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_RAND_bytes_Null_Failure() throws Exception {
2194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] output = null;
2195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.RAND_bytes(output);
2197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Should be an error on null buffer input");
2198860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2200860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_get_digestbyname() throws Exception {
2203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.EVP_get_digestbyname("sha256") != NULL);
2204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname(null);
2207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2212860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname("");
2213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname("foobar");
2214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_SignInit() throws Exception {
2220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final long ctx = NativeCrypto.EVP_SignInit("RSA-SHA256");
2221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(ctx != NULL);
2222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.EVP_MD_CTX_destroy(ctx);
2223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_SignInit("foobar");
2226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2227860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2228860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2231860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_get_RSA_private_params() throws Exception {
2232860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2233860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.get_RSA_private_params(NULL);
2234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2236860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2238860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.get_RSA_private_params(NULL);
2239860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2241860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2242860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Test getting params for the wrong kind of key.
2243860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] seed = new byte[20];
2244860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long ctx = 0;
2245860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2246860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
2247860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(ctx != NULL);
2248860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2249860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.get_RSA_private_params(ctx);
2250860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2251860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (RuntimeException expected) {
2252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2253860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2254860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (ctx != 0) {
2255860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(ctx);
2256860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2257860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2258860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2259860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2260860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_get_RSA_public_params() throws Exception {
2261860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2262860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.get_RSA_public_params(NULL);
2263860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2264860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2265860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2266860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2267860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.get_RSA_public_params(NULL);
2268860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2269860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2270860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2271860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Test getting params for the wrong kind of key.
2272860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] seed = new byte[20];
2273860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long ctx = 0;
2274860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2275860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
2276860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(ctx != NULL);
2277860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2278860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.get_RSA_public_params(ctx);
2279860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2280860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (RuntimeException expected) {
2281860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2282860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2283860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (ctx != 0) {
2284860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(ctx);
2285860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2286860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2287860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2288860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2289860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    final byte[] dsa2048_p = {
2290860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xC3, (byte) 0x16, (byte) 0xD4, (byte) 0xBA, (byte) 0xDC, (byte) 0x0E,
2291860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xB8, (byte) 0xFC, (byte) 0x40, (byte) 0xDB, (byte) 0xB0, (byte) 0x76,
2292860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x47, (byte) 0xB8, (byte) 0x8D, (byte) 0xC1, (byte) 0xF1, (byte) 0xAB,
2293860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x9B, (byte) 0x80, (byte) 0x9D, (byte) 0xDC, (byte) 0x55, (byte) 0x33,
2294860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xEC, (byte) 0xB6, (byte) 0x09, (byte) 0x8F, (byte) 0xB7, (byte) 0xD9,
2295860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xA5, (byte) 0x7F, (byte) 0xC1, (byte) 0xE3, (byte) 0xAD, (byte) 0xE1,
2296860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x7A, (byte) 0x58, (byte) 0xF4, (byte) 0x2D, (byte) 0xB9, (byte) 0x61,
2297860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xCF, (byte) 0x5B, (byte) 0xCA, (byte) 0x41, (byte) 0x9F, (byte) 0x73,
2298860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8D, (byte) 0x81, (byte) 0x62, (byte) 0xD2, (byte) 0x19, (byte) 0x7D,
2299860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x18, (byte) 0xDB, (byte) 0xB3, (byte) 0x04, (byte) 0xE7, (byte) 0xB2,
2300860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x28, (byte) 0x59, (byte) 0x14, (byte) 0x73, (byte) 0x43, (byte) 0xF1,
2301860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x45, (byte) 0xC7, (byte) 0x47, (byte) 0xCC, (byte) 0xD1, (byte) 0x12,
2302860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8E, (byte) 0x19, (byte) 0x00, (byte) 0x2C, (byte) 0xD0, (byte) 0x86,
2303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x54, (byte) 0x64, (byte) 0x2D, (byte) 0x42, (byte) 0x6C, (byte) 0x6B,
2304860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x5C, (byte) 0x2D, (byte) 0x4D, (byte) 0x97, (byte) 0x6A, (byte) 0x1D,
2305860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x89, (byte) 0xB1, (byte) 0x2C, (byte) 0xA0, (byte) 0x05, (byte) 0x2B,
2306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x3C, (byte) 0xDB, (byte) 0x1F, (byte) 0x89, (byte) 0x03, (byte) 0x03,
2307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x92, (byte) 0x63, (byte) 0xB6, (byte) 0x08, (byte) 0x32, (byte) 0x50,
2308860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xB2, (byte) 0x54, (byte) 0xA3, (byte) 0xFE, (byte) 0x6C, (byte) 0x35,
2309860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x17, (byte) 0x2F, (byte) 0x7F, (byte) 0x54, (byte) 0xA4, (byte) 0xAE,
2310860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x96, (byte) 0x1E, (byte) 0x31, (byte) 0x83, (byte) 0xF1, (byte) 0x3F,
2311860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x9E, (byte) 0xB9, (byte) 0x5D, (byte) 0xD3, (byte) 0xA9, (byte) 0xCB,
2312860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xE5, (byte) 0x2F, (byte) 0xBC, (byte) 0xA4, (byte) 0x1A, (byte) 0x31,
2313860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x41, (byte) 0x91, (byte) 0x2C, (byte) 0xA0, (byte) 0xF4, (byte) 0x83,
2314860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xAC, (byte) 0xD5, (byte) 0xBA, (byte) 0x3D, (byte) 0x19, (byte) 0xED,
2315860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xF1, (byte) 0x6C, (byte) 0xD9, (byte) 0x3F, (byte) 0x30, (byte) 0xDA,
2316860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x80, (byte) 0x06, (byte) 0x56, (byte) 0x3A, (byte) 0x8C, (byte) 0x74,
2317860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x63, (byte) 0xF2, (byte) 0xED, (byte) 0x1E, (byte) 0xE3, (byte) 0x86,
2318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x95, (byte) 0x64, (byte) 0x2A, (byte) 0xC4, (byte) 0x5F, (byte) 0xB2,
2319860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x64, (byte) 0x40, (byte) 0x9D, (byte) 0xA6, (byte) 0xB8, (byte) 0xF5,
2320860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x84, (byte) 0x03, (byte) 0x2E, (byte) 0x4A, (byte) 0x7A, (byte) 0x1A,
2321860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xB0, (byte) 0x0E, (byte) 0xBA, (byte) 0xB1, (byte) 0xF5, (byte) 0xD2,
2322860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xE7, (byte) 0x65, (byte) 0xCE, (byte) 0xEE, (byte) 0x2C, (byte) 0x7C,
2323860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x68, (byte) 0x20, (byte) 0x50, (byte) 0x53, (byte) 0x0F, (byte) 0x60,
2324860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x92, (byte) 0x81, (byte) 0xC0, (byte) 0x2C, (byte) 0x2A, (byte) 0xEA,
2325860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xE9, (byte) 0xB3, (byte) 0x2A, (byte) 0x81, (byte) 0xDA, (byte) 0x0F,
2326860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xBB, (byte) 0xFA, (byte) 0x5B, (byte) 0x47, (byte) 0xDA, (byte) 0x57,
2327860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x4E, (byte) 0xFC, (byte) 0x05, (byte) 0x2C, (byte) 0x6A, (byte) 0x90,
2328860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xA0, (byte) 0x99, (byte) 0x88, (byte) 0x71, (byte) 0x8A, (byte) 0xCC,
2329860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xD2, (byte) 0x97, (byte) 0x11, (byte) 0xB1, (byte) 0xCE, (byte) 0xF7,
2330860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x47, (byte) 0x53, (byte) 0x53, (byte) 0x68, (byte) 0xE1, (byte) 0x2A,
2331860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x56, (byte) 0xD5, (byte) 0x3D, (byte) 0xDF, (byte) 0x08, (byte) 0x16,
2332860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x1F, (byte) 0xAA, (byte) 0x54, (byte) 0x15,
2333860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2334860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2335860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    final byte[] dsa2048_q = {
2336860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xAA, (byte) 0xDD, (byte) 0xE2, (byte) 0xCE, (byte) 0x08, (byte) 0xC0,
2337860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x0E, (byte) 0x91, (byte) 0x8C, (byte) 0xD9, (byte) 0xBC, (byte) 0x1E,
2338860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x05, (byte) 0x70, (byte) 0x07, (byte) 0x3B, (byte) 0xB5, (byte) 0xA9,
2339860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xB5, (byte) 0x8B, (byte) 0x21, (byte) 0x68, (byte) 0xA2, (byte) 0x76,
2340860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x53, (byte) 0x1E, (byte) 0x68, (byte) 0x1B, (byte) 0x4F, (byte) 0x88,
2341860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x6D, (byte) 0xCF,
2342860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2343860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2344860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    final byte[] dsa2048_g = {
2345860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x6B, (byte) 0x4D, (byte) 0x21, (byte) 0x92, (byte) 0x24, (byte) 0x76,
2346860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xE5, (byte) 0xA2, (byte) 0xCE, (byte) 0x02, (byte) 0x85, (byte) 0x32,
2347860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x73, (byte) 0x70, (byte) 0xFF, (byte) 0xB9, (byte) 0xD4, (byte) 0x51,
2348860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xBA, (byte) 0x22, (byte) 0x8B, (byte) 0x75, (byte) 0x29, (byte) 0xE3,
2349860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xF2, (byte) 0x2E, (byte) 0x20, (byte) 0xF5, (byte) 0x6A, (byte) 0xD9,
2350860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x75, (byte) 0xA0, (byte) 0xC0, (byte) 0x3B, (byte) 0x12, (byte) 0x2F,
2351860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x4F, (byte) 0x9A, (byte) 0xF8, (byte) 0x5D, (byte) 0x45, (byte) 0xC5,
2352860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x80, (byte) 0x6C, (byte) 0x9B, (byte) 0x56, (byte) 0xBE, (byte) 0x8E,
2353860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x40, (byte) 0xF9, (byte) 0x0A, (byte) 0xF0, (byte) 0x3D, (byte) 0xD7,
2354860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x7C, (byte) 0xDE, (byte) 0x22, (byte) 0x10, (byte) 0x24, (byte) 0xCC,
2355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xAE, (byte) 0x8A, (byte) 0xC0, (byte) 0x05, (byte) 0xCD, (byte) 0xDC,
2356860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x10, (byte) 0x29, (byte) 0x4D, (byte) 0xFC, (byte) 0xEC, (byte) 0xEF,
2357860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x51, (byte) 0x4B, (byte) 0xF9, (byte) 0xCC, (byte) 0x99, (byte) 0x84,
2358860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x1B, (byte) 0x14, (byte) 0x68, (byte) 0xEC, (byte) 0xF0, (byte) 0x5E,
2359860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x07, (byte) 0x10, (byte) 0x09, (byte) 0xA9, (byte) 0x2C, (byte) 0x04,
2360860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xD0, (byte) 0x14, (byte) 0xBF, (byte) 0x88, (byte) 0x9E, (byte) 0xBB,
2361860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xE3, (byte) 0x3F, (byte) 0xDE, (byte) 0x92, (byte) 0xE1, (byte) 0x64,
2362860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x07, (byte) 0x28, (byte) 0xC1, (byte) 0xCA, (byte) 0x48, (byte) 0xC1,
2363860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x1D, (byte) 0x33, (byte) 0xE4, (byte) 0x35, (byte) 0xBE, (byte) 0xDF,
2364860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x5E, (byte) 0x50, (byte) 0xF9, (byte) 0xC2, (byte) 0x0E, (byte) 0x25,
2365860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x0D, (byte) 0x20, (byte) 0x8C, (byte) 0x01, (byte) 0x0A, (byte) 0x23,
2366860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xD4, (byte) 0x6E, (byte) 0x42, (byte) 0x47, (byte) 0xE1, (byte) 0x9E,
2367860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x36, (byte) 0x91, (byte) 0xC8, (byte) 0x65, (byte) 0x44, (byte) 0xE0,
2368860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x04, (byte) 0x86, (byte) 0x2F, (byte) 0xD4, (byte) 0x90, (byte) 0x16,
2369860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x09, (byte) 0x14, (byte) 0xB1, (byte) 0xC5, (byte) 0x7D, (byte) 0xB2,
2370860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x7C, (byte) 0x36, (byte) 0x0D, (byte) 0x9C, (byte) 0x1F, (byte) 0x83,
2371860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x57, (byte) 0x94, (byte) 0x26, (byte) 0x32, (byte) 0x9C, (byte) 0x86,
2372860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8E, (byte) 0xE5, (byte) 0x80, (byte) 0x3A, (byte) 0xA9, (byte) 0xAF,
2373860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x4A, (byte) 0x95, (byte) 0x78, (byte) 0x8D, (byte) 0xE6, (byte) 0xC3,
2374860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x0C, (byte) 0x78, (byte) 0x83, (byte) 0x4B, (byte) 0xF5, (byte) 0x40,
2375860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x04, (byte) 0x20, (byte) 0x90, (byte) 0x5C, (byte) 0xA1, (byte) 0x19,
2376860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xEB, (byte) 0x95, (byte) 0x70, (byte) 0x2B, (byte) 0x94, (byte) 0xA3,
2377860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x43, (byte) 0xDD, (byte) 0xEB, (byte) 0xD4, (byte) 0x0C, (byte) 0xBC,
2378860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xBD, (byte) 0x58, (byte) 0x2D, (byte) 0x75, (byte) 0xB0, (byte) 0x8D,
2379860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8B, (byte) 0x70, (byte) 0xB9, (byte) 0xE7, (byte) 0xA3, (byte) 0xCC,
2380860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8C, (byte) 0xB4, (byte) 0xCD, (byte) 0xBB, (byte) 0x4B, (byte) 0xB1,
2381860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x15, (byte) 0x18, (byte) 0x79, (byte) 0xDF, (byte) 0x22, (byte) 0xA6,
2382860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x5C, (byte) 0x90, (byte) 0x7C, (byte) 0x1F, (byte) 0xEA, (byte) 0x1B,
2383860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xF2, (byte) 0x89, (byte) 0x87, (byte) 0xB2, (byte) 0xEC, (byte) 0x57,
2384860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xFF, (byte) 0xB2, (byte) 0xDA, (byte) 0xF5, (byte) 0xAD, (byte) 0x73,
2385860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0xC0, (byte) 0xA0, (byte) 0x20, (byte) 0x8B, (byte) 0x78, (byte) 0xA1,
2386860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x5D, (byte) 0x04, (byte) 0x0A, (byte) 0x29, (byte) 0xE3, (byte) 0xD7,
2387860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x37, (byte) 0xF6, (byte) 0xA2, (byte) 0xCA,
2388860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2389860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2390860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_DSA_generate_key() throws Exception {
2391860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] seed = new byte[20];
2392860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2393860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Real key
2394860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2395860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long ctx = 0;
2396860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2397860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                ctx = NativeCrypto.DSA_generate_key(2048, seed, dsa2048_g, dsa2048_p, dsa2048_q);
2398860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(ctx != NULL);
2399860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } finally {
2400860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (ctx != 0) {
2401860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_free(ctx);
2402860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2403860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2404860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2405860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2406860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Real key with minimum bit size (should be 512 bits)
2407860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2408860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long ctx = 0;
2409860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2410860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                ctx = NativeCrypto.DSA_generate_key(0, null, null, null, null);
2411860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(ctx != NULL);
2412860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } finally {
2413860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (ctx != 0) {
2414860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_free(ctx);
2415860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2416860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2417860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2418860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2419860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Bad DSA params.
2420860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2421860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long ctx = 0;
2422860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2423860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                ctx = NativeCrypto.DSA_generate_key(0, null, new byte[] {}, new byte[] {},
2424860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        new byte[] {});
2425860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2426860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (RuntimeException expected) {
2427860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } finally {
2428860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (ctx != 0) {
2429860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EVP_PKEY_free(ctx);
2430860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2431860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2432860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2433860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2434860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2435860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /*
2436860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Test vector generation:
2437860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * openssl rand -hex 16
2438860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
2439860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final byte[] AES_128_KEY = new byte[] {
2440860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2,
2441860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29,
2442860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f,
2443860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2444860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2445860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final byte[] AES_IV_ZEROES = new byte[] {
2446860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2447860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2448860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
2449860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2450860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2451860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testEC_GROUP() throws Exception {
2452860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        /* Test using NIST's P-256 curve */
2453860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        check_EC_GROUP(NativeCrypto.EC_CURVE_GFP, "prime256v1",
2454860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
2455860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
2456860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
2457860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
2458860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
2459860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
2460860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                1L);
2461860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2462860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        check_EC_GROUP(NativeCrypto.EC_CURVE_GF2M, "sect283r1",
2463860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "0800000000000000000000000000000000000000000000000000000000000000000010A1",
2464860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "000000000000000000000000000000000000000000000000000000000000000000000001",
2465860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5",
2466860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053",
2467860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4",
2468860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307",
2469860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                2L);
2470860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2471860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2472860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void check_EC_GROUP(int type, String name, String pStr, String aStr, String bStr,
2473860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            String xStr, String yStr, String nStr, long hLong) throws Exception {
2474860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long group1 = NULL, group2 = NULL, point1 = NULL, point2 = NULL, key1 = NULL;
2475860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2476860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            group1 = NativeCrypto.EC_GROUP_new_by_curve_name(name);
2477860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(group1 != NULL);
2478860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(NativeCrypto.OBJ_txt2nid_longName(name),
2479860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EC_GROUP_get_curve_name(group1));
2480860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(type, NativeCrypto.get_EC_GROUP_type(group1));
2481860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2482860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // prime
2483860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger p = new BigInteger(pStr, 16);
2484860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // first coefficient
2485860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger a = new BigInteger(aStr, 16);
2486860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // second coefficient
2487860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger b = new BigInteger(bStr, 16);
2488860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // x affine coordinate of generator
2489860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger x = new BigInteger(xStr, 16);
2490860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // y affine coordinate of generator
2491860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger y = new BigInteger(yStr, 16);
2492860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // order of the generator
2493860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger n = new BigInteger(nStr, 16);
2494860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // cofactor of generator
2495860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger h = BigInteger.valueOf(hLong);
2496860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2497860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            group2 = NativeCrypto.EC_GROUP_new_curve(type, p.toByteArray(),
2498860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    a.toByteArray(), b.toByteArray());
2499860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(type, NativeCrypto.get_EC_GROUP_type(group2));
2500860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2501860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            point2 = NativeCrypto.EC_POINT_new(group2);
2502860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2503860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EC_POINT_set_affine_coordinates(group2, point2, x.toByteArray(),
2504860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    y.toByteArray());
2505860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2506860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EC_GROUP_set_generator(group2, point2, n.toByteArray(), h.toByteArray());
2507860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2508860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            point1 = NativeCrypto.EC_GROUP_get_generator(group2);
2509860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(NativeCrypto.EC_POINT_cmp(group1, point1, point2));
2510860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2511860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            byte[][] pab = NativeCrypto.EC_GROUP_get_curve(group2);
2512860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(3, pab.length);
2513860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2514860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger p2 = new BigInteger(pab[0]);
2515860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(p, p2);
2516860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2517860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger a2 = new BigInteger(pab[1]);
2518860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(a, a2);
2519860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2520860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger b2 = new BigInteger(pab[2]);
2521860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(b, b2);
2522860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2523860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            byte[][] xy = NativeCrypto.EC_POINT_get_affine_coordinates(group2, point2);
2524860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(2, xy.length);
2525860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2526860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger x2 = new BigInteger(xy[0]);
2527860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(x, x2);
2528860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2529860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger y2 = new BigInteger(xy[1]);
2530860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(y, y2);
2531860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2532860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger n2 = new BigInteger(NativeCrypto.EC_GROUP_get_order(group1));
2533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(n, n2);
2534860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2535860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            BigInteger h2 = new BigInteger(NativeCrypto.EC_GROUP_get_cofactor(group2));
2536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(h, h2);
2537860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2538860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(NativeCrypto.EC_GROUP_cmp(group1, group2));
2539860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            key1 = NativeCrypto.EC_KEY_generate_key(group1);
2541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long groupTmp = NativeCrypto.EC_KEY_get0_group(key1);
2542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(NativeCrypto.EC_GROUP_get_curve_name(group1),
2543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.EC_GROUP_get_curve_name(groupTmp));
2544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (group1 != NULL) {
2547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EC_GROUP_clear_free(group1);
2548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (group2 != NULL) {
2551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EC_GROUP_clear_free(group2);
2552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2553860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2554860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (point1 != NULL) {
2555860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EC_POINT_clear_free(point1);
2556860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2557860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (point2 != NULL) {
2559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EC_POINT_clear_free(point2);
2560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2561860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2562860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (key1 != NULL) {
2563860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_PKEY_free(key1);
2564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2565860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2566860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CipherInit_ex_Null_Failure() throws Exception {
2569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final long ctx = NativeCrypto.EVP_CIPHER_CTX_new();
2570860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2571860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
2572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2574860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EVP_CipherInit_ex(NULL, evpCipher, null, null, true);
2575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail("Null context should throw NullPointerException");
2576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2578860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2579860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            /* Initialize encrypting. */
2580860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, true);
2581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, true);
2582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            /* Initialize decrypting. */
2584860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, false);
2585860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, false);
2586860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2587860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CIPHER_CTX_cleanup(ctx);
2588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2589860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2590860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2591860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CipherInit_ex_Success() throws Exception {
2592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final long ctx = NativeCrypto.EVP_CIPHER_CTX_new();
2593860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2594860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
2595860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, AES_128_KEY, null, true);
2596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2597860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_CIPHER_CTX_cleanup(ctx);
2598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2600860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2601860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CIPHER_iv_length() throws Exception {
2602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long aes128ecb = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
2603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.EVP_CIPHER_iv_length(aes128ecb));
2604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long aes128cbc = NativeCrypto.EVP_get_cipherbyname("aes-128-cbc");
2606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(16, NativeCrypto.EVP_CIPHER_iv_length(aes128cbc));
2607860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2608860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2609860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_OpenSSLKey_toJava() throws Exception {
2610860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        OpenSSLKey key1;
2611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2612860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        BigInteger e = BigInteger.valueOf(65537);
2613860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        key1 = new OpenSSLKey(NativeCrypto.RSA_generate_key_ex(1024, e.toByteArray()));
2614860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(key1.getPublicKey() instanceof RSAPublicKey);
2615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        key1 = new OpenSSLKey(NativeCrypto.DSA_generate_key(1024, null, null, null, null));
2617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(key1.getPublicKey() instanceof DSAPublicKey);
2618860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2619860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long group1 = NULL;
2620860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2621860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            group1 = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
2622860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertTrue(group1 != NULL);
2623860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            key1 = new OpenSSLKey(NativeCrypto.EC_KEY_generate_key(group1));
2624860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2625860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (group1 != NULL) {
2626860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.EC_GROUP_clear_free(group1);
2627860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2628860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2629860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(key1.getPublicKey() instanceof ECPublicKey);
2630860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2631860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2632860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_create_BIO_InputStream() throws Exception {
2633860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] actual = "Test".getBytes();
2634860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ByteArrayInputStream is = new ByteArrayInputStream(actual);
2635860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2636860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long ctx = NativeCrypto.create_BIO_InputStream(new OpenSSLBIOInputStream(is));
2637860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2638860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            byte[] buffer = new byte[1024];
2639860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            int numRead = NativeCrypto.BIO_read(ctx, buffer);
2640860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(actual.length, numRead);
2641860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(Arrays.toString(actual),
2642860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    Arrays.toString(Arrays.copyOfRange(buffer, 0, numRead)));
2643860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2644860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.BIO_free(ctx);
2645860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2646860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2647860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2648860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2649860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_create_BIO_OutputStream() throws Exception {
2650860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] actual = "Test".getBytes();
2651860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ByteArrayOutputStream os = new ByteArrayOutputStream();
2652860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2653860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long ctx = NativeCrypto.create_BIO_OutputStream(os);
2654860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2655860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.BIO_write(ctx, actual, 0, actual.length);
2656860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(actual.length, os.size());
2657860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(Arrays.toString(actual), Arrays.toString(os.toByteArray()));
2658860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
2659860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.BIO_free(ctx);
2660860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2661860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2662860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root}
2663