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