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 java.io.ByteArrayInputStream;
20860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.ByteArrayOutputStream;
21860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.FileDescriptor;
22860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.io.IOException;
2301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubinimport java.io.UnsupportedEncodingException;
24860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.math.BigInteger;
25860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.ServerSocket;
26860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.Socket;
2781c666781f8e24242e997e2666b656b240c5a145Kenny Rootimport java.net.SocketException;
28860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.net.SocketTimeoutException;
29860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyPair;
30860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyPairGenerator;
31860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyStore;
32860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.KeyStore.PrivateKeyEntry;
330e9746b7b132058651155b33f219c7789997985bKenny Rootimport java.security.cert.Certificate;
340e9746b7b132058651155b33f219c7789997985bKenny Rootimport java.security.cert.CertificateEncodingException;
35860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.CertificateException;
36860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.cert.X509Certificate;
37860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.ECPublicKey;
38860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.RSAPrivateCrtKey;
39860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.interfaces.RSAPublicKey;
40860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.security.spec.ECPrivateKeySpec;
41860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.ArrayList;
42860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.Arrays;
43b9bfe69f1c205ab67a03e10a01e2cc90871a0879Alex Klyubinimport java.util.HashSet;
44860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.List;
45860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Callable;
46860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.ExecutionException;
47860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.ExecutorService;
48860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Executors;
49860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.Future;
50860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport java.util.concurrent.TimeUnit;
514757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root
52860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.SSLException;
53efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Rootimport javax.net.ssl.SSLHandshakeException;
54860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.net.ssl.SSLProtocolException;
55860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport javax.security.auth.x500.X500Principal;
564757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root
57860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport junit.framework.TestCase;
58860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.io.IoUtils;
59860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.java.security.StandardNames;
60860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport libcore.java.security.TestKeyStore;
614757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root
62860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootimport org.conscrypt.NativeCrypto.SSLHandshakeCallbacks;
63f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langleyimport static org.conscrypt.NativeConstants.SSL_MODE_CBC_RECORD_SPLITTING;
64f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langleyimport static org.conscrypt.NativeConstants.SSL_MODE_HANDSHAKE_CUTTHROUGH;
65860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
66860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Rootpublic class NativeCryptoTest extends TestCase {
67860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /** Corresponds to the native test library "libjavacoretests.so" */
68860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static final String TEST_ENGINE_ID = "javacoretests";
69860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
70860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final long NULL = 0;
71860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final FileDescriptor INVALID_FD = new FileDescriptor();
72860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final SSLHandshakeCallbacks DUMMY_CB
73860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            = new TestSSLHandshakeCallbacks(null, 0, null);
74860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
75860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final long TIMEOUT_SECONDS = 5;
76860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
771ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey SERVER_PRIVATE_KEY;
780e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] SERVER_CERTIFICATES_HOLDER;
790e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] SERVER_CERTIFICATES;
801ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey CLIENT_PRIVATE_KEY;
810e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] CLIENT_CERTIFICATES_HOLDER;
820e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] CLIENT_CERTIFICATES;
83860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[][] CA_PRINCIPALS;
841ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey CHANNEL_ID_PRIVATE_KEY;
85860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[] CHANNEL_ID;
86860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
87860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    @Override
88860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    protected void tearDown() throws Exception {
89860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.ERR_peek_last_error());
90860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
91860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
921ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey getServerPrivateKey() {
93860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
94860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return SERVER_PRIVATE_KEY;
95860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
96860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
970e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getServerCertificates() {
98860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
99860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return SERVER_CERTIFICATES;
100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1021ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root    private static OpenSSLKey getClientPrivateKey() {
103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CLIENT_PRIVATE_KEY;
105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1070e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getClientCertificates() {
108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CLIENT_CERTIFICATES;
110860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
111860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static byte[][] getCaPrincipals() {
113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initCerts();
114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return CA_PRINCIPALS;
115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Lazily create shared test certificates.
119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static synchronized void initCerts() {
121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (SERVER_PRIVATE_KEY != null) {
122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return;
123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            PrivateKeyEntry serverPrivateKeyEntry
127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    = TestKeyStore.getServer().getPrivateKey("RSA", "RSA");
1281ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            SERVER_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(serverPrivateKeyEntry.getPrivateKey());
1290e9746b7b132058651155b33f219c7789997985bKenny Root            SERVER_CERTIFICATES_HOLDER = encodeCertificateList(
130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    serverPrivateKeyEntry.getCertificateChain());
1310e9746b7b132058651155b33f219c7789997985bKenny Root            SERVER_CERTIFICATES = getCertificateReferences(SERVER_CERTIFICATES_HOLDER);
132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            PrivateKeyEntry clientPrivateKeyEntry
134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA");
1351ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root            CLIENT_PRIVATE_KEY = OpenSSLKey.fromPrivateKey(clientPrivateKeyEntry.getPrivateKey());
1360e9746b7b132058651155b33f219c7789997985bKenny Root            CLIENT_CERTIFICATES_HOLDER = encodeCertificateList(
137860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    clientPrivateKeyEntry.getCertificateChain());
1380e9746b7b132058651155b33f219c7789997985bKenny Root            CLIENT_CERTIFICATES = getCertificateReferences(CLIENT_CERTIFICATES_HOLDER);
139860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            KeyStore ks = TestKeyStore.getClient().keyStore;
141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            String caCertAlias = ks.aliases().nextElement();
142860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            X509Certificate certificate = (X509Certificate) ks.getCertificate(caCertAlias);
143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            X500Principal principal = certificate.getIssuerX500Principal();
144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            CA_PRINCIPALS = new byte[][] { principal.getEncoded() };
145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            initChannelIdKey();
146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (Exception e) {
147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            throw new RuntimeException(e);
148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1510e9746b7b132058651155b33f219c7789997985bKenny Root    private static long[] getCertificateReferences(OpenSSLX509Certificate[] certs) {
1520e9746b7b132058651155b33f219c7789997985bKenny Root        final long[] certRefs = new long[certs.length];
1530e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < certs.length; i++) {
1540e9746b7b132058651155b33f219c7789997985bKenny Root            certRefs[i] = certs[i].getContext();
1550e9746b7b132058651155b33f219c7789997985bKenny Root        }
1560e9746b7b132058651155b33f219c7789997985bKenny Root        return certRefs;
1570e9746b7b132058651155b33f219c7789997985bKenny Root    }
1580e9746b7b132058651155b33f219c7789997985bKenny Root
1590e9746b7b132058651155b33f219c7789997985bKenny Root    private static OpenSSLX509Certificate[] encodeCertificateList(Certificate[] chain)
1600e9746b7b132058651155b33f219c7789997985bKenny Root            throws CertificateEncodingException {
1610e9746b7b132058651155b33f219c7789997985bKenny Root        final OpenSSLX509Certificate[] openSslCerts = new OpenSSLX509Certificate[chain.length];
1620e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < chain.length; i++) {
1630e9746b7b132058651155b33f219c7789997985bKenny Root            openSslCerts[i] = OpenSSLX509Certificate.fromCertificate(chain[i]);
1640e9746b7b132058651155b33f219c7789997985bKenny Root        }
1650e9746b7b132058651155b33f219c7789997985bKenny Root        return openSslCerts;
1660e9746b7b132058651155b33f219c7789997985bKenny Root    }
1670e9746b7b132058651155b33f219c7789997985bKenny Root
168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static synchronized void initChannelIdKey() throws Exception {
169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        if (CHANNEL_ID_PRIVATE_KEY != null) {
170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return;
171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NIST P-256 aka SECG secp256r1 aka X9.62 prime256v1
174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        OpenSSLECGroupContext openSslSpec = OpenSSLECGroupContext.getCurveByName("prime256v1");
175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        BigInteger s = new BigInteger(
176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "229cdbbf489aea584828a261a23f9ff8b0f66f7ccac98bf2096ab3aee41497c5", 16);
177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        CHANNEL_ID_PRIVATE_KEY = new OpenSSLECPrivateKey(
1781ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root                new ECPrivateKeySpec(s, openSslSpec.getECParameterSpec())).getOpenSSLKey();
179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Channel ID is the concatenation of the X and Y coordinates of the public key.
181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        CHANNEL_ID = new BigInteger(
182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "702b07871fd7955c320b26f15e244e47eed60272124c92b9ebecf0b42f90069b" +
183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        "ab53592ebfeb4f167dbf3ce61513afb0e354c479b1c1b69874fa471293494f77",
184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                16).toByteArray();
185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualSessions(long expected, long actual) {
188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected),
189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                              NativeCrypto.SSL_SESSION_session_id(actual));
190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualByteArrays(byte[] expected, byte[] actual) {
192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.toString(expected), Arrays.toString(actual));
193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualPrincipals(byte[][] expected, byte[][] actual) {
196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(expected, actual);
197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1980e9746b7b132058651155b33f219c7789997985bKenny Root
1990e9746b7b132058651155b33f219c7789997985bKenny Root    public static void assertEqualCertificateChains(long[] expected, long[] actual) {
2000e9746b7b132058651155b33f219c7789997985bKenny Root        assertEquals(expected.length, actual.length);
2010e9746b7b132058651155b33f219c7789997985bKenny Root        for (int i = 0; i < expected.length; i++) {
2020e9746b7b132058651155b33f219c7789997985bKenny Root            NativeCrypto.X509_cmp(expected[i], actual[i]);
2030e9746b7b132058651155b33f219c7789997985bKenny Root        }
204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2050e9746b7b132058651155b33f219c7789997985bKenny Root
206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static void assertEqualByteArrays(byte[][] expected, byte[][] actual) {
207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual));
208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_PKEY_cmp() throws Exception {
211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
212796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EVP_PKEY_cmp(null, null);
213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Should throw NullPointerException when arguments are NULL");
214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        kpg.initialize(512);
219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPair kp1 = kpg.generateKeyPair();
221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        RSAPrivateCrtKey privKey1 = (RSAPrivateCrtKey) kp1.getPrivate();
222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        KeyPair kp2 = kpg.generateKeyPair();
224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        RSAPrivateCrtKey privKey2 = (RSAPrivateCrtKey) kp2.getPrivate();
225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
22637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeRef.EVP_PKEY pkey1, pkey1_copy, pkey2;
22737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        pkey1 = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
22837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getModulus().toByteArray(),
22937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPublicExponent().toByteArray(),
23037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrivateExponent().toByteArray(),
23137e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeP().toByteArray(),
23237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeQ().toByteArray(),
23337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeExponentP().toByteArray(),
23437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeExponentQ().toByteArray(),
23537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getCrtCoefficient().toByteArray()));
23637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertNotSame(NULL, pkey1);
23737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root
23837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        pkey1_copy = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
23937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getModulus().toByteArray(),
24037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPublicExponent().toByteArray(),
24137e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrivateExponent().toByteArray(),
24237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeP().toByteArray(),
24337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeQ().toByteArray(),
24437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeExponentP().toByteArray(),
24537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getPrimeExponentQ().toByteArray(),
24637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey1.getCrtCoefficient().toByteArray()));
24737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertNotSame(NULL, pkey1_copy);
24837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root
24937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        pkey2 = new NativeRef.EVP_PKEY(NativeCrypto.EVP_PKEY_new_RSA(
25037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getModulus().toByteArray(),
25137e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPublicExponent().toByteArray(),
25237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPrivateExponent().toByteArray(),
25337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPrimeP().toByteArray(),
25437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPrimeQ().toByteArray(),
25537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPrimeExponentP().toByteArray(),
25637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getPrimeExponentQ().toByteArray(),
25737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                privKey2.getCrtCoefficient().toByteArray()));
25837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertNotSame(NULL, pkey2);
25937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root
26037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        try {
261796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EVP_PKEY_cmp(pkey1, null);
26237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            fail("Should throw NullPointerException when arguments are NULL");
26337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        } catch (NullPointerException expected) {
26437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        }
265860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
26637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        try {
267796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EVP_PKEY_cmp(null, null);
26837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            fail("Should throw NullPointerException when arguments are NULL");
26937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        } catch (NullPointerException expected) {
27037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        }
271860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertEquals("Same keys should be the equal", 1,
27337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1));
274860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertEquals("Same keys should be the equal", 1,
27637e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.EVP_PKEY_cmp(pkey1, pkey1_copy));
277860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        assertEquals("Different keys should not be equal", 0,
27937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.EVP_PKEY_cmp(pkey1, pkey2));
280860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
281860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
282860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_new() throws Exception {
283860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
284860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(c != NULL);
285860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c2 = NativeCrypto.SSL_CTX_new();
286860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(c != c2);
287860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
288860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c2);
289860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
290860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
291860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_free() throws Exception {
292860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
293860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(NULL);
294860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
295860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
296860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
297860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
298860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(NativeCrypto.SSL_CTX_new());
299860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
300860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
301860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_CTX_set_session_id_context() throws Exception {
302860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] empty = new byte[0];
303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
304860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(NULL, empty);
305860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
308860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
309860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
310860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(c, null);
311860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
312860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
313860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
314860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_set_session_id_context(c, empty);
315860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[32]);
316860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
317860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_set_session_id_context(c, new byte[33]);
318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (IllegalArgumentException expected) {
319860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
320860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
321860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
322860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
323860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_new() throws Exception {
324860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
325860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
326860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
327860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(s != NULL);
328f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
329f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1) == 0);
330f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1_1) == 0);
331f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_TLSv1_2) == 0);
332978e2e1e44570bdbac7b3538c5e198d8ff645202Alex Klyubin
333860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s2 = NativeCrypto.SSL_new(c);
334860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(s != s2);
335860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s2);
336860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
337860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
338860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
339860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
340860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
341860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_certificate() throws Exception {
342860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
343860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_use_certificate(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 {
352860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_use_certificate(s, null);
353860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
354860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
356860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
357860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
358860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
359860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
360860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
361860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
362860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
363860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_PrivateKey_for_tls_channel_id() throws Exception {
36497d151b258d226b3afc1b3588171b283ec3f8046Kenny Root        initChannelIdKey();
36597d151b258d226b3afc1b3588171b283ec3f8046Kenny Root
366860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
367796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.SSL_set1_tls_channel_id(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 {
376796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.SSL_set1_tls_channel_id(s, null);
377860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
378860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
379860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
380860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
381860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Use the key natively. This works because the initChannelIdKey method ensures that the
382860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // key is backed by OpenSSL.
38337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeCrypto.SSL_set1_tls_channel_id(s, CHANNEL_ID_PRIVATE_KEY.getNativeRef());
384860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
385860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
386860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
387860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
388860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
389860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_use_PrivateKey() throws Exception {
390860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
391796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.SSL_use_PrivateKey(NULL, null);
392860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
393860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
394860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
395860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
396860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
397860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
398860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
399860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
400796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.SSL_use_PrivateKey(s, null);
401860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
402860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
403860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
404860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
40537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
406860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
407860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
408860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
409860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
410860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
411860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_null() throws Exception {
412860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
413860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(NULL);
414860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
415860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
416860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
417860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
418860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
419860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_no_key_no_cert() throws Exception {
420860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
421860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
422860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
423860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // neither private or certificate set
424860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
425860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
426860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
427860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
428860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
429860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
430860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
431860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
432860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
433860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
434860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_cert_then_key() throws Exception {
435860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
436860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
437860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
438860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // first certificate, then private
439860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
440860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
441860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
442860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
443860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
444860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
445860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
446860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
44737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
448860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_check_private_key(s);
449860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
450860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
451860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
452860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
453860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_check_private_key_key_then_cert() throws Exception {
454860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
455860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
456860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
457860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // first private, then certificate
45837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey().getNativeRef());
459860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
460860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
461860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_check_private_key(s);
462860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
463860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (SSLException expected) {
464860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
465860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
466860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_use_certificate(s, getServerCertificates());
467860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_check_private_key(s);
468860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
469860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
470860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
471860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
472860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
473860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_mode() throws Exception {
474860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
475860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_mode(NULL);
476860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
477860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
478860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
479860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
480860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
481860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
482860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.SSL_get_mode(s) != 0);
483860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
484860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
485860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
486860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
487860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_mode_and_clear_mode() throws Exception {
488860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
489860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_mode(NULL, 0);
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        // check SSL_MODE_HANDSHAKE_CUTTHROUGH off by default
497860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
498f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin        // check SSL_MODE_CBC_RECORD_SPLITTING off by default
499f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin        assertEquals(0, NativeCrypto.SSL_get_mode(s) & SSL_MODE_CBC_RECORD_SPLITTING);
500f087968310bb5233b76ad42841eb07e3c327f40fAlex Klyubin
501860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // set SSL_MODE_HANDSHAKE_CUTTHROUGH on
502860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
503860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_mode(s)
504860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                & SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0);
505860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off
506860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
507860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue((NativeCrypto.SSL_get_mode(s)
508860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    & SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0);
509860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
510860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
511860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
512860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
513860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
514860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_options() throws Exception {
515860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
516860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_options(NULL);
517860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
518860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
519860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
520860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
521860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
522860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
523860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.SSL_get_options(s) != 0);
524860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
525860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
526860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
527860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
528860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_options() throws Exception {
529860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
530860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_options(NULL, 0);
531860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
532860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
534860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
535860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
537f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
538f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        NativeCrypto.SSL_set_options(s, NativeConstants.SSL_OP_NO_SSLv3);
539f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) != 0);
540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_clear_options() throws Exception {
545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_clear_options(NULL, 0);
547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
553f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
554f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        NativeCrypto.SSL_set_options(s, NativeConstants.SSL_OP_NO_SSLv3);
555f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) != 0);
556f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        NativeCrypto.SSL_clear_options(s, NativeConstants.SSL_OP_NO_SSLv3);
557f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley        assertTrue((NativeCrypto.SSL_get_options(s) & NativeConstants.SSL_OP_NO_SSLv3) == 0);
558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
561860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
562860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_cipher_lists() throws Exception {
563860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(NULL, null);
5651d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro            fail("Exception not thrown for null ssl and null list");
566860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
570860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
571860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(s, null);
5741d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro            fail("Exception not thrown for null list");
575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
5781d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro        // Explicitly checking that the empty list is allowed.
5791d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro        // b/21816861
5801d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro        NativeCrypto.SSL_set_cipher_lists(s, new String[]{});
581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_cipher_lists(s, new String[] { null });
5841d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro            fail("Exception not thrown for list with null element");
585860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
586860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
587860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // see OpenSSL ciphers man page
589860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        String[] illegals = new String[] {
590860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // empty
591860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "",
592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // never standardized
593860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "EXP1024-DES-CBC-SHA", "EXP1024-RC4-SHA", "DHE-DSS-RC4-SHA",
594860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // IDEA
595860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            "IDEA-CBC-SHA", "IDEA-CBC-MD5"
596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
597860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        for (String illegal : illegals) {
599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
600860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_cipher_lists(s, new String[] { illegal });
6011d7e7b3c1d81c1d73451e20be8937da9e842ce6bSergio Giro                fail("Exception now thrown for illegal cipher: " + illegal);
602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (IllegalArgumentException expected) {
603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        List<String> ciphers
607860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                = new ArrayList<String>(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.keySet());
608860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_cipher_lists(s, ciphers.toArray(new String[ciphers.size()]));
609860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
610860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
612860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
613860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
614860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_verify() throws Exception {
615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_verify(NULL, 0);
617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
618860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
619860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
620860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
621860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
622860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
623860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
624860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
625860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
626860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_set_verify(s, (NativeCrypto.SSL_VERIFY_PEER
627860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                        | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT));
628860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
629860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
630860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
631860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
632860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final boolean DEBUG = false;
633860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
634860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class Hooks {
63501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        protected String negotiatedCipherSuite;
6361ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        private OpenSSLKey channelIdPrivateKey;
63701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        protected boolean pskEnabled;
63801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        protected byte[] pskKey;
639ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        protected List<String> enabledCipherSuites;
640860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
641767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        /**
642767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin         * @throws SSLException
643767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin         */
644860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long getContext() throws SSLException {
645860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return NativeCrypto.SSL_CTX_new();
646860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
647860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long beforeHandshake(long context) throws SSLException {
648860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(context);
649860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // without this SSL_set_cipher_lists call the tests were
650860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // negotiating DHE-RSA-AES256-SHA by default which had
651860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // very slow ephemeral RSA key generation
65201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            List<String> cipherSuites = new ArrayList<String>();
653ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin            if (enabledCipherSuites == null) {
654ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                cipherSuites.add("RC4-MD5");
655ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                if (pskEnabled) {
656ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                    // In TLS-PSK the client indicates that PSK key exchange is desired by offering
657ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                    // at least one PSK cipher suite.
658ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                    cipherSuites.add(0, "PSK-AES128-CBC-SHA");
659ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                }
660ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin            } else {
661ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin                cipherSuites.addAll(enabledCipherSuites);
66201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
66301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            NativeCrypto.SSL_set_cipher_lists(
66401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    s, cipherSuites.toArray(new String[cipherSuites.size()]));
665860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
666860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (channelIdPrivateKey != null) {
66737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.SSL_set1_tls_channel_id(s, channelIdPrivateKey.getNativeRef());
668860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
669860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return s;
670860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
67101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public void configureCallbacks(
67201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                @SuppressWarnings("unused") TestSSLHandshakeCallbacks callbacks) {}
673767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        public void clientCertificateRequested(@SuppressWarnings("unused") long s) {}
674860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void afterHandshake(long session, long ssl, long context,
675860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   Socket socket, FileDescriptor fd,
676860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   SSLHandshakeCallbacks callback)
677860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
678860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (session != NULL) {
67901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                negotiatedCipherSuite = NativeCrypto.SSL_SESSION_cipher(session);
680860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_SESSION_free(session);
681860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
682860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (ssl != NULL) {
683860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
684860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_shutdown(ssl, fd, callback);
685860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } catch (IOException e) {
686860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
687860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_free(ssl);
688860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
689860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (context != NULL) {
690860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_free(context);
691860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
692860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (socket != null) {
693860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                socket.close();
694860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
695860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
696860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
697860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
698860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks {
699860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final Socket socket;
700860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final long sslNativePointer;
701860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private final Hooks hooks;
702860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
703860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public TestSSLHandshakeCallbacks(Socket socket,
704860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                         long sslNativePointer,
705860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                         Hooks hooks) {
706860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.socket = socket;
707860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.sslNativePointer = sslNativePointer;
708860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.hooks = hooks;
709860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
710860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
7110e9746b7b132058651155b33f219c7789997985bKenny Root        public long[] certificateChainRefs;
712860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public String authMethod;
713860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean verifyCertificateChainCalled;
714860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
715767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        @Override
716d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root        public void verifyCertificateChain(long sslSessionNativePtr, long[] certChainRefs,
717d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                String authMethod) throws CertificateException {
718860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
719860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
720860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " verifyCertificateChain"
721d2cced8b10f5e4f600a5eb9464eba0da7c8f09deKenny Root                                   + " sessionPtr=0x" + Long.toString(sslSessionNativePtr, 16)
722860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " asn1DerEncodedCertificateChain="
7230e9746b7b132058651155b33f219c7789997985bKenny Root                                   + Arrays.toString(certChainRefs)
724860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " authMethod=" + authMethod);
725860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
7260e9746b7b132058651155b33f219c7789997985bKenny Root            this.certificateChainRefs = certChainRefs;
727860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.authMethod = authMethod;
728860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.verifyCertificateChainCalled = true;
729860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
730860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
731860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public byte[] keyTypes;
732860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public byte[][] asn1DerEncodedX500Principals;
733860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean clientCertificateRequestedCalled;
734767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin
735767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        @Override
736860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void clientCertificateRequested(byte[] keyTypes,
737860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               byte[][] asn1DerEncodedX500Principals) {
738860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
739860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
740860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " clientCertificateRequested"
741860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " keyTypes=" + keyTypes
742860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + " asn1DerEncodedX500Principals="
743860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   + asn1DerEncodedX500Principals);
744860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
745860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.keyTypes = keyTypes;
746860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.asn1DerEncodedX500Principals = asn1DerEncodedX500Principals;
747860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.clientCertificateRequestedCalled = true;
748860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (hooks != null ) {
749860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                hooks.clientCertificateRequested(sslNativePointer);
750860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
751860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
752860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
753860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public boolean handshakeCompletedCalled;
754f878e438660d93f8689b864165230492e7a412d4Kenny Root
755767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        @Override
756f878e438660d93f8689b864165230492e7a412d4Kenny Root        public void onSSLStateChange(long sslSessionNativePtr, int type, int val) {
757860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (DEBUG) {
758860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
759f878e438660d93f8689b864165230492e7a412d4Kenny Root                                   + " onSSLStateChange");
760860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
761860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.handshakeCompletedCalled = true;
762860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
763860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
764860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public Socket getSocket() {
765860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return socket;
766860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
76701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
76801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private boolean clientPSKKeyRequestedInvoked;
76901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private String clientPSKKeyRequestedIdentityHint;
77001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private int clientPSKKeyRequestedResult;
77101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private byte[] clientPSKKeyRequestedResultKey;
77201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private byte[] clientPSKKeyRequestedResultIdentity;
77301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
77401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        @Override
77501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) {
77601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (DEBUG) {
77701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
77801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " clientPSKKeyRequested"
77901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " identityHint=" + identityHint
78001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " identity capacity=" + identity.length
78101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " key capacity=" + key.length);
78201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
78301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            clientPSKKeyRequestedInvoked = true;
78401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            clientPSKKeyRequestedIdentityHint = identityHint;
78501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (clientPSKKeyRequestedResultKey != null) {
78601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                System.arraycopy(
78701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        clientPSKKeyRequestedResultKey, 0,
78801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        key, 0,
78901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        clientPSKKeyRequestedResultKey.length);
79001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
79101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (clientPSKKeyRequestedResultIdentity != null) {
79201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                System.arraycopy(
79301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        clientPSKKeyRequestedResultIdentity, 0,
79401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        identity, 0,
79501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        Math.min(clientPSKKeyRequestedResultIdentity.length, identity.length));
79601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
79701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            return clientPSKKeyRequestedResult;
79801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
79901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
80001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private boolean serverPSKKeyRequestedInvoked;
80101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private int serverPSKKeyRequestedResult;
80201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private byte[] serverPSKKeyRequestedResultKey;
80301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private String serverPSKKeyRequestedIdentityHint;
80401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        private String serverPSKKeyRequestedIdentity;
80501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        @Override
80601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) {
80701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (DEBUG) {
80801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                System.out.println("ssl=0x" + Long.toString(sslNativePointer, 16)
80901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " serverPSKKeyRequested"
81001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " identityHint=" + identityHint
81101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " identity=" + identity
81201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                                   + " key capacity=" + key.length);
81301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
81401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            serverPSKKeyRequestedInvoked = true;
81501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            serverPSKKeyRequestedIdentityHint = identityHint;
81601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            serverPSKKeyRequestedIdentity = identity;
81701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (serverPSKKeyRequestedResultKey != null) {
81801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                System.arraycopy(
81901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        serverPSKKeyRequestedResultKey, 0,
82001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        key, 0,
82101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        serverPSKKeyRequestedResultKey.length);
82201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
82301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            return serverPSKKeyRequestedResult;
82401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
82501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
82601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
82701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public static class ClientHooks extends Hooks {
82801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        protected String pskIdentity;
82901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
83001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        @Override
83101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
83201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            super.configureCallbacks(callbacks);
83301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (pskEnabled) {
83401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                if (pskIdentity != null) {
83501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    // Create a NULL-terminated modified UTF-8 representation of pskIdentity.
83601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    byte[] b;
83701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    try {
83801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        b = pskIdentity.getBytes("UTF-8");
83901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    } catch (UnsupportedEncodingException e) {
84001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                        throw new RuntimeException("UTF-8 encoding not supported", e);
84101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    }
84201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    callbacks.clientPSKKeyRequestedResultIdentity =
84301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                            Arrays.copyOf(b, b.length + 1);
84401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                }
84501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                callbacks.clientPSKKeyRequestedResultKey = pskKey;
84601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                callbacks.clientPSKKeyRequestedResult = (pskKey != null) ? pskKey.length : 0;
84701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
84801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
84901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
85001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        @Override
85101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public long beforeHandshake(long c) throws SSLException {
85201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            long s = super.beforeHandshake(c);
85301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (pskEnabled) {
85401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                NativeCrypto.set_SSL_psk_client_callback_enabled(s, true);
85501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
85601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            return s;
85701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
858860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
859860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
860860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static class ServerHooks extends Hooks {
8611ecc0481f90d32b89b3b051cad70efe07468acd0Kenny Root        private final OpenSSLKey privateKey;
8620e9746b7b132058651155b33f219c7789997985bKenny Root        private final long[] certificates;
863860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private boolean channelIdEnabled;
864860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private byte[] channelIdAfterHandshake;
865860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        private Throwable channelIdAfterHandshakeException;
866860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
86701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        protected String pskIdentityHint;
86801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
86901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public ServerHooks() {
87001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            this(null, null);
87101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
87201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
8730e9746b7b132058651155b33f219c7789997985bKenny Root        public ServerHooks(OpenSSLKey privateKey, long[] certificates) {
874860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.privateKey = privateKey;
875860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            this.certificates = certificates;
876860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
877860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
878860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        @Override
879860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public long beforeHandshake(long c) throws SSLException {
880860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = super.beforeHandshake(c);
881860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (privateKey != null) {
88237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.SSL_use_PrivateKey(s, privateKey.getNativeRef());
883860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
884860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (certificates != null) {
885860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_use_certificate(s, certificates);
886860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
887860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (channelIdEnabled) {
888860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_enable_tls_channel_id(s);
889860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
89001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (pskEnabled) {
89101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                NativeCrypto.set_SSL_psk_server_callback_enabled(s, true);
89201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                NativeCrypto.SSL_use_psk_identity_hint(s, pskIdentityHint);
89301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
894a132fc92896da9372f9a34ab1d6dca52c467d2f6Kenny Root            NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE);
895860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            return s;
896860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
897860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
898860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        @Override
89901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
90001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            super.configureCallbacks(callbacks);
90101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            if (pskEnabled) {
90201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                callbacks.serverPSKKeyRequestedResultKey = pskKey;
90301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                callbacks.serverPSKKeyRequestedResult = (pskKey != null) ? pskKey.length : 0;
90401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
90501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
90601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
90701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        @Override
908860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void afterHandshake(long session, long ssl, long context,
909860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   Socket socket, FileDescriptor fd,
910860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                   SSLHandshakeCallbacks callback)
911860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
912860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          if (channelIdEnabled) {
913860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
914860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root              channelIdAfterHandshake = NativeCrypto.SSL_get_tls_channel_id(ssl);
915860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (Exception e) {
916860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root              channelIdAfterHandshakeException = e;
917860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
918860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          }
919860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root          super.afterHandshake(session, ssl, context, socket, fd, callback);
920860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
921860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
922767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin        @Override
923860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        public void clientCertificateRequested(long s) {
924860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Server asked for client certificates");
925860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
926860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
927860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
928860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener,
9296fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            final int timeout, final boolean client, final Hooks hooks, final byte[] npnProtocols,
9306fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            final byte[] alpnProtocols) {
931860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ExecutorService executor = Executors.newSingleThreadExecutor();
932860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> future = executor.submit(
933860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                new Callable<TestSSLHandshakeCallbacks>() {
934860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public TestSSLHandshakeCallbacks call() throws Exception {
935767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin                @SuppressWarnings("resource") // Socket needs to remain open after the handshake
936860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Socket socket = (client
937860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 ? new Socket(listener.getInetAddress(),
938860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                              listener.getLocalPort())
939860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 : listener.accept());
940860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (timeout == -1) {
941860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return new TestSSLHandshakeCallbacks(socket, 0, null);
942860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
943860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                FileDescriptor fd = socket.getFileDescriptor$();
944860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long c = hooks.getContext();
945860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = hooks.beforeHandshake(c);
946860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                TestSSLHandshakeCallbacks callback
947860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        = new TestSSLHandshakeCallbacks(socket, s, hooks);
94801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                hooks.configureCallbacks(callback);
949860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                if (DEBUG) {
950860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    System.out.println("ssl=0x" + Long.toString(s, 16)
951860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " handshake"
952860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " context=0x" + Long.toString(c, 16)
953860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " socket=" + socket
954860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " fd=" + fd
955860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " timeout=" + timeout
956860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       + " client=" + client);
957860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
958860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long session = NULL;
959860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
960860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    session = NativeCrypto.SSL_do_handshake(s, fd, callback, timeout, client,
9616fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                                                            npnProtocols, alpnProtocols);
962860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    if (DEBUG) {
963860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        System.out.println("ssl=0x" + Long.toString(s, 16)
964860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           + " handshake"
965860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           + " session=0x" + Long.toString(session, 16));
966860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
967860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } finally {
968860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    // Ensure afterHandshake is called to free resources
969860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    hooks.afterHandshake(session, s, c, socket, fd, callback);
970860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
971860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return callback;
972860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
973860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        });
974860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        executor.shutdown();
975860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        return future;
976860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
977860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
978860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_NULL_SSL() throws Exception {
979860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
9806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false, null, null);
981860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
982860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
983860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
984860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
985860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
986860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_null_args() throws Exception {
987860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
988860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
989860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
990860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
9916fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(s, null, null, 0, true, null, null);
992860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
993860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
994860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
995860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
996860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
9976fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true, null, null);
998860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
999860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1000860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1001860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1002860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
1003860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
1004860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1005860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1006860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_normal() throws Exception {
1007860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal client and server case
1008860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1009860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1010860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
10116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
10126fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1013860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1014860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1015860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1016860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
10170e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1018860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
1019860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1020860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1021860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
102201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
102301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
102401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
102501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
1026860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1027860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1028860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1029860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1030860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_optional_client_certificate() throws Exception {
1031860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // optional client certificate case
1032860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1033860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1034860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1035860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1036860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void clientCertificateRequested(long s) {
1037860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.clientCertificateRequested(s);
103837e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey().getNativeRef());
1039860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_use_certificate(s, getClientCertificates());
1040860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1041860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1042860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1043860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1044860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long c) throws SSLException {
1045860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(c);
1046860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
1047860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
1048860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
1049860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1050860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
10516fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
10526fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1053860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1054860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1055860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1056860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
10570e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1058860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", clientCallback.authMethod);
1059860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.verifyCertificateChainCalled);
1060860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getClientCertificates(),
10610e9746b7b132058651155b33f219c7789997985bKenny Root                serverCallback.certificateChainRefs);
1062860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals("RSA", serverCallback.authMethod);
1063860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1064860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.clientCertificateRequestedCalled);
1065860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNotNull(clientCallback.keyTypes);
1066e53baea9221be7f9828d0f338ede284e22f55722Alex Klyubin        assertEquals(new HashSet<String>(Arrays.asList("EC", "RSA")),
1067b9bfe69f1c205ab67a03e10a01e2cc90871a0879Alex Klyubin                SSLParametersImpl.getSupportedClientKeyTypes(clientCallback.keyTypes));
1068860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualPrincipals(getCaPrincipals(),
1069860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                              clientCallback.asn1DerEncodedX500Principals);
1070860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
1071860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
107201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
107301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
107401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
107501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
107601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
1077860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1078860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1079860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1080860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1081860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_missing_required_certificate() throws Exception {
1082860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // required client certificate negative case
1083860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1084860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1085860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1086860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1087860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1088860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
1089860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
1090860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals());
1091860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_verify(s,
1092860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                NativeCrypto.SSL_VERIFY_PEER
1093860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT);
1094860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
1095860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1096860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1097767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin            @SuppressWarnings("unused")
10986fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
10996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
11006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
11016fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1102860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1108860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1109860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /**
1110860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Usually if a RuntimeException is thrown by the
1111860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * clientCertificateRequestedCalled callback, the caller sees it
1112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * during the call to NativeCrypto_SSL_do_handshake.  However, IIS
1113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * does not request client certs until after the initial
1114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * handshake. It does an SSL renegotiation, which means we need to
1115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * be able to deliver the callback's exception in cases like
1116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * SSL_read, SSL_write, and SSL_shutdown.
1117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
1118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate()
1119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            throws Exception {
1120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long context) throws SSLException {
1125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(context);
1126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_clear_mode(s, SSL_MODE_HANDSHAKE_CUTTHROUGH);
1127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
1128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1131860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
1135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1136860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1137860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1138860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1139860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void clientCertificateRequested(long s) {
1140860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.clientCertificateRequested(s);
1141860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throw new RuntimeException("expected");
1142860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                try {
1151860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER);
1152860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_options(
1153f79c90d56464e254ce8645f886ec0ca47573ced1Adam Langley                            s, NativeConstants.SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION);
1154860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_renegotiate(s);
1155860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1,
1156860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           (int) ((TIMEOUT_SECONDS * 1000) / 2));
1157860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } catch (IOException expected) {
1158860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                } finally {
1159860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
1160860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1161860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1162860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
11636fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
11646fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException e) {
1168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (!"expected".equals(e.getCause().getMessage())) {
1169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throw e;
1170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_client_timeout() throws Exception {
1176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // client timeout
1177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Socket serverSocket = null;
1179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
11826fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks, null,
11836fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
11846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks, null,
11856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            serverSocket = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
1187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            if (SocketTimeoutException.class != expected.getCause().getClass()) {
1191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                expected.printStackTrace();
1192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
1194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
1195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // Manually close peer socket when testing timeout
1196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            IoUtils.closeQuietly(serverSocket);
1197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1198860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1200860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_server_timeout() throws Exception {
1201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // server timeout
1202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Socket clientSocket = null;
1204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
12076fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks, null, null);
12086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks, null, null);
1209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            clientSocket = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS).getSocket();
1210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1212860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
1213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
1214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
1215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // Manually close peer socket when testing timeout
1216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            IoUtils.closeQuietly(clientSocket);
1217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_normal() throws Exception {
1221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Normal handshake with TLS Channel ID.
1224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
1227ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        // TLS Channel ID currently requires ECDHE-based key exchanges.
1228ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
1229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = true;
1231ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
12326fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
12336fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1236860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
12380e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1239ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        assertEquals("ECDHE_RSA", clientCallback.authMethod);
1240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1241860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1242860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
124301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
124401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
124501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
124601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
1247860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1248860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1249860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1250860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualByteArrays(CHANNEL_ID, sHooks.channelIdAfterHandshake);
1251860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1253860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_not_supported_by_server() throws Exception {
1254860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1255860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1256860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Client tries to use TLS Channel ID but the server does not enable/offer the extension.
1257860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1258860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1259860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = CHANNEL_ID_PRIVATE_KEY;
1260ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        // TLS Channel ID currently requires ECDHE-based key exchanges.
1261ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
1262860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1263860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = false;
1264ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
12656fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
12666fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1267860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1268860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1269860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1270860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
12710e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1272ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        assertEquals("ECDHE_RSA", clientCallback.authMethod);
1273860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1274860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1275860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
127601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
127701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
127801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
127901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
1280860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1281860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1282860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1283860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshake);
1284860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1285860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1286860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_do_handshake_with_channel_id_not_enabled_by_client() throws Exception {
1287860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        initChannelIdKey();
1288860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1289860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Client does not use TLS Channel ID when the server has the extension enabled/offered.
1290860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1291860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks();
1292860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        cHooks.channelIdPrivateKey = null;
1293ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        // TLS Channel ID currently requires ECDHE-based key exchanges.
1294ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        cHooks.enabledCipherSuites = Arrays.asList(new String[] {"ECDHE-RSA-AES128-SHA"});
1295860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerHooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
1296860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        sHooks.channelIdEnabled = true;
1297ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        sHooks.enabledCipherSuites = cHooks.enabledCipherSuites;
12986fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
12996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1300860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1301860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1302860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.verifyCertificateChainCalled);
1303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEqualCertificateChains(getServerCertificates(),
13040e9746b7b132058651155b33f219c7789997985bKenny Root                                     clientCallback.certificateChainRefs);
1305ea7cf2a1bacb8293947ad5168bc41bdb39e6a3f0Alex Klyubin        assertEquals("ECDHE_RSA", clientCallback.authMethod);
1306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.verifyCertificateChainCalled);
1307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(clientCallback.clientCertificateRequestedCalled);
1308860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse(serverCallback.clientCertificateRequestedCalled);
130901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientPSKKeyRequestedInvoked);
131001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
131101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
131201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.serverPSKKeyRequestedInvoked);
1313860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(clientCallback.handshakeCompletedCalled);
1314860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(serverCallback.handshakeCompletedCalled);
1315860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshakeException);
1316860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(sHooks.channelIdAfterHandshake);
1317860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
131901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_normal() throws Exception {
132001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        // normal TLS-PSK client and server case
132101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
132201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Hooks cHooks = new ClientHooks();
132301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
132401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
132501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
132601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
132701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = cHooks.pskKey;
132801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
132901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
133001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
133101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
133201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
133301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.verifyCertificateChainCalled);
133401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.verifyCertificateChainCalled);
133501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientCertificateRequestedCalled);
133601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientCertificateRequestedCalled);
133701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.handshakeCompletedCalled);
133801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.handshakeCompletedCalled);
133901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
134001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
134101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
134201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
134301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertContains(cHooks.negotiatedCipherSuite, "PSK");
134401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
134501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertNull(clientCallback.clientPSKKeyRequestedIdentityHint);
134601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertNull(serverCallback.serverPSKKeyRequestedIdentityHint);
134701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals("", serverCallback.serverPSKKeyRequestedIdentity);
134801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
134901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
135001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_with_identity_and_hint() throws Exception {
135101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        // normal TLS-PSK client and server case where the server provides the client with a PSK
135201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        // identity hint, and the client provides the server with a PSK identity.
135301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
135401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks();
135501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
135601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
135701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
135801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
135901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = cHooks.pskKey;
136001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskIdentityHint = "Some non-ASCII characters: \u00c4\u0332";
136101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskIdentity = "More non-ASCII characters: \u00f5\u044b";
136201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
136301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
136401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
136501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
136601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
136701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.verifyCertificateChainCalled);
136801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.verifyCertificateChainCalled);
136901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientCertificateRequestedCalled);
137001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientCertificateRequestedCalled);
137101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.handshakeCompletedCalled);
137201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.handshakeCompletedCalled);
137301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
137401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
137501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
137601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
137701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertContains(cHooks.negotiatedCipherSuite, "PSK");
137801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
137901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(sHooks.pskIdentityHint, clientCallback.clientPSKKeyRequestedIdentityHint);
138001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(sHooks.pskIdentityHint, serverCallback.serverPSKKeyRequestedIdentityHint);
138101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(cHooks.pskIdentity, serverCallback.serverPSKKeyRequestedIdentity);
138201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
138301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
138401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_with_identity_and_hint_of_max_length()
138501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            throws Exception {
138601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        // normal TLS-PSK client and server case where the server provides the client with a PSK
138701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        // identity hint, and the client provides the server with a PSK identity.
138801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
138901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks();
139001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
139101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
139201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
139301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
139401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = cHooks.pskKey;
139501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskIdentityHint = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
139601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx";
139701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskIdentity = "123456789012345678901234567890123456789012345678901234567890"
139801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                + "12345678901234567890123456789012345678901234567890123456789012345678";
139901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES, sHooks.pskIdentityHint.length());
140001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(PSKKeyManager.MAX_IDENTITY_LENGTH_BYTES, cHooks.pskIdentity.length());
140101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
140201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
140301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
140401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
140501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
140601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.verifyCertificateChainCalled);
140701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.verifyCertificateChainCalled);
140801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.clientCertificateRequestedCalled);
140901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientCertificateRequestedCalled);
141001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.handshakeCompletedCalled);
141101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.handshakeCompletedCalled);
141201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(clientCallback.clientPSKKeyRequestedInvoked);
141301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(clientCallback.serverPSKKeyRequestedInvoked);
141401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertFalse(serverCallback.clientPSKKeyRequestedInvoked);
141501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertTrue(serverCallback.serverPSKKeyRequestedInvoked);
141601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertContains(cHooks.negotiatedCipherSuite, "PSK");
141701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(cHooks.negotiatedCipherSuite, sHooks.negotiatedCipherSuite);
141801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(sHooks.pskIdentityHint, clientCallback.clientPSKKeyRequestedIdentityHint);
141901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(sHooks.pskIdentityHint, serverCallback.serverPSKKeyRequestedIdentityHint);
142001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        assertEquals(cHooks.pskIdentity, serverCallback.serverPSKKeyRequestedIdentity);
142101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
142201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
142301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_key_mismatch() throws Exception {
142401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
142501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks();
142601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
142701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
142801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
142901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
143001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = "1, 2, 3, 3, Testing...".getBytes("UTF-8");
143101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
143201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
143301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
143401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        try {
143501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
143601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
143701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            fail();
143801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        } catch (ExecutionException expected) {
143901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
144001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
144101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
144201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
144301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_with_no_client_key() throws Exception {
144401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
144501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks();
144601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
144701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
144801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
144901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = null;
145001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
145101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
145201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
145301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
145401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        try {
145501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
145601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
145701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            fail();
145801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        } catch (ExecutionException expected) {
145901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
146001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
146101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
146201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
146301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_with_no_server_key() throws Exception {
146401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
146501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks();
146601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
146701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
146801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
146901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
147001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = null;
147101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
147201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
147301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
147401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        try {
147501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
147601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
147701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            fail();
147801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        } catch (ExecutionException expected) {
147901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
148001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
148101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
148201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
148301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_do_handshake_with_psk_key_too_long() throws Exception {
148401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        final ServerSocket listener = new ServerSocket(0);
148501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ClientHooks cHooks = new ClientHooks() {
148601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            @Override
148701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            public void configureCallbacks(TestSSLHandshakeCallbacks callbacks) {
148801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                super.configureCallbacks(callbacks);
148901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                callbacks.clientPSKKeyRequestedResult = PSKKeyManager.MAX_KEY_LENGTH_BYTES + 1;
149001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
149101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        };
149201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        ServerHooks sHooks = new ServerHooks();
149301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskEnabled = true;
149401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskEnabled = true;
149501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        cHooks.pskKey = "1, 2, 3, 4, Testing...".getBytes("UTF-8");
149601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        sHooks.pskKey = cHooks.pskKey;
149701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
149801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        Future<TestSSLHandshakeCallbacks> server =
149901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                handshake(listener, 0, false, sHooks, null, null);
150001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        try {
150101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
150201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
150301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            fail();
150401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        } catch (ExecutionException expected) {
150501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            assertEquals(SSLProtocolException.class, expected.getCause().getClass());
150601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
150701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
150801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
150901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    public void test_SSL_use_psk_identity_hint() throws Exception {
151001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        long c = NativeCrypto.SSL_CTX_new();
151101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        long s = NativeCrypto.SSL_new(c);
151201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        try {
151301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            NativeCrypto.SSL_use_psk_identity_hint(s, null);
151401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            NativeCrypto.SSL_use_psk_identity_hint(s, "test");
151501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
151601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            try {
151701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                // 800 characters is much longer than the permitted maximum.
151801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                StringBuilder pskIdentityHint = new StringBuilder();
151901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                for (int i = 0; i < 160; i++) {
152001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                    pskIdentityHint.append(" long");
152101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                }
152201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                assertTrue(pskIdentityHint.length() > PSKKeyManager.MAX_IDENTITY_HINT_LENGTH_BYTES);
152301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                NativeCrypto.SSL_use_psk_identity_hint(s, pskIdentityHint.toString());
152401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin                fail();
152501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            } catch (SSLException expected) {
152601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            }
152701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        } finally {
152801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            NativeCrypto.SSL_free(s);
152901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            NativeCrypto.SSL_CTX_free(c);
153001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
153101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
153201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
1533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_session() throws Exception {
1534860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1535860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session(NULL, NULL);
1536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1537860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1538860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1539860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session(s, NULL);
1544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long clientContext = NativeCrypto.SSL_CTX_new();
1550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long serverContext = NativeCrypto.SSL_CTX_new();
1551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final ServerSocket listener = new ServerSocket(0);
1552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long[] clientSession = new long[] { NULL };
1553860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            final long[] serverSession = new long[] { NULL };
1554860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            {
1555860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks cHooks = new Hooks() {
1556860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1557860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return clientContext;
1559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1561860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1562860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1563860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1565860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1566860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        clientSession[0] = session;
1567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1570860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1571860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return serverContext;
1573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1574860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1578860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1579860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1580860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        serverSession[0] = session;
1581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> client
15846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, true, cHooks, null, null);
1585860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> server
15866fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, false, sHooks, null, null);
1587860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1589860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1590860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEqualSessions(clientSession[0], serverSession[0]);
1591860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            {
1592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks cHooks = new Hooks() {
1593860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1594860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1595860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return clientContext;
1596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1597860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long beforeHandshake(long c) throws SSLException {
1599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        long s = NativeCrypto.SSL_new(clientContext);
1600860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        NativeCrypto.SSL_set_session(s, clientSession[0]);
1601860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return s;
1602860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1607860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1608860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEqualSessions(clientSession[0], session);
1609860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1610860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1612860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1613860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1614860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public long getContext() throws SSLException {
1615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        return serverContext;
1616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    @Override
1618860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void afterHandshake(long session, long s, long c,
1619860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               Socket sock, FileDescriptor fd,
1620860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                               SSLHandshakeCallbacks callback)
1621860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            throws Exception {
1622860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEqualSessions(serverSession[0], session);
1623860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        super.afterHandshake(NULL, s, NULL, sock, fd, callback);
1624860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
1625860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                };
1626860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> client
16276fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, true, cHooks, null, null);
1628860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Future<TestSSLHandshakeCallbacks> server
16296fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        = handshake(listener, 0, false, sHooks, null, null);
1630860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1631860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1632860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1633860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(clientSession[0]);
1634860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(serverSession[0]);
1635860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(serverContext);
1636860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(clientContext);
1637860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1638860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1639860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1640860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_session_creation_enabled() throws Exception {
1641860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1642860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(NULL, false);
1643860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1644860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1645860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1646860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1647860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1648860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1649860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1650860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(s, false);
1651860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_session_creation_enabled(s, true);
1652860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1653860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1654860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1655860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1656860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1657860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1658860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // negative test case for SSL_set_session_creation_enabled(false) on client
1659efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root        {
1660860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
1661860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1662860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
1663860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
1664860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_session_creation_enabled(s, false);
1665860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
1666860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1667860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
1668860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
16696fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
16706fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1671767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin            @SuppressWarnings("unused")
16726fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
16736fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1674efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            try {
1675efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1676efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                fail();
1677efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            } catch (ExecutionException expected) {
1678efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1679efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            }
1680efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            try {
1681efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1682efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                fail();
1683efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            } catch (ExecutionException expected) {
1684efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1685efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            }
1686860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1687860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1688860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // negative test case for SSL_set_session_creation_enabled(false) on server
1689efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root        {
1690860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks();
1691860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1692860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
1693860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public long beforeHandshake(long c) throws SSLException {
1694860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long s = super.beforeHandshake(c);
1695860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_set_session_creation_enabled(s, false);
1696860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    return s;
1697860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
1698860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
16996fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
17006fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1701767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin            @SuppressWarnings("unused")
17026fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
17036fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
1704efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            try {
1705efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1706efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                fail();
1707efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            } catch (ExecutionException expected) {
1708efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                assertEquals(SSLHandshakeException.class, expected.getCause().getClass());
1709efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            }
1710efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            try {
1711efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1712efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                fail();
1713efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            } catch (ExecutionException expected) {
1714efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root                assertEquals(SSLProtocolException.class, expected.getCause().getClass());
1715efe5c66651fcd9b342d781cdfc02a1069a86e210Kenny Root            }
1716860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1717860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1718860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1719860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_set_tlsext_host_name() throws Exception {
1720860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL SSL
1721860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1722860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_tlsext_host_name(NULL, null);
1723860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1724860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1725860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1726860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1727860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final String hostname = "www.android.com";
1728860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1729860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
1730860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
1731860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
1732860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1733860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // null hostname
1734860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1735860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, null);
1736860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1737860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
1738860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1739860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1740860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            // too long hostname
1741860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
1742860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                char[] longHostname = new char[256];
1743860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                Arrays.fill(longHostname, 'w');
1744860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, new String(longHostname));
1745860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
1746860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
1747860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1748860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1749860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertNull(NativeCrypto.SSL_get_servername(s));
1750860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_set_tlsext_host_name(s, new String(hostname));
1751860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
1752860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1753860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
1754860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
1755860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1756860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1757860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1758860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1759860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal
1760860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1761860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1762860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public long beforeHandshake(long c) throws SSLException {
1763860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long s = super.beforeHandshake(c);
1764860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_set_tlsext_host_name(s, hostname);
1765860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return s;
1766860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1767860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1768860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1769860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1770860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1771860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1772860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1773860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1774860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(hostname, NativeCrypto.SSL_get_servername(s));
1775860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1776860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1777860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
17786fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
17796fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1780860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1781860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1782860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1783860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1784860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_NpnNegotiateSuccess() throws Exception {
1785860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] clientNpnProtocols = new byte[] {
1786860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                8, 'h', 't', 't', 'p', '/', '1', '.', '1',
1787860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'f', 'o', 'o',
1788860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
1789860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1790860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final byte[] serverNpnProtocols = new byte[] {
1791860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
1792860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'f', 'o', 'o',
1793860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                3, 'b', 'a', 'r',
1794860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1795860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1796860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1797860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
1798860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_enable_npn(context);
1799860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return super.beforeHandshake(context);
1800860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1801860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
1802860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
1803860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
1804860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("spdy/2", new String(negotiated));
1805860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue("NPN should enable cutthrough on the client",
1806860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        0 != (NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH));
180768a3f229cd71c1367173ebc31e5363293b9b5dbcKenny Root                NativeCrypto.SSL_write(ssl, fd, callback, new byte[] { 42 }, 0, 1,
180868a3f229cd71c1367173ebc31e5363293b9b5dbcKenny Root                        (int) ((TIMEOUT_SECONDS * 1000) / 2));
1809860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, ssl, context, socket, fd, callback);
1810860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1811860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1812860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1813860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
1814860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_CTX_enable_npn(context);
1815860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                return super.beforeHandshake(context);
1816860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1817860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
1818860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
1819860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] negotiated = NativeCrypto.SSL_get_npn_negotiated_protocol(ssl);
1820860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("spdy/2", new String(negotiated));
1821860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals("NPN should not enable cutthrough on the server",
1822860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
182368a3f229cd71c1367173ebc31e5363293b9b5dbcKenny Root                byte[] buffer = new byte[1];
182468a3f229cd71c1367173ebc31e5363293b9b5dbcKenny Root                NativeCrypto.SSL_read(ssl, fd, callback, buffer, 0, 1, 0);
182568a3f229cd71c1367173ebc31e5363293b9b5dbcKenny Root                assertEquals(42, buffer[0]);
1826860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, ssl, c, sock, fd, callback);
1827860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1828860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1829860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1830860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ServerSocket listener = new ServerSocket(0);
1831860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> client
18326fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, true, cHooks, clientNpnProtocols, null);
1833860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Future<TestSSLHandshakeCallbacks> server
18346fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, false, sHooks, serverNpnProtocols, null);
18356fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
18366fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
18376fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    }
18386fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
18396fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root    public void test_SSL_AlpnNegotiateSuccess() throws Exception {
18406fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        final byte[] clientAlpnProtocols = new byte[] {
18416fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                8, 'h', 't', 't', 'p', '/', '1', '.', '1',
18426fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'f', 'o', 'o',
18436fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
18446fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
18456fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        final byte[] serverAlpnProtocols = new byte[] {
18466fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                6, 's', 'p', 'd', 'y', '/', '2',
18476fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'f', 'o', 'o',
18486fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                3, 'b', 'a', 'r',
18496fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
18506fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
18516fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Hooks cHooks = new Hooks() {
18526fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public long beforeHandshake(long context) throws SSLException {
1853f8a9b546d57c4731805e73e1e96ff2fb3e77d6e0Kenny Root                long sslContext = super.beforeHandshake(context);
1854f8a9b546d57c4731805e73e1e96ff2fb3e77d6e0Kenny Root                NativeCrypto.SSL_set_alpn_protos(sslContext, clientAlpnProtocols);
1855f8a9b546d57c4731805e73e1e96ff2fb3e77d6e0Kenny Root                return sslContext;
18566fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
18576fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public void afterHandshake(long session, long ssl, long context, Socket socket,
18586fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
18596fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
18606fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("spdy/2", new String(negotiated));
18616fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                /*
18626fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 * There is no callback on the client, so we can't enable
18636fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 * cut-through
18646fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                 */
18656fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("ALPN should not enable cutthrough on the client", 0,
18666fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
18676fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                super.afterHandshake(session, ssl, context, socket, fd, callback);
18686fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
18696fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
18706fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
18716fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            @Override public void afterHandshake(long session, long ssl, long c, Socket sock,
18726fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    FileDescriptor fd, SSLHandshakeCallbacks callback) throws Exception {
18736fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                byte[] negotiated = NativeCrypto.SSL_get0_alpn_selected(ssl);
18746fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("spdy/2", new String(negotiated));
18756fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                assertEquals("ALPN should not enable cutthrough on the server",
18766fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                        0, NativeCrypto.SSL_get_mode(ssl) & SSL_MODE_HANDSHAKE_CUTTHROUGH);
18776fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                super.afterHandshake(session, ssl, c, sock, fd, callback);
18786fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            }
18796fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        };
18806fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root
18816fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        ServerSocket listener = new ServerSocket(0);
18826fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client
18836fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, true, cHooks, null, null);
18846fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server
18856fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                = handshake(listener, 0, false, sHooks, null, serverAlpnProtocols);
1886860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1887860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1888860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1889860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1890860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_servername_null() throws Exception {
1891860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL SSL
1892860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1893860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_servername(NULL);
1894860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1895860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1896860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1897860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1898860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
1899860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long s = NativeCrypto.SSL_new(c);
1900860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertNull(NativeCrypto.SSL_get_servername(s));
1901860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(s);
1902860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
1903860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1904860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing by test_SSL_set_tlsext_host_name
1905860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1906860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1907860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_renegotiate() throws Exception {
1908860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1909860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_renegotiate(NULL);
1910860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1911860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1912860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1913860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1914860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1915860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1916860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1917860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1918860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1919860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1920860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1921860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] buffer = new byte[1];
1922860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, buffer, 0, 1, 0);
1923860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(42, buffer[0]);
1924860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1925860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1926860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1927860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1928860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1929860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1930860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1931860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1932860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
1933860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_renegotiate(s);
1934860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1, 0);
1935860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1936860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1937860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
19386fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
19396fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1940860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1941860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1942860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1943860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1944860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_certificate() throws Exception {
1945860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1946860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_certificate(NULL);
1947860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1948860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1949860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1950860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1951860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1952860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1953860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1954860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1955860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1956860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1957860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                throws Exception {
1958860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNull(NativeCrypto.SSL_get_certificate(s));
1959860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1960860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1961860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
1962860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
1963860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1964860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1965860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1966860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1967860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
1968860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEqualCertificateChains(
1969860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                             getServerCertificates(),
1970860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                             NativeCrypto.SSL_get_certificate(s));
1971860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
1972860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
1973860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
19746fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
19756fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
1976860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1977860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
1978860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
1979860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1980860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_get_peer_cert_chain() throws Exception {
1981860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
1982860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_get_peer_cert_chain(NULL);
1983860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
1984860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
1985860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
1986860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1987860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
1988860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
1989860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
1990860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
1991860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
1992860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
1993860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
1994860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
19950e9746b7b132058651155b33f219c7789997985bKenny Root                long[] cc = NativeCrypto.SSL_get_peer_cert_chain(s);
1996860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEqualCertificateChains(getServerCertificates(), cc);
19970e9746b7b132058651155b33f219c7789997985bKenny Root                for (long ref : cc) {
19980e9746b7b132058651155b33f219c7789997985bKenny Root                    NativeCrypto.X509_free(ref);
19990e9746b7b132058651155b33f219c7789997985bKenny Root                }
2000860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2001860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2002860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2003860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
20046fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
20056fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2006860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2007860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2008860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2009860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2010860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 };
2011860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2012860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_read() throws Exception {
2013860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2014860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // NULL ssl
2015860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2016860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0);
2017860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2018860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2019860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2020860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2021860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null FileDescriptor
2022860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2023860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2024860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2025860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2026860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0);
2027860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2028860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2029860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2030860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2031860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2032860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2033860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2034860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
2035860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2036860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2037860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2038860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2039860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0);
2040860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2041860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2042860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2043860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2044860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2045860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2046860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2047860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null byte array
2048860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2049860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2050860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2051860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2052860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0);
2053860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2054860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2055860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2056860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2057860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2058860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2059860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2060860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
2061860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2062860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2063860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2064860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2065860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
2066860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2067860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
2068860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2069860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2070860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2071860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2072860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2073860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2074860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2075860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // normal case
2076860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2077860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
2078860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
2079860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
2080860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
2081860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
2082860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2083860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    byte[] in = new byte[256];
2084860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertEquals(BYTES.length,
2085860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                 NativeCrypto.SSL_read(s,
2086860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       fd,
2087860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       callback,
2088860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       in,
2089860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       0,
2090860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       BYTES.length,
2091860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                                       0));
2092860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    for (int i = 0; i < BYTES.length; i++) {
2093860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        assertEquals(BYTES[i], in[i]);
2094860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
2095860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
2096860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2097860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
2098860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
2099860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
2100860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
2101860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
2102860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
2103860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2104860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length, 0);
2105860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
2106860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2107860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
21086fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
21096fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
21106fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
21116fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
2112860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2113860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2114860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2115860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2116860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // timeout case
2117860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2118860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
2119860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
2120860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
2121860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
2122860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
2123860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2124860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1);
2125860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    fail();
2126860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2127860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
2128860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
2129860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
2130860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
2131860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
2132860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
2133860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2134860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
2135860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
2136860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2137860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
21386fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
21396fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
2140767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin            @SuppressWarnings("unused")
21416fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
21426fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
2143860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2144860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2145860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (ExecutionException expected) {
2146860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(SocketTimeoutException.class, expected.getCause().getClass());
2147860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2148860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2149860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2150860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_write() throws Exception {
2151860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2152860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_write(NULL, null, null, null, 0, 0, 0);
2153860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2154860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2155860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2156860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2157860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null FileDescriptor
2158860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2159860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2160860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2161860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2162860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1, 0);
2163860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2164860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2165860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2166860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2167860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2168860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2169860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2170860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
2171860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2172860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2173860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2174860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2175860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1, 0);
2176860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2177860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2178860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2179860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2180860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2181860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2182860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2183860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null byte array
2184860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2185860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2186860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2187860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2188860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1, 0);
2189860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2190860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (NullPointerException expected) {
2191860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2192860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2193860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2194860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2195860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2196860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
2197860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2198860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2199860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2200860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            try {
2201860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0);
2202860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                fail();
2203860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            } catch (SSLException expected) {
2204860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2205860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2206860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2207860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2208860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2209860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positively tested by test_SSL_read
2210860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2211860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2212860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_interrupt() throws Exception {
2213860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_interrupt is a rare case that tolerates a null SSL argument
2214860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_interrupt(NULL);
2215860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2216860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // also works without handshaking
2217860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2218860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long c = NativeCrypto.SSL_CTX_new();
2219860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            long s = NativeCrypto.SSL_new(c);
2220860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_interrupt(s);
2221860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(s);
2222860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_CTX_free(c);
2223860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2224860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2225860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2226860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2227860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2228860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2229860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2230860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2231860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2232860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2233860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0);
2234860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2235860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2236860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2237860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) {
2238860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2239860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, final long s, long c,
2240860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2241860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2242860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2243860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                new Thread() {
2244767fda1ec66f2e2bf8a8f5fe17841906338b9471Alex Klyubin                    @Override
2245860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    public void run() {
2246860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        try {
2247860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            Thread.sleep(1*1000);
2248860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                            NativeCrypto.SSL_interrupt(s);
2249860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        } catch (Exception e) {
2250860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        }
2251860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    }
2252860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }.start();
2253860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(-1, NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0));
2254860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2255860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2256860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
22576fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
22586fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2259860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2260860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2261860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2262860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
226381c666781f8e24242e997e2666b656b240c5a145Kenny Root    private static abstract class SSLSessionWrappedTask {
226481c666781f8e24242e997e2666b656b240c5a145Kenny Root        public abstract void run(long sslSession) throws Exception;
226581c666781f8e24242e997e2666b656b240c5a145Kenny Root    }
2266860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
226781c666781f8e24242e997e2666b656b240c5a145Kenny Root    private void wrapWithSSLSession(SSLSessionWrappedTask task) throws Exception {
226881c666781f8e24242e997e2666b656b240c5a145Kenny Root        long c = NativeCrypto.SSL_CTX_new();
226981c666781f8e24242e997e2666b656b240c5a145Kenny Root        long s = NativeCrypto.SSL_new(c);
2270860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
227181c666781f8e24242e997e2666b656b240c5a145Kenny Root            task.run(s);
227281c666781f8e24242e997e2666b656b240c5a145Kenny Root        } finally {
227381c666781f8e24242e997e2666b656b240c5a145Kenny Root            NativeCrypto.SSL_free(s);
227481c666781f8e24242e997e2666b656b240c5a145Kenny Root            NativeCrypto.SSL_CTX_free(c);
2275860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
227681c666781f8e24242e997e2666b656b240c5a145Kenny Root    }
227781c666781f8e24242e997e2666b656b240c5a145Kenny Root
227881c666781f8e24242e997e2666b656b240c5a145Kenny Root    public void test_SSL_shutdown() throws Exception {
227981c666781f8e24242e997e2666b656b240c5a145Kenny Root
228081c666781f8e24242e997e2666b656b240c5a145Kenny Root        // null FileDescriptor
228181c666781f8e24242e997e2666b656b240c5a145Kenny Root        wrapWithSSLSession(new SSLSessionWrappedTask() {
228281c666781f8e24242e997e2666b656b240c5a145Kenny Root            @Override
228381c666781f8e24242e997e2666b656b240c5a145Kenny Root            public void run(long sslSession) throws Exception {
228481c666781f8e24242e997e2666b656b240c5a145Kenny Root                try {
228581c666781f8e24242e997e2666b656b240c5a145Kenny Root                    NativeCrypto.SSL_shutdown(sslSession, null, DUMMY_CB);
228681c666781f8e24242e997e2666b656b240c5a145Kenny Root                    fail();
228781c666781f8e24242e997e2666b656b240c5a145Kenny Root                } catch (NullPointerException expected) {
228881c666781f8e24242e997e2666b656b240c5a145Kenny Root                }
228981c666781f8e24242e997e2666b656b240c5a145Kenny Root            }
229081c666781f8e24242e997e2666b656b240c5a145Kenny Root        });
2291860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2292860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // null SSLHandshakeCallbacks
229381c666781f8e24242e997e2666b656b240c5a145Kenny Root        wrapWithSSLSession(new SSLSessionWrappedTask() {
229481c666781f8e24242e997e2666b656b240c5a145Kenny Root            @Override
229581c666781f8e24242e997e2666b656b240c5a145Kenny Root            public void run(long sslSession) throws Exception {
229681c666781f8e24242e997e2666b656b240c5a145Kenny Root                try {
229781c666781f8e24242e997e2666b656b240c5a145Kenny Root                    NativeCrypto.SSL_shutdown(sslSession, INVALID_FD, null);
229881c666781f8e24242e997e2666b656b240c5a145Kenny Root                    fail();
229981c666781f8e24242e997e2666b656b240c5a145Kenny Root                } catch (NullPointerException expected) {
230081c666781f8e24242e997e2666b656b240c5a145Kenny Root                }
230181c666781f8e24242e997e2666b656b240c5a145Kenny Root            }
230281c666781f8e24242e997e2666b656b240c5a145Kenny Root        });
2303860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2304860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_shutdown is a rare case that tolerates a null SSL argument
2305860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB);
2306860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2307860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // handshaking not yet performed
230881c666781f8e24242e997e2666b656b240c5a145Kenny Root        wrapWithSSLSession(new SSLSessionWrappedTask() {
230981c666781f8e24242e997e2666b656b240c5a145Kenny Root            @Override
231081c666781f8e24242e997e2666b656b240c5a145Kenny Root            public void run(long sslSession) throws Exception {
231181c666781f8e24242e997e2666b656b240c5a145Kenny Root                try {
231281c666781f8e24242e997e2666b656b240c5a145Kenny Root                    NativeCrypto.SSL_shutdown(sslSession, INVALID_FD, DUMMY_CB);
231381c666781f8e24242e997e2666b656b240c5a145Kenny Root                    fail();
231481c666781f8e24242e997e2666b656b240c5a145Kenny Root                } catch (SocketException expected) {
231581c666781f8e24242e997e2666b656b240c5a145Kenny Root                }
231681c666781f8e24242e997e2666b656b240c5a145Kenny Root            }
231781c666781f8e24242e997e2666b656b240c5a145Kenny Root        });
2318860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2319860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positively tested elsewhere because handshake uses use
2320860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // SSL_shutdown to ensure SSL_SESSIONs are reused.
2321860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2322860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2323860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_free() throws Exception {
2324860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2325860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_free(NULL);
2326860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2327860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2328860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2329860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2330860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long c = NativeCrypto.SSL_CTX_new();
2331860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_free(NativeCrypto.SSL_new(c));
2332860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.SSL_CTX_free(c);
2333860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2334860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing elsewhere because handshake
2335860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // uses use SSL_free to cleanup in afterHandshake.
2336860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2337860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2338860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_session_id() throws Exception {
2339860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2340860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_session_id(NULL);
2341860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2342860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2343860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2344860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2345860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2346860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2347860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2348860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2349860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2350860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2351860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2352860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2353860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] id = NativeCrypto.SSL_SESSION_session_id(session);
2354860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNotNull(id);
2355860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(32, id.length);
2356860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2357860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2358860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2359860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
23606fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
23616fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2362860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2363860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2364860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2365860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2366860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_get_time() throws Exception {
2367860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2368860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_get_time(NULL);
2369860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2370860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2371860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2372860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2373860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2374860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2375860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        {
2376860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks cHooks = new Hooks() {
2377860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                @Override
2378860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                public void afterHandshake(long session, long s, long c,
2379860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           Socket sock, FileDescriptor fd,
2380860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                           SSLHandshakeCallbacks callback)
2381860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2382860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    long time = NativeCrypto.SSL_SESSION_get_time(session);
2383860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertTrue(time != 0);
2384860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    assertTrue(time < System.currentTimeMillis());
2385860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    super.afterHandshake(session, s, c, sock, fd, callback);
2386860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                }
2387860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            };
2388860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
23896fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null,
23906fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
23916fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root            Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null,
23926fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root                    null);
2393860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2394860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2395860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2396860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2397860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2398860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_get_version() throws Exception {
2399860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2400860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_get_version(NULL);
2401860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2402860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2403860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2404860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2405860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2406860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2407860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2408860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2409860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2410860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2411860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2412860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2413860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                String v = NativeCrypto.SSL_SESSION_get_version(session);
2414860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v));
2415860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2416860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2417860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2418860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
24196fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
24206fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2421860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2422860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2423860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2424860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2425860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_cipher() throws Exception {
2426860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2427860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_cipher(NULL);
2428860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2429860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2430860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2431860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2432860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2433860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2434860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2435860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2436860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2437860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2438860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2439860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                        throws Exception {
2440860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                String a = NativeCrypto.SSL_SESSION_cipher(session);
2441860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a));
2442860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2443860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2444860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2445860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
24466fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
24476fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2448860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2449860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2450860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2451860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2452860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_SSL_SESSION_free() throws Exception {
2453860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2454860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.SSL_SESSION_free(NULL);
2455860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2456860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2457860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2458860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2459860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // additional positive testing elsewhere because handshake
2460860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // uses use SSL_SESSION_free to cleanup in afterHandshake.
2461860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2462860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2463860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_i2d_SSL_SESSION() throws Exception {
2464860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2465860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.i2d_SSL_SESSION(NULL);
2466860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2467860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2468860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2469860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2470860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        final ServerSocket listener = new ServerSocket(0);
2471860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2472860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks cHooks = new Hooks() {
2473860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            @Override
2474860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            public void afterHandshake(long session, long s, long c,
2475860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       Socket sock, FileDescriptor fd,
2476860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                                       SSLHandshakeCallbacks callback)
2477860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    throws Exception {
2478860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                byte[] b = NativeCrypto.i2d_SSL_SESSION(session);
2479860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertNotNull(b);
2480860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                long session2 = NativeCrypto.d2i_SSL_SESSION(b);
2481860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(session2 != NULL);
2482860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2483860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                // Make sure d2i_SSL_SESSION retores SSL_SESSION_cipher value http://b/7091840
2484860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertTrue(NativeCrypto.SSL_SESSION_cipher(session2) != null);
2485860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                assertEquals(NativeCrypto.SSL_SESSION_cipher(session),
2486860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                             NativeCrypto.SSL_SESSION_cipher(session2));
2487860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2488860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                NativeCrypto.SSL_SESSION_free(session2);
2489860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                super.afterHandshake(session, s, c, sock, fd, callback);
2490860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            }
2491860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        };
2492860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates());
24936fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks, null, null);
24946fcf0cbeec79d1f2491d8d0774fdb314fc419ba3Kenny Root        Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks, null, null);
2495860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2496860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
2497860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2498860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2499860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_d2i_SSL_SESSION() throws Exception {
2500860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2501860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.d2i_SSL_SESSION(null);
2502860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2503860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2504860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2505860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2506860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[0]));
2507860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[1]));
2508860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2509860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // positive testing by test_i2d_SSL_SESSION
2510860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2511860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2512860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_X509_NAME_hashes() {
2513860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // ensure these hash functions are stable over time since the
2514860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // /system/etc/security/cacerts CA filenames have to be
2515860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // consistent with the output.
2516860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        X500Principal name = new X500Principal("CN=localhost");
2517860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(-1372642656, NativeCrypto.X509_NAME_hash(name)); // SHA1
2518860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(-1626170662, NativeCrypto.X509_NAME_hash_old(name)); // MD5
2519860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2520860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2521860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_RAND_bytes_Success() throws Exception {
2522860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] output = new byte[128];
2523860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        NativeCrypto.RAND_bytes(output);
2524860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2525860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        boolean isZero = true;
2526860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        for (int i = 0; i < output.length; i++) {
2527860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            isZero &= (output[i] == 0);
2528860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2529860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2530860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertFalse("Random output was zero. This is a very low probability event (1 in 2^128) "
2531860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                + "and probably indicates an error.", isZero);
2532860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2533860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2534860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_RAND_bytes_Null_Failure() throws Exception {
2535860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] output = null;
2536860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2537860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.RAND_bytes(output);
2538860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail("Should be an error on null buffer input");
2539860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2540860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2541860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2542860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2543860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_get_digestbyname() throws Exception {
2544860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(NativeCrypto.EVP_get_digestbyname("sha256") != NULL);
2545860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2546860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2547860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname(null);
2548860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2549860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2550860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2551860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2552860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2553860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname("");
2554860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.EVP_get_digestbyname("foobar");
2555860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2556860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2557860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2558860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2559860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2560860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_SignInit() throws Exception {
25614bff0a15ae03c8a3e1ae95590cc8c4240837bff6Kenny Root        final NativeRef.EVP_MD_CTX ctx = new NativeRef.EVP_MD_CTX(NativeCrypto.EVP_MD_CTX_create());
2562652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root        assertEquals(1,
2563ad73400e9d5c7048fcf2980b75ea45e2aac8fb39Kenny Root                NativeCrypto.EVP_SignInit(ctx, NativeCrypto.EVP_get_digestbyname("sha256")));
2564860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2565860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2566652ff53bd48ed61389337a42d8e50cdb7ace0fecKenny Root            NativeCrypto.EVP_SignInit(ctx, 0);
2567860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            fail();
2568860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (RuntimeException expected) {
2569860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2570860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2571860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2572860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_get_RSA_private_params() throws Exception {
2573860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2574796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.get_RSA_private_params(null);
2575860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2576860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2577860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2578860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2579796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.get_RSA_private_params(null);
2580860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2581860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2582860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2583860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Test getting params for the wrong kind of key.
25847dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
25857dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertFalse(groupCtx == NULL);
25867dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupCtx);
258737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeRef.EVP_PKEY ctx = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
2588860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
258937e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            NativeCrypto.get_RSA_private_params(ctx);
259037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            fail();
259137e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        } catch (RuntimeException expected) {
2592860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2593860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2594860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2595860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_get_RSA_public_params() throws Exception {
2596860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2597796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.get_RSA_public_params(null);
2598860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2599860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2600860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2601860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2602796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.get_RSA_public_params(null);
2603860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } catch (NullPointerException expected) {
2604860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2605860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2606860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        // Test getting params for the wrong kind of key.
26077dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
26087dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertFalse(groupCtx == NULL);
26097dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupCtx);
261037e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        NativeRef.EVP_PKEY ctx = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
2611860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
261237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            NativeCrypto.get_RSA_public_params(ctx);
261337e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            fail();
261437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root        } catch (RuntimeException expected) {
2615860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2616860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2617860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
26187c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_RSA_size_null_key_Failure() throws Exception {
26197c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
2620796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.RSA_size(null);
2621796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            fail("Expecting null pointer exception for RSA_size with null key");
26227c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
26237c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
26247c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
26257c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_RSA_private_encrypt_null_key_Failure() throws Exception {
26267c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
262737e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            NativeCrypto.RSA_private_encrypt(0, new byte[0], new byte[0],
2628796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro                    null, 0);
2629796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            fail("Expecting null pointer exception for RSA_private encrypt with null key");
26307c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
26317c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
26327c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
26337c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_RSA_private_decrypt_null_key_Failure() throws Exception {
26347c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
263537e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root            NativeCrypto.RSA_private_decrypt(0, new byte[0], new byte[0],
2636796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro null, 0);
2637796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            fail("Expecting null pointer exception for RSA_private_decrypt with null key");
26387c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
26397c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
26407c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
26417c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_RSA_public_encrypt_null_key_Failure() throws Exception {
26427c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
2643796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.RSA_public_encrypt(0, new byte[0], new byte[0], null,
264437e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                    0);
2645796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            fail("Expecting null pointer exception for RSA_public encrypt with null key");
26467c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
26477c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
26487c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
26497c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_RSA_public_decrypt_null_key_Failure() throws Exception {
26507c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
2651796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.RSA_public_decrypt(0, new byte[0], new byte[0], null,
265237e58bbef60b18389074d8ef8a8c470e47f3d7eeKenny Root                    0);
2653796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            fail("Expecting null pointer exception for RSA_public decrypt with null key");
26547c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
26557c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
26567c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
2657860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    /*
2658860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * Test vector generation:
2659860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     * openssl rand -hex 16
2660860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root     */
2661860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private static final byte[] AES_128_KEY = new byte[] {
2662860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x3d, (byte) 0x4f, (byte) 0x89, (byte) 0x70, (byte) 0xb1, (byte) 0xf2,
2663860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x75, (byte) 0x37, (byte) 0xf4, (byte) 0x0a, (byte) 0x39, (byte) 0x29,
2664860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            (byte) 0x8a, (byte) 0x41, (byte) 0x55, (byte) 0x5f,
2665860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    };
2666860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2667860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void testEC_GROUP() throws Exception {
2668860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        /* Test using NIST's P-256 curve */
2669860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        check_EC_GROUP(NativeCrypto.EC_CURVE_GFP, "prime256v1",
2670860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
2671860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
2672860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b",
2673860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
2674860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
2675860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
2676860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                1L);
2677860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2678860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2679860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    private void check_EC_GROUP(int type, String name, String pStr, String aStr, String bStr,
2680860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            String xStr, String yStr, String nStr, long hLong) throws Exception {
26817dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        long groupRef = NativeCrypto.EC_GROUP_new_by_curve_name(name);
26827dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertFalse(groupRef == NULL);
26837dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP group = new NativeRef.EC_GROUP(groupRef);
26847dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(NativeCrypto.OBJ_txt2nid_longName(name),
26857dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root                NativeCrypto.EC_GROUP_get_curve_name(group));
26867dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(type, NativeCrypto.get_EC_GROUP_type(group));
2687860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
26887dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // prime
26897dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger p = new BigInteger(pStr, 16);
26907dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // first coefficient
26917dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger a = new BigInteger(aStr, 16);
26927dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // second coefficient
26937dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger b = new BigInteger(bStr, 16);
26947dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // x affine coordinate of generator
26957dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger x = new BigInteger(xStr, 16);
26967dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // y affine coordinate of generator
26977dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger y = new BigInteger(yStr, 16);
26987dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // order of the generator
26997dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger n = new BigInteger(nStr, 16);
27007dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // cofactor of generator
27017dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger h = BigInteger.valueOf(hLong);
2702860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27037dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        byte[][] pab = NativeCrypto.EC_GROUP_get_curve(group);
27047dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(3, pab.length);
2705860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27067dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger p2 = new BigInteger(pab[0]);
27077dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(p, p2);
2708860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27097dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger a2 = new BigInteger(pab[1]);
27107dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(a, a2);
2711860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27127dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger b2 = new BigInteger(pab[2]);
27137dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(b, b2);
2714de5225d1ebe7b3a5f3565539685fcd95348ae815Adam Langley
27157dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_POINT point = new NativeRef.EC_POINT(
27167dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root                NativeCrypto.EC_GROUP_get_generator(group));
2717860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27187dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        byte[][] xy = NativeCrypto.EC_POINT_get_affine_coordinates(group, point);
27197dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(2, xy.length);
2720860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27217dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger x2 = new BigInteger(xy[0]);
27227dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(x, x2);
2723860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27247dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger y2 = new BigInteger(xy[1]);
27257dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(y, y2);
2726860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27277dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger n2 = new BigInteger(NativeCrypto.EC_GROUP_get_order(group));
27287dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(n, n2);
2729860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27307dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        BigInteger h2 = new BigInteger(NativeCrypto.EC_GROUP_get_cofactor(group));
27317dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(h, h2);
2732860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27337dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EVP_PKEY key1 = new NativeRef.EVP_PKEY(NativeCrypto.EC_KEY_generate_key(group));
27347dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP groupTmp = new NativeRef.EC_GROUP(NativeCrypto.EC_KEY_get1_group(key1));
27357dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertEquals(NativeCrypto.EC_GROUP_get_curve_name(group),
27367dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root                NativeCrypto.EC_GROUP_get_curve_name(groupTmp));
2737860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2738860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27397c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_EC_KEY_get_private_key_null_key_Failure() throws Exception {
27407c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
2741796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EC_KEY_get_private_key(null);
27427c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin            fail();
27437c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
27447c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
27457c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
27467c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_EC_KEY_get_public_key_null_key_Failure() throws Exception {
27477c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        try {
2748796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EC_KEY_get_public_key(null);
27497c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin            fail();
27507c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        } catch (NullPointerException expected) {}
27517c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
27527c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
2753ddcacec3f4f08759f3652a2efebd8b696a87fc4dKenny Root    public void test_ECKeyPairGenerator_CurvesAreValid() throws Exception {
2754ddcacec3f4f08759f3652a2efebd8b696a87fc4dKenny Root        OpenSSLECKeyPairGenerator.assertCurvesAreValid();
2755ddcacec3f4f08759f3652a2efebd8b696a87fc4dKenny Root    }
2756ddcacec3f4f08759f3652a2efebd8b696a87fc4dKenny Root
27577c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    public void test_ECDH_compute_key_null_key_Failure() throws Exception {
27587dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
27597dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertFalse(groupCtx == NULL);
27607dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP groupRef = new NativeRef.EC_GROUP(groupCtx);
27617dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EVP_PKEY pkey1Ref = new NativeRef.EVP_PKEY(
27627dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root                NativeCrypto.EC_KEY_generate_key(groupRef));
27637dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EVP_PKEY pkey2Ref = new NativeRef.EVP_PKEY(
27647dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root                NativeCrypto.EC_KEY_generate_key(groupRef));
27657c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
27667dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        byte[] out = new byte[128];
27677dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        int outOffset = 0;
27687dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // Assert that the method under test works fine with the two
27697dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // non-null keys
27707dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeCrypto.ECDH_compute_key(out, outOffset, pkey1Ref, pkey2Ref);
27717c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
27727dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // Assert that it fails when only the first key is null
27737dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        try {
2774796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.ECDH_compute_key(out, outOffset, null, pkey2Ref);
27757dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root            fail();
27767dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        } catch (NullPointerException expected) {
27777dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        }
27787c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
27797dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        // Assert that it fails when only the second key is null
27807dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        try {
2781796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.ECDH_compute_key(out, outOffset, pkey1Ref, null);
27827dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root            fail();
27837dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        } catch (NullPointerException expected) {
27847c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin        }
27857c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin    }
27867c2b4ae9455185974ffe5ec1804c8980fe429635Alex Klyubin
2787860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CipherInit_ex_Null_Failure() throws Exception {
27884757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        final NativeRef.EVP_CIPHER_CTX ctx = new NativeRef.EVP_CIPHER_CTX(
27894757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root                NativeCrypto.EVP_CIPHER_CTX_new());
27904757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
2791860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27924757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        try {
2793796ed069bc90d1de9f45ea1f746edaeec8081ed3Sergio Giro            NativeCrypto.EVP_CipherInit_ex(null, evpCipher, null, null, true);
27944757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root            fail("Null context should throw NullPointerException");
27954757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        } catch (NullPointerException expected) {
27964757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        }
2797860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
27984757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        /* Initialize encrypting. */
27994757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, true);
28004757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, true);
2801860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
28024757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        /* Initialize decrypting. */
28034757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, null, null, false);
28044757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        NativeCrypto.EVP_CipherInit_ex(ctx, NULL, null, null, false);
2805860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2806860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2807860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CipherInit_ex_Success() throws Exception {
28084757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        final NativeRef.EVP_CIPHER_CTX ctx = new NativeRef.EVP_CIPHER_CTX(
28094757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root                NativeCrypto.EVP_CIPHER_CTX_new());
28104757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        final long evpCipher = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
28114757cdbe3c9e06f243a8cb07086ced5537d69af2Kenny Root        NativeCrypto.EVP_CipherInit_ex(ctx, evpCipher, AES_128_KEY, null, true);
2812860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2813860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2814860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_EVP_CIPHER_iv_length() throws Exception {
2815860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long aes128ecb = NativeCrypto.EVP_get_cipherbyname("aes-128-ecb");
2816860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(0, NativeCrypto.EVP_CIPHER_iv_length(aes128ecb));
2817860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2818860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long aes128cbc = NativeCrypto.EVP_get_cipherbyname("aes-128-cbc");
2819860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertEquals(16, NativeCrypto.EVP_CIPHER_iv_length(aes128cbc));
2820860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2821860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2822860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_OpenSSLKey_toJava() throws Exception {
2823860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        OpenSSLKey key1;
2824860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2825860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        BigInteger e = BigInteger.valueOf(65537);
2826860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        key1 = new OpenSSLKey(NativeCrypto.RSA_generate_key_ex(1024, e.toByteArray()));
2827860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(key1.getPublicKey() instanceof RSAPublicKey);
2828860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
28297dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        final long groupCtx = NativeCrypto.EC_GROUP_new_by_curve_name("prime256v1");
28307dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        assertFalse(groupCtx == NULL);
28317dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        NativeRef.EC_GROUP group1 = new NativeRef.EC_GROUP(groupCtx);
28327dc06b9e323ba7f227709b5941324f9c3a46fe4fKenny Root        key1 = new OpenSSLKey(NativeCrypto.EC_KEY_generate_key(group1));
2833860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        assertTrue(key1.getPublicKey() instanceof ECPublicKey);
2834860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2835860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2836860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_create_BIO_InputStream() throws Exception {
2837860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] actual = "Test".getBytes();
2838860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ByteArrayInputStream is = new ByteArrayInputStream(actual);
2839860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
284019fdf1af6bada9ebf4820839780d8713ac3824faKenny Root        @SuppressWarnings("resource")
2841d82dc06faee760a737da6f2755a9063637c206e3Adam Langley        OpenSSLBIOInputStream bis = new OpenSSLBIOInputStream(is, true);
2842860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2843860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            byte[] buffer = new byte[1024];
284419fdf1af6bada9ebf4820839780d8713ac3824faKenny Root            int numRead = NativeCrypto.BIO_read(bis.getBioContext(), buffer);
2845860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(actual.length, numRead);
2846860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(Arrays.toString(actual),
2847860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root                    Arrays.toString(Arrays.copyOfRange(buffer, 0, numRead)));
2848860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
284919fdf1af6bada9ebf4820839780d8713ac3824faKenny Root            bis.release();
2850860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2851860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
2852860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2853860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    public void test_create_BIO_OutputStream() throws Exception {
2854860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        byte[] actual = "Test".getBytes();
2855860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        ByteArrayOutputStream os = new ByteArrayOutputStream();
2856860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root
2857860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        long ctx = NativeCrypto.create_BIO_OutputStream(os);
2858860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        try {
2859860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            NativeCrypto.BIO_write(ctx, actual, 0, actual.length);
2860860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(actual.length, os.size());
2861860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root            assertEquals(Arrays.toString(actual), Arrays.toString(os.toByteArray()));
2862860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        } finally {
286319fdf1af6bada9ebf4820839780d8713ac3824faKenny Root            NativeCrypto.BIO_free_all(ctx);
2864860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root        }
2865860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root    }
286601cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin
286701cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    private static void assertContains(String actualValue, String expectedSubstring) {
286801cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        if (actualValue == null) {
286901cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            return;
287001cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
287101cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        if (actualValue.contains(expectedSubstring)) {
287201cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin            return;
287301cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        }
287401cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin        fail("\"" + actualValue + "\" does not contain \"" + expectedSubstring + "\"");
287501cce891dd313a0fb9d4694283f2a13fb5c43afeAlex Klyubin    }
2876860d2707ce126ef8f66e3eac7ceeab6d24218cd8Kenny Root}
2877