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