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