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.apache.harmony.xnet.provider.jsse; 18 19 import java.io.FileDescriptor; 20 import java.io.IOException; 21 import java.net.ServerSocket; 22 import java.net.Socket; 23 import java.net.SocketTimeoutException; 24 import java.security.KeyStore.PrivateKeyEntry; 25 import java.security.KeyStore; 26 import java.security.KeyStoreException; 27 import java.security.cert.Certificate; 28 import java.security.cert.CertificateEncodingException; 29 import java.security.cert.CertificateException; 30 import java.security.cert.X509Certificate; 31 import java.util.ArrayList; 32 import java.util.Arrays; 33 import java.util.List; 34 import java.util.concurrent.Callable; 35 import java.util.concurrent.ExecutionException; 36 import java.util.concurrent.ExecutorService; 37 import java.util.concurrent.Executors; 38 import java.util.concurrent.Future; 39 import java.util.concurrent.TimeUnit; 40 import javax.net.ssl.SSLException; 41 import javax.net.ssl.SSLProtocolException; 42 import javax.security.auth.x500.X500Principal; 43 import junit.framework.TestCase; 44 import libcore.java.security.StandardNames; 45 import libcore.java.security.TestKeyStore; 46 import org.apache.harmony.xnet.provider.jsse.CipherSuite; 47 import org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSLHandshakeCallbacks; 48 49 public class NativeCryptoTest extends TestCase { 50 51 private static final int NULL = 0; 52 private static final FileDescriptor INVALID_FD = new FileDescriptor(); 53 private static final SSLHandshakeCallbacks DUMMY_CB = new TestSSLHandshakeCallbacks(-1, null); 54 55 private static final long TIMEOUT_SECONDS = 5; 56 57 private static byte[] SERVER_PRIVATE_KEY; 58 private static byte[][] SERVER_CERTIFICATES; 59 private static byte[] CLIENT_PRIVATE_KEY; 60 private static byte[][] CLIENT_CERTIFICATES; 61 private static byte[][] CA_PRINCIPALS; 62 63 private static byte[] getServerPrivateKey() { 64 initCerts(); 65 return SERVER_PRIVATE_KEY; 66 } 67 68 private static byte[][] getServerCertificates() { 69 initCerts(); 70 return SERVER_CERTIFICATES; 71 } 72 73 private static byte[] getClientPrivateKey() { 74 initCerts(); 75 return CLIENT_PRIVATE_KEY; 76 } 77 78 private static byte[][] getClientCertificates() { 79 initCerts(); 80 return CLIENT_CERTIFICATES; 81 } 82 83 private static byte[][] getCaPrincipals() { 84 initCerts(); 85 return CA_PRINCIPALS; 86 } 87 88 /** 89 * Lazily create shared test certificates. 90 */ 91 private static synchronized void initCerts() { 92 if (SERVER_PRIVATE_KEY != null) { 93 return; 94 } 95 96 try { 97 PrivateKeyEntry serverPrivateKeyEntry 98 = TestKeyStore.getServer().getPrivateKey("RSA", "RSA"); 99 SERVER_PRIVATE_KEY = serverPrivateKeyEntry.getPrivateKey().getEncoded(); 100 SERVER_CERTIFICATES = NativeCrypto.encodeCertificates( 101 serverPrivateKeyEntry.getCertificateChain()); 102 103 PrivateKeyEntry clientPrivateKeyEntry 104 = TestKeyStore.getClientCertificate().getPrivateKey("RSA", "RSA"); 105 CLIENT_PRIVATE_KEY = clientPrivateKeyEntry.getPrivateKey().getEncoded(); 106 CLIENT_CERTIFICATES = NativeCrypto.encodeCertificates( 107 clientPrivateKeyEntry.getCertificateChain()); 108 109 KeyStore ks = TestKeyStore.getClient().keyStore; 110 String caCertAlias = ks.aliases().nextElement(); 111 X509Certificate certificate = (X509Certificate) ks.getCertificate(caCertAlias); 112 X500Principal principal = certificate.getIssuerX500Principal(); 113 CA_PRINCIPALS = new byte[][] { principal.getEncoded() }; 114 } catch (Exception e) { 115 throw new RuntimeException(e); 116 } 117 } 118 119 public static void assertEqualSessions(int expected, int actual) { 120 assertEqualByteArrays(NativeCrypto.SSL_SESSION_session_id(expected), 121 NativeCrypto.SSL_SESSION_session_id(actual)); 122 } 123 public static void assertEqualByteArrays(byte[] expected, byte[] actual) { 124 assertEquals(Arrays.toString(expected), Arrays.toString(actual)); 125 } 126 127 public static void assertEqualPrincipals(byte[][] expected, byte[][] actual) { 128 assertEqualByteArrays(expected, actual); 129 } 130 public static void assertEqualCertificateChains(byte[][] expected, byte[][] actual) { 131 assertEqualByteArrays(expected, actual); 132 } 133 public static void assertEqualByteArrays(byte[][] expected, byte[][] actual) { 134 assertEquals(Arrays.deepToString(expected), Arrays.deepToString(actual)); 135 } 136 137 public void test_SSL_CTX_new() throws Exception { 138 int c = NativeCrypto.SSL_CTX_new(); 139 assertTrue(c != NULL); 140 int c2 = NativeCrypto.SSL_CTX_new(); 141 assertTrue(c != c2); 142 NativeCrypto.SSL_CTX_free(c); 143 NativeCrypto.SSL_CTX_free(c2); 144 } 145 146 public void test_SSL_CTX_free() throws Exception { 147 try { 148 NativeCrypto.SSL_CTX_free(NULL); 149 fail(); 150 } catch (NullPointerException expected) { 151 } 152 153 NativeCrypto.SSL_CTX_free(NativeCrypto.SSL_CTX_new()); 154 } 155 156 public void test_SSL_new() throws Exception { 157 int c = NativeCrypto.SSL_CTX_new(); 158 int s = NativeCrypto.SSL_new(c); 159 160 assertTrue(s != NULL); 161 assertTrue((NativeCrypto.SSL_get_options(s) & 0x01000000L) != 0); // SSL_OP_NO_SSLv2 162 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0); 163 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_TLSv1) == 0); 164 165 int s2 = NativeCrypto.SSL_new(c); 166 assertTrue(s != s2); 167 NativeCrypto.SSL_free(s2); 168 169 NativeCrypto.SSL_free(s); 170 NativeCrypto.SSL_CTX_free(c); 171 } 172 173 public void test_SSL_use_certificate() throws Exception { 174 try { 175 NativeCrypto.SSL_use_certificate(NULL, null); 176 fail(); 177 } catch (NullPointerException expected) { 178 } 179 180 int c = NativeCrypto.SSL_CTX_new(); 181 int s = NativeCrypto.SSL_new(c); 182 183 try { 184 NativeCrypto.SSL_use_certificate(s, null); 185 fail(); 186 } catch (NullPointerException expected) { 187 } 188 189 NativeCrypto.SSL_use_certificate(s, getServerCertificates()); 190 191 NativeCrypto.SSL_free(s); 192 NativeCrypto.SSL_CTX_free(c); 193 } 194 195 public void test_SSL_use_PrivateKey() throws Exception { 196 try { 197 NativeCrypto.SSL_use_PrivateKey(NULL, null); 198 fail(); 199 } catch (NullPointerException expected) { 200 } 201 202 int c = NativeCrypto.SSL_CTX_new(); 203 int s = NativeCrypto.SSL_new(c); 204 205 try { 206 NativeCrypto.SSL_use_PrivateKey(s, null); 207 fail(); 208 } catch (NullPointerException expected) { 209 } 210 211 NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey()); 212 213 NativeCrypto.SSL_free(s); 214 NativeCrypto.SSL_CTX_free(c); 215 } 216 217 public void test_SSL_check_private_key_null() throws Exception { 218 try { 219 NativeCrypto.SSL_check_private_key(NULL); 220 fail(); 221 } catch (NullPointerException expected) { 222 } 223 } 224 225 public void test_SSL_check_private_key_no_key_no_cert() throws Exception { 226 int c = NativeCrypto.SSL_CTX_new(); 227 int s = NativeCrypto.SSL_new(c); 228 229 // neither private or certificate set 230 try { 231 NativeCrypto.SSL_check_private_key(s); 232 fail(); 233 } catch (SSLException expected) { 234 } 235 236 NativeCrypto.SSL_free(s); 237 NativeCrypto.SSL_CTX_free(c); 238 } 239 240 public void test_SSL_check_private_key_cert_then_key() throws Exception { 241 int c = NativeCrypto.SSL_CTX_new(); 242 int s = NativeCrypto.SSL_new(c); 243 244 // first certificate, then private 245 NativeCrypto.SSL_use_certificate(s, getServerCertificates()); 246 247 try { 248 NativeCrypto.SSL_check_private_key(s); 249 fail(); 250 } catch (SSLException expected) { 251 } 252 253 NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey()); 254 NativeCrypto.SSL_check_private_key(s); 255 256 NativeCrypto.SSL_free(s); 257 NativeCrypto.SSL_CTX_free(c); 258 } 259 public void test_SSL_check_private_key_key_then_cert() throws Exception { 260 int c = NativeCrypto.SSL_CTX_new(); 261 int s = NativeCrypto.SSL_new(c); 262 263 // first private, then certificate 264 NativeCrypto.SSL_use_PrivateKey(s, getServerPrivateKey()); 265 266 try { 267 NativeCrypto.SSL_check_private_key(s); 268 fail(); 269 } catch (SSLException expected) { 270 } 271 272 NativeCrypto.SSL_use_certificate(s, getServerCertificates()); 273 NativeCrypto.SSL_check_private_key(s); 274 275 NativeCrypto.SSL_free(s); 276 NativeCrypto.SSL_CTX_free(c); 277 } 278 279 public void test_SSL_get_mode() throws Exception { 280 try { 281 NativeCrypto.SSL_get_mode(NULL); 282 fail(); 283 } catch (NullPointerException expected) { 284 } 285 286 int c = NativeCrypto.SSL_CTX_new(); 287 int s = NativeCrypto.SSL_new(c); 288 assertTrue(NativeCrypto.SSL_get_mode(s) != 0); 289 NativeCrypto.SSL_free(s); 290 NativeCrypto.SSL_CTX_free(c); 291 } 292 293 public void test_SSL_set_mode() throws Exception { 294 try { 295 NativeCrypto.SSL_set_mode(NULL, 0); 296 fail(); 297 } catch (NullPointerException expected) { 298 } 299 300 int c = NativeCrypto.SSL_CTX_new(); 301 int s = NativeCrypto.SSL_new(c); 302 // check SSL_MODE_HANDSHAKE_CUTTHROUGH on 303 assertTrue((NativeCrypto.SSL_get_mode(s) 304 & NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0); 305 // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off 306 NativeCrypto.SSL_clear_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 307 assertTrue((NativeCrypto.SSL_get_mode(s) 308 & NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0); 309 // set SSL_MODE_HANDSHAKE_CUTTHROUGH on 310 NativeCrypto.SSL_set_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 311 assertTrue((NativeCrypto.SSL_get_mode(s) 312 & NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0); 313 314 NativeCrypto.SSL_free(s); 315 NativeCrypto.SSL_CTX_free(c); 316 } 317 318 public void test_SSL_clear_mode() throws Exception { 319 try { 320 NativeCrypto.SSL_clear_mode(NULL, 0); 321 fail(); 322 } catch (NullPointerException expected) { 323 } 324 325 int c = NativeCrypto.SSL_CTX_new(); 326 int s = NativeCrypto.SSL_new(c); 327 // check SSL_MODE_HANDSHAKE_CUTTHROUGH on 328 assertTrue((NativeCrypto.SSL_get_mode(s) 329 & NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH) != 0); 330 // clear SSL_MODE_HANDSHAKE_CUTTHROUGH off 331 NativeCrypto.SSL_clear_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 332 assertTrue((NativeCrypto.SSL_get_mode(s) 333 & NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH) == 0); 334 NativeCrypto.SSL_free(s); 335 NativeCrypto.SSL_CTX_free(c); 336 } 337 338 public void test_SSL_get_options() throws Exception { 339 try { 340 NativeCrypto.SSL_get_options(NULL); 341 fail(); 342 } catch (NullPointerException expected) { 343 } 344 345 int c = NativeCrypto.SSL_CTX_new(); 346 int s = NativeCrypto.SSL_new(c); 347 assertTrue(NativeCrypto.SSL_get_options(s) != 0); 348 NativeCrypto.SSL_free(s); 349 NativeCrypto.SSL_CTX_free(c); 350 } 351 352 public void test_SSL_set_options() throws Exception { 353 try { 354 NativeCrypto.SSL_set_options(NULL, 0); 355 fail(); 356 } catch (NullPointerException expected) { 357 } 358 359 int c = NativeCrypto.SSL_CTX_new(); 360 int s = NativeCrypto.SSL_new(c); 361 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0); 362 NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3); 363 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0); 364 NativeCrypto.SSL_free(s); 365 NativeCrypto.SSL_CTX_free(c); 366 } 367 368 public void test_SSL_clear_options() throws Exception { 369 try { 370 NativeCrypto.SSL_clear_options(NULL, 0); 371 fail(); 372 } catch (NullPointerException expected) { 373 } 374 375 int c = NativeCrypto.SSL_CTX_new(); 376 int s = NativeCrypto.SSL_new(c); 377 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0); 378 NativeCrypto.SSL_set_options(s, NativeCrypto.SSL_OP_NO_SSLv3); 379 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) != 0); 380 NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_SSLv3); 381 assertTrue((NativeCrypto.SSL_get_options(s) & NativeCrypto.SSL_OP_NO_SSLv3) == 0); 382 NativeCrypto.SSL_free(s); 383 NativeCrypto.SSL_CTX_free(c); 384 } 385 386 public void test_SSL_set_cipher_lists() throws Exception { 387 try { 388 NativeCrypto.SSL_set_cipher_lists(NULL, null); 389 fail(); 390 } catch (NullPointerException expected) { 391 } 392 393 int c = NativeCrypto.SSL_CTX_new(); 394 int s = NativeCrypto.SSL_new(c); 395 396 try { 397 NativeCrypto.SSL_set_cipher_lists(s, null); 398 fail(); 399 } catch (NullPointerException expected) { 400 } 401 402 NativeCrypto.SSL_set_cipher_lists(s, new String[] {}); 403 404 try { 405 NativeCrypto.SSL_set_cipher_lists(s, new String[] { null }); 406 fail(); 407 } catch (NullPointerException expected) { 408 } 409 410 // see OpenSSL ciphers man page 411 String[] illegals = new String[] { 412 // empty 413 "", 414 // never standardized 415 "EXP1024-DES-CBC-SHA", "EXP1024-RC4-SHA", "DHE-DSS-RC4-SHA", 416 // IDEA 417 "IDEA-CBC-SHA", "IDEA-CBC-MD5" 418 }; 419 420 for (String illegal : illegals) { 421 try { 422 NativeCrypto.SSL_set_cipher_lists(s, new String[] { illegal }); 423 fail(illegal); 424 } catch (IllegalArgumentException expected) { 425 } 426 } 427 428 List<String> ciphers 429 = new ArrayList<String>(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.keySet()); 430 NativeCrypto.SSL_set_cipher_lists(s, ciphers.toArray(new String[ciphers.size()])); 431 432 NativeCrypto.SSL_free(s); 433 NativeCrypto.SSL_CTX_free(c); 434 } 435 436 public void test_SSL_set_verify() throws Exception { 437 try { 438 NativeCrypto.SSL_set_verify(NULL, 0); 439 fail(); 440 } catch (NullPointerException expected) { 441 } 442 443 int c = NativeCrypto.SSL_CTX_new(); 444 int s = NativeCrypto.SSL_new(c); 445 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_NONE); 446 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER); 447 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 448 NativeCrypto.SSL_set_verify(s, (NativeCrypto.SSL_VERIFY_PEER 449 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT)); 450 NativeCrypto.SSL_free(s); 451 NativeCrypto.SSL_CTX_free(c); 452 } 453 454 private static final boolean DEBUG = false; 455 456 public static class Hooks { 457 public int getContext() throws SSLException { 458 return NativeCrypto.SSL_CTX_new(); 459 } 460 public int beforeHandshake(int context) throws SSLException { 461 int s = NativeCrypto.SSL_new(context); 462 // without this SSL_set_cipher_lists call the tests were 463 // negotiating DHE-RSA-AES256-SHA by default which had 464 // very slow ephemeral RSA key generation 465 NativeCrypto.SSL_set_cipher_lists(s, new String[] { "RC4-MD5" }); 466 return s; 467 } 468 public void clientCertificateRequested(int s) {} 469 public void afterHandshake(int session, int ssl, int context, 470 Socket socket, FileDescriptor fd, 471 SSLHandshakeCallbacks callback) 472 throws Exception { 473 if (session != NULL) { 474 NativeCrypto.SSL_SESSION_free(session); 475 } 476 if (ssl != NULL) { 477 try { 478 NativeCrypto.SSL_shutdown(ssl, fd, callback); 479 } catch (IOException e) { 480 } 481 NativeCrypto.SSL_free(ssl); 482 } 483 if (context != NULL) { 484 NativeCrypto.SSL_CTX_free(context); 485 } 486 if (socket != null) { 487 socket.close(); 488 } 489 } 490 } 491 492 public static class TestSSLHandshakeCallbacks implements SSLHandshakeCallbacks { 493 private final int sslNativePointer; 494 private final Hooks hooks; 495 496 public TestSSLHandshakeCallbacks(int sslNativePointer, 497 Hooks hooks) { 498 this.sslNativePointer = sslNativePointer; 499 this.hooks = hooks; 500 } 501 502 public byte[][] asn1DerEncodedCertificateChain; 503 public String authMethod; 504 public boolean verifyCertificateChainCalled; 505 506 public void verifyCertificateChain(byte[][] asn1DerEncodedCertificateChain, 507 String authMethod) 508 throws CertificateException { 509 if (DEBUG) { 510 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16) 511 + " verifyCertificateChain" 512 + " asn1DerEncodedCertificateChain=" 513 + asn1DerEncodedCertificateChain 514 + " authMethod=" + authMethod); 515 } 516 this.asn1DerEncodedCertificateChain = asn1DerEncodedCertificateChain; 517 this.authMethod = authMethod; 518 this.verifyCertificateChainCalled = true; 519 return; 520 } 521 522 public byte[] keyTypes; 523 public byte[][] asn1DerEncodedX500Principals; 524 public boolean clientCertificateRequestedCalled; 525 public void clientCertificateRequested(byte[] keyTypes, 526 byte[][] asn1DerEncodedX500Principals) { 527 if (DEBUG) { 528 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16) 529 + " clientCertificateRequested" 530 + " keyTypes=" + keyTypes 531 + " asn1DerEncodedX500Principals=" 532 + asn1DerEncodedX500Principals); 533 } 534 this.keyTypes = keyTypes; 535 this.asn1DerEncodedX500Principals = asn1DerEncodedX500Principals; 536 this.clientCertificateRequestedCalled = true; 537 if (hooks != null ) { 538 hooks.clientCertificateRequested(sslNativePointer); 539 } 540 } 541 542 public boolean handshakeCompletedCalled; 543 public void handshakeCompleted() { 544 if (DEBUG) { 545 System.out.println("ssl=0x" + Integer.toString(sslNativePointer, 16) 546 + " handshakeCompleted"); 547 } 548 this.handshakeCompletedCalled = true; 549 return; 550 } 551 } 552 553 public static class ServerHooks extends Hooks { 554 private final byte[] privateKey; 555 private final byte[][] certificates; 556 public ServerHooks(byte[] privateKey, byte[][] certificates) { 557 this.privateKey = privateKey; 558 this.certificates = certificates; 559 } 560 561 @Override 562 public int beforeHandshake(int c) throws SSLException { 563 int s = super.beforeHandshake(c); 564 if (privateKey != null) { 565 NativeCrypto.SSL_use_PrivateKey(s, privateKey); 566 } 567 if (certificates != null) { 568 NativeCrypto.SSL_use_certificate(s, certificates); 569 } 570 return s; 571 } 572 public void clientCertificateRequested(int s) { 573 fail("Server asked for client certificates"); 574 } 575 } 576 577 public static Future<TestSSLHandshakeCallbacks> handshake(final ServerSocket listener, 578 final int timeout, 579 final boolean client, 580 final Hooks hooks) { 581 ExecutorService executor = Executors.newSingleThreadExecutor(); 582 Future future = executor.submit(new Callable<TestSSLHandshakeCallbacks>() { 583 public TestSSLHandshakeCallbacks call() throws Exception { 584 Socket socket = (client 585 ? new Socket(listener.getInetAddress(), 586 listener.getLocalPort()) 587 : listener.accept()); 588 if (timeout == -1) { 589 return null; 590 } 591 FileDescriptor fd = socket.getFileDescriptor$(); 592 int c = hooks.getContext(); 593 int s = hooks.beforeHandshake(c); 594 TestSSLHandshakeCallbacks callback = new TestSSLHandshakeCallbacks(s, hooks); 595 if (DEBUG) { 596 System.out.println("ssl=0x" + Integer.toString(s, 16) 597 + " handshake" 598 + " context=0x" + Integer.toString(c, 16) 599 + " socket=" + socket 600 + " fd=" + fd 601 + " timeout=" + timeout 602 + " client=" + client); 603 } 604 int session = NativeCrypto.SSL_do_handshake(s, 605 fd, 606 callback, 607 timeout, 608 client); 609 if (DEBUG) { 610 System.out.println("ssl=0x" + Integer.toString(s, 16) 611 + " handshake" 612 + " session=0x" + Integer.toString(session, 16)); 613 } 614 hooks.afterHandshake(session, s, c, socket, fd, callback); 615 return callback; 616 } 617 }); 618 executor.shutdown(); 619 return future; 620 } 621 622 public void test_SSL_do_handshake_NULL_SSL() throws Exception { 623 try { 624 NativeCrypto.SSL_do_handshake(NULL, null, null, 0, false); 625 fail(); 626 } catch (NullPointerException expected) { 627 } 628 } 629 630 public void test_SSL_do_handshake_null_args() throws Exception { 631 int c = NativeCrypto.SSL_CTX_new(); 632 int s = NativeCrypto.SSL_new(c); 633 634 try { 635 NativeCrypto.SSL_do_handshake(s, null, null, 0, true); 636 fail(); 637 } catch (NullPointerException e) { 638 } 639 640 try { 641 NativeCrypto.SSL_do_handshake(s, INVALID_FD, null, 0, true); 642 fail(); 643 } catch (NullPointerException e) { 644 } 645 646 NativeCrypto.SSL_free(s); 647 NativeCrypto.SSL_CTX_free(c); 648 } 649 650 public void test_SSL_do_handshake_normal() throws Exception { 651 // normal client and server case 652 final ServerSocket listener = new ServerSocket(0); 653 Hooks cHooks = new Hooks() { 654 @Override 655 public int beforeHandshake(int context) throws SSLException { 656 int s = super.beforeHandshake(context); 657 NativeCrypto.SSL_clear_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 658 return s; 659 } 660 }; 661 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 662 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 663 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 664 TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 665 TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 666 assertTrue(clientCallback.verifyCertificateChainCalled); 667 assertEqualCertificateChains(getServerCertificates(), 668 clientCallback.asn1DerEncodedCertificateChain); 669 assertEquals("RSA", clientCallback.authMethod); 670 assertFalse(serverCallback.verifyCertificateChainCalled); 671 assertFalse(clientCallback.clientCertificateRequestedCalled); 672 assertFalse(serverCallback.clientCertificateRequestedCalled); 673 assertTrue(clientCallback.handshakeCompletedCalled); 674 assertTrue(serverCallback.handshakeCompletedCalled); 675 } 676 677 public void test_SSL_do_handshake_optional_client_certificate() throws Exception { 678 // optional client certificate case 679 final ServerSocket listener = new ServerSocket(0); 680 681 Hooks cHooks = new Hooks() { 682 @Override 683 public int beforeHandshake(int context) throws SSLException { 684 int s = super.beforeHandshake(context); 685 NativeCrypto.SSL_clear_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 686 return s; 687 } 688 @Override 689 public void clientCertificateRequested(int s) { 690 super.clientCertificateRequested(s); 691 NativeCrypto.SSL_use_PrivateKey(s, getClientPrivateKey()); 692 NativeCrypto.SSL_use_certificate(s, getClientCertificates()); 693 } 694 }; 695 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 696 @Override 697 public int beforeHandshake(int c) throws SSLException { 698 int s = super.beforeHandshake(c); 699 NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals()); 700 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER); 701 return s; 702 } 703 }; 704 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 705 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 706 TestSSLHandshakeCallbacks clientCallback = client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 707 TestSSLHandshakeCallbacks serverCallback = server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 708 assertTrue(clientCallback.verifyCertificateChainCalled); 709 assertEqualCertificateChains(getServerCertificates(), 710 clientCallback.asn1DerEncodedCertificateChain); 711 assertEquals("RSA", clientCallback.authMethod); 712 assertTrue(serverCallback.verifyCertificateChainCalled); 713 assertEqualCertificateChains(getClientCertificates(), 714 serverCallback.asn1DerEncodedCertificateChain); 715 assertEquals("RSA", serverCallback.authMethod); 716 717 assertTrue(clientCallback.clientCertificateRequestedCalled); 718 assertNotNull(clientCallback.keyTypes); 719 // this depends on the SSL_set_cipher_lists call in beforeHandshake 720 // the three returned are the non-ephemeral cases. 721 assertEquals(3, clientCallback.keyTypes.length); 722 assertEquals("RSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[0])); 723 assertEquals("DSA", CipherSuite.getClientKeyType(clientCallback.keyTypes[1])); 724 assertEquals("EC", CipherSuite.getClientKeyType(clientCallback.keyTypes[2])); 725 assertEqualPrincipals(getCaPrincipals(), 726 clientCallback.asn1DerEncodedX500Principals); 727 assertFalse(serverCallback.clientCertificateRequestedCalled); 728 729 assertTrue(clientCallback.handshakeCompletedCalled); 730 assertTrue(serverCallback.handshakeCompletedCalled); 731 } 732 733 public void test_SSL_do_handshake_missing_required_certificate() throws Exception { 734 // required client certificate negative case 735 final ServerSocket listener = new ServerSocket(0); 736 try { 737 Hooks cHooks = new Hooks(); 738 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 739 @Override 740 public int beforeHandshake(int c) throws SSLException { 741 int s = super.beforeHandshake(c); 742 NativeCrypto.SSL_set_client_CA_list(s, getCaPrincipals()); 743 NativeCrypto.SSL_set_verify(s, 744 NativeCrypto.SSL_VERIFY_PEER 745 | NativeCrypto.SSL_VERIFY_FAIL_IF_NO_PEER_CERT); 746 return s; 747 } 748 }; 749 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 750 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 751 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 752 fail(); 753 } catch (ExecutionException expected) { 754 assertEquals(SSLProtocolException.class, expected.getCause().getClass()); 755 } 756 } 757 758 /** 759 * Usually if a RuntimeException is thrown by the 760 * clientCertificateRequestedCalled callback, the caller sees it 761 * during the call to NativeCrypto_SSL_do_handshake. However, IIS 762 * does not request client certs until after the initial 763 * handshake. It does an SSL renegotiation, which means we need to 764 * be able to deliver the callback's exception in cases like 765 * SSL_read, SSL_write, and SSL_shutdown. 766 */ 767 public void test_SSL_do_handshake_clientCertificateRequested_throws_after_renegotiate() 768 throws Exception { 769 final ServerSocket listener = new ServerSocket(0); 770 771 Hooks cHooks = new Hooks() { 772 @Override 773 public int beforeHandshake(int context) throws SSLException { 774 int s = super.beforeHandshake(context); 775 NativeCrypto.SSL_clear_mode(s, NativeCrypto.SSL_MODE_HANDSHAKE_CUTTHROUGH); 776 return s; 777 } 778 @Override 779 public void afterHandshake(int session, int s, int c, 780 Socket sock, FileDescriptor fd, 781 SSLHandshakeCallbacks callback) 782 throws Exception { 783 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0); 784 fail(); 785 super.afterHandshake(session, s, c, sock, fd, callback); 786 } 787 @Override 788 public void clientCertificateRequested(int s) { 789 super.clientCertificateRequested(s); 790 throw new RuntimeException("expected"); 791 } 792 }; 793 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 794 @Override 795 public void afterHandshake(int session, int s, int c, 796 Socket sock, FileDescriptor fd, 797 SSLHandshakeCallbacks callback) 798 throws Exception { 799 NativeCrypto.SSL_set_verify(s, NativeCrypto.SSL_VERIFY_PEER); 800 NativeCrypto.SSL_renegotiate(s); 801 NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1); 802 super.afterHandshake(session, s, c, sock, fd, callback); 803 } 804 }; 805 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 806 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 807 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 808 try { 809 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 810 } catch (ExecutionException e) { 811 if (!"expected".equals(e.getCause().getMessage())) { 812 throw e; 813 } 814 } 815 } 816 817 public void test_SSL_do_handshake_client_timeout() throws Exception { 818 // client timeout 819 final ServerSocket listener = new ServerSocket(0); 820 try { 821 Hooks cHooks = new Hooks(); 822 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 823 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 1, true, cHooks); 824 Future<TestSSLHandshakeCallbacks> server = handshake(listener, -1, false, sHooks); 825 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 826 fail(); 827 } catch (ExecutionException expected) { 828 assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); 829 } 830 } 831 832 public void test_SSL_do_handshake_server_timeout() throws Exception { 833 // server timeout 834 final ServerSocket listener = new ServerSocket(0); 835 try { 836 Hooks cHooks = new Hooks(); 837 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 838 Future<TestSSLHandshakeCallbacks> client = handshake(listener, -1, true, cHooks); 839 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 1, false, sHooks); 840 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 841 fail(); 842 } catch (ExecutionException expected) { 843 assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); 844 } 845 } 846 847 public void test_SSL_set_session() throws Exception { 848 try { 849 NativeCrypto.SSL_set_session(NULL, NULL); 850 fail(); 851 } catch (NullPointerException expected) { 852 } 853 854 { 855 int c = NativeCrypto.SSL_CTX_new(); 856 int s = NativeCrypto.SSL_new(c); 857 NativeCrypto.SSL_set_session(s, NULL); 858 NativeCrypto.SSL_free(s); 859 NativeCrypto.SSL_CTX_free(c); 860 } 861 862 { 863 final int clientContext = NativeCrypto.SSL_CTX_new(); 864 final int serverContext = NativeCrypto.SSL_CTX_new(); 865 final ServerSocket listener = new ServerSocket(0); 866 final int[] clientSession = new int[] { NULL }; 867 final int[] serverSession = new int[] { NULL }; 868 { 869 Hooks cHooks = new Hooks() { 870 @Override 871 public int getContext() throws SSLException { 872 return clientContext; 873 } 874 @Override 875 public void afterHandshake(int session, int s, int c, 876 Socket sock, FileDescriptor fd, 877 SSLHandshakeCallbacks callback) 878 throws Exception { 879 super.afterHandshake(NULL, s, NULL, sock, fd, callback); 880 clientSession[0] = session; 881 } 882 }; 883 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 884 @Override 885 public int getContext() throws SSLException { 886 return serverContext; 887 } 888 @Override 889 public void afterHandshake(int session, int s, int c, 890 Socket sock, FileDescriptor fd, 891 SSLHandshakeCallbacks callback) 892 throws Exception { 893 super.afterHandshake(NULL, s, NULL, sock, fd, callback); 894 serverSession[0] = session; 895 } 896 }; 897 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 898 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 899 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 900 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 901 } 902 assertEqualSessions(clientSession[0], serverSession[0]); 903 { 904 Hooks cHooks = new Hooks() { 905 @Override 906 public int getContext() throws SSLException { 907 return clientContext; 908 } 909 @Override 910 public int beforeHandshake(int c) throws SSLException { 911 int s = NativeCrypto.SSL_new(clientContext); 912 NativeCrypto.SSL_set_session(s, clientSession[0]); 913 return s; 914 } 915 @Override 916 public void afterHandshake(int session, int s, int c, 917 Socket sock, FileDescriptor fd, 918 SSLHandshakeCallbacks callback) 919 throws Exception { 920 assertEqualSessions(clientSession[0], session); 921 super.afterHandshake(NULL, s, NULL, sock, fd, callback); 922 } 923 }; 924 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 925 @Override 926 public int getContext() throws SSLException { 927 return serverContext; 928 } 929 @Override 930 public void afterHandshake(int session, int s, int c, 931 Socket sock, FileDescriptor fd, 932 SSLHandshakeCallbacks callback) 933 throws Exception { 934 assertEqualSessions(serverSession[0], session); 935 super.afterHandshake(NULL, s, NULL, sock, fd, callback); 936 } 937 }; 938 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 939 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 940 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 941 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 942 } 943 NativeCrypto.SSL_SESSION_free(clientSession[0]); 944 NativeCrypto.SSL_SESSION_free(serverSession[0]); 945 NativeCrypto.SSL_CTX_free(serverContext); 946 NativeCrypto.SSL_CTX_free(clientContext); 947 } 948 } 949 950 public void test_SSL_set_session_creation_enabled() throws Exception { 951 try { 952 NativeCrypto.SSL_set_session_creation_enabled(NULL, false); 953 fail(); 954 } catch (NullPointerException expected) { 955 } 956 957 { 958 int c = NativeCrypto.SSL_CTX_new(); 959 int s = NativeCrypto.SSL_new(c); 960 NativeCrypto.SSL_set_session_creation_enabled(s, false); 961 NativeCrypto.SSL_set_session_creation_enabled(s, true); 962 NativeCrypto.SSL_free(s); 963 NativeCrypto.SSL_CTX_free(c); 964 } 965 966 final ServerSocket listener = new ServerSocket(0); 967 968 // negative test case for SSL_set_session_creation_enabled(false) on client 969 try { 970 Hooks cHooks = new Hooks() { 971 @Override 972 public int beforeHandshake(int c) throws SSLException { 973 int s = super.beforeHandshake(c); 974 NativeCrypto.SSL_set_session_creation_enabled(s, false); 975 return s; 976 } 977 }; 978 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 979 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 980 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 981 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 982 fail(); 983 } catch (ExecutionException expected) { 984 assertEquals(SSLProtocolException.class, expected.getCause().getClass()); 985 } 986 987 // negative test case for SSL_set_session_creation_enabled(false) on server 988 try { 989 Hooks cHooks = new Hooks(); 990 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 991 @Override 992 public int beforeHandshake(int c) throws SSLException { 993 int s = super.beforeHandshake(c); 994 NativeCrypto.SSL_set_session_creation_enabled(s, false); 995 return s; 996 } 997 }; 998 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 999 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1000 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1001 fail(); 1002 } catch (ExecutionException expected) { 1003 assertEquals(SSLProtocolException.class, expected.getCause().getClass()); 1004 } 1005 } 1006 1007 public void test_SSL_set_tlsext_host_name() throws Exception { 1008 // NULL SSL 1009 try { 1010 NativeCrypto.SSL_set_tlsext_host_name(NULL, null); 1011 fail(); 1012 } catch (NullPointerException expected) { 1013 } 1014 1015 final String hostname = "www.android.com"; 1016 1017 { 1018 int c = NativeCrypto.SSL_CTX_new(); 1019 int s = NativeCrypto.SSL_new(c); 1020 1021 // null hostname 1022 try { 1023 NativeCrypto.SSL_set_tlsext_host_name(s, null); 1024 fail(); 1025 } catch (NullPointerException expected) { 1026 } 1027 1028 // too long hostname 1029 try { 1030 char[] longHostname = new char[256]; 1031 Arrays.fill(longHostname, 'w'); 1032 NativeCrypto.SSL_set_tlsext_host_name(s, new String(longHostname)); 1033 fail(); 1034 } catch (SSLException expected) { 1035 } 1036 1037 assertNull(NativeCrypto.SSL_get_servername(s)); 1038 NativeCrypto.SSL_set_tlsext_host_name(s, new String(hostname)); 1039 assertEquals(hostname, NativeCrypto.SSL_get_servername(s)); 1040 1041 NativeCrypto.SSL_free(s); 1042 NativeCrypto.SSL_CTX_free(c); 1043 } 1044 1045 final ServerSocket listener = new ServerSocket(0); 1046 1047 // normal 1048 Hooks cHooks = new Hooks() { 1049 @Override 1050 public int beforeHandshake(int c) throws SSLException { 1051 int s = super.beforeHandshake(c); 1052 NativeCrypto.SSL_set_tlsext_host_name(s, hostname); 1053 return s; 1054 } 1055 }; 1056 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1057 @Override 1058 public void afterHandshake(int session, int s, int c, 1059 Socket sock, FileDescriptor fd, 1060 SSLHandshakeCallbacks callback) 1061 throws Exception { 1062 assertEquals(hostname, NativeCrypto.SSL_get_servername(s)); 1063 super.afterHandshake(session, s, c, sock, fd, callback); 1064 } 1065 }; 1066 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1067 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1068 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1069 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1070 } 1071 1072 public void test_SSL_get_servername_null() throws Exception { 1073 // NULL SSL 1074 try { 1075 NativeCrypto.SSL_get_servername(NULL); 1076 fail(); 1077 } catch (NullPointerException expected) { 1078 } 1079 1080 int c = NativeCrypto.SSL_CTX_new(); 1081 int s = NativeCrypto.SSL_new(c); 1082 assertNull(NativeCrypto.SSL_get_servername(s)); 1083 NativeCrypto.SSL_free(s); 1084 NativeCrypto.SSL_CTX_free(c); 1085 1086 // additional positive testing by test_SSL_set_tlsext_host_name 1087 } 1088 1089 public void test_SSL_renegotiate() throws Exception { 1090 try { 1091 NativeCrypto.SSL_renegotiate(NULL); 1092 fail(); 1093 } catch (NullPointerException expected) { 1094 } 1095 1096 final ServerSocket listener = new ServerSocket(0); 1097 Hooks cHooks = new Hooks() { 1098 @Override 1099 public void afterHandshake(int session, int s, int c, 1100 Socket sock, FileDescriptor fd, 1101 SSLHandshakeCallbacks callback) 1102 throws Exception { 1103 byte[] buffer = new byte[1]; 1104 NativeCrypto.SSL_read(s, fd, callback, buffer, 0, 1, 0); 1105 assertEquals(42, buffer[0]); 1106 super.afterHandshake(session, s, c, sock, fd, callback); 1107 } 1108 }; 1109 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1110 @Override 1111 public void afterHandshake(int session, int s, int c, 1112 Socket sock, FileDescriptor fd, 1113 SSLHandshakeCallbacks callback) 1114 throws Exception { 1115 NativeCrypto.SSL_renegotiate(s); 1116 NativeCrypto.SSL_write(s, fd, callback, new byte[] { 42 }, 0, 1); 1117 super.afterHandshake(session, s, c, sock, fd, callback); 1118 } 1119 }; 1120 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1121 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1122 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1123 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1124 } 1125 1126 public void test_SSL_get_certificate() throws Exception { 1127 try { 1128 NativeCrypto.SSL_get_certificate(NULL); 1129 fail(); 1130 } catch (NullPointerException expected) { 1131 } 1132 1133 final ServerSocket listener = new ServerSocket(0); 1134 Hooks cHooks = new Hooks() { 1135 @Override 1136 public void afterHandshake(int session, int s, int c, 1137 Socket sock, FileDescriptor fd, 1138 SSLHandshakeCallbacks callback) 1139 throws Exception { 1140 assertNull(NativeCrypto.SSL_get_certificate(s)); 1141 super.afterHandshake(session, s, c, sock, fd, callback); 1142 } 1143 }; 1144 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1145 @Override 1146 public void afterHandshake(int session, int s, int c, 1147 Socket sock, FileDescriptor fd, 1148 SSLHandshakeCallbacks callback) 1149 throws Exception { 1150 assertEqualCertificateChains( 1151 getServerCertificates(), 1152 NativeCrypto.SSL_get_certificate(s)); 1153 super.afterHandshake(session, s, c, sock, fd, callback); 1154 } 1155 }; 1156 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1157 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1158 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1159 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1160 } 1161 1162 public void test_SSL_get_peer_cert_chain() throws Exception { 1163 try { 1164 NativeCrypto.SSL_get_peer_cert_chain(NULL); 1165 fail(); 1166 } catch (NullPointerException expected) { 1167 } 1168 1169 final ServerSocket listener = new ServerSocket(0); 1170 1171 Hooks cHooks = new Hooks() { 1172 @Override 1173 public void afterHandshake(int session, int s, int c, 1174 Socket sock, FileDescriptor fd, 1175 SSLHandshakeCallbacks callback) 1176 throws Exception { 1177 byte[][] cc = NativeCrypto.SSL_get_peer_cert_chain(s); 1178 assertEqualCertificateChains(getServerCertificates(), cc); 1179 super.afterHandshake(session, s, c, sock, fd, callback); 1180 } 1181 }; 1182 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1183 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1184 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1185 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1186 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1187 } 1188 1189 final byte[] BYTES = new byte[] { 2, -3, 5, 127, 0, -128 }; 1190 1191 public void test_SSL_read() throws Exception { 1192 1193 // NULL ssl 1194 try { 1195 NativeCrypto.SSL_read(NULL, null, null, null, 0, 0, 0); 1196 fail(); 1197 } catch (NullPointerException expected) { 1198 } 1199 1200 // null FileDescriptor 1201 { 1202 int c = NativeCrypto.SSL_CTX_new(); 1203 int s = NativeCrypto.SSL_new(c); 1204 try { 1205 NativeCrypto.SSL_read(s, null, DUMMY_CB, null, 0, 0, 0); 1206 fail(); 1207 } catch (NullPointerException expected) { 1208 } 1209 NativeCrypto.SSL_free(s); 1210 NativeCrypto.SSL_CTX_free(c); 1211 } 1212 1213 // null SSLHandshakeCallbacks 1214 { 1215 int c = NativeCrypto.SSL_CTX_new(); 1216 int s = NativeCrypto.SSL_new(c); 1217 try { 1218 NativeCrypto.SSL_read(s, INVALID_FD, null, null, 0, 0, 0); 1219 fail(); 1220 } catch (NullPointerException expected) { 1221 } 1222 NativeCrypto.SSL_free(s); 1223 NativeCrypto.SSL_CTX_free(c); 1224 } 1225 1226 // null byte array 1227 { 1228 int c = NativeCrypto.SSL_CTX_new(); 1229 int s = NativeCrypto.SSL_new(c); 1230 try { 1231 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, null, 0, 0, 0); 1232 fail(); 1233 } catch (NullPointerException expected) { 1234 } 1235 NativeCrypto.SSL_free(s); 1236 NativeCrypto.SSL_CTX_free(c); 1237 } 1238 1239 // handshaking not yet performed 1240 { 1241 int c = NativeCrypto.SSL_CTX_new(); 1242 int s = NativeCrypto.SSL_new(c); 1243 try { 1244 NativeCrypto.SSL_read(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1, 0); 1245 fail(); 1246 } catch (SSLException expected) { 1247 } 1248 NativeCrypto.SSL_free(s); 1249 NativeCrypto.SSL_CTX_free(c); 1250 } 1251 1252 final ServerSocket listener = new ServerSocket(0); 1253 1254 // normal case 1255 { 1256 Hooks cHooks = new Hooks() { 1257 @Override 1258 public void afterHandshake(int session, int s, int c, 1259 Socket sock, FileDescriptor fd, 1260 SSLHandshakeCallbacks callback) 1261 throws Exception { 1262 byte[] in = new byte[256]; 1263 assertEquals(BYTES.length, 1264 NativeCrypto.SSL_read(s, 1265 fd, 1266 callback, 1267 in, 1268 0, 1269 BYTES.length, 1270 0)); 1271 for (int i = 0; i < BYTES.length; i++) { 1272 assertEquals(BYTES[i], in[i]); 1273 } 1274 super.afterHandshake(session, s, c, sock, fd, callback); 1275 } 1276 }; 1277 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1278 @Override 1279 public void afterHandshake(int session, int s, int c, 1280 Socket sock, FileDescriptor fd, 1281 SSLHandshakeCallbacks callback) 1282 throws Exception { 1283 NativeCrypto.SSL_write(s, fd, callback, BYTES, 0, BYTES.length); 1284 super.afterHandshake(session, s, c, sock, fd, callback); 1285 } 1286 }; 1287 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1288 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1289 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1290 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1291 } 1292 1293 // timeout case 1294 try { 1295 Hooks cHooks = new Hooks() { 1296 @Override 1297 public void afterHandshake(int session, int s, int c, 1298 Socket sock, FileDescriptor fd, 1299 SSLHandshakeCallbacks callback) 1300 throws Exception { 1301 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 1); 1302 fail(); 1303 } 1304 }; 1305 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1306 @Override 1307 public void afterHandshake(int session, int s, int c, 1308 Socket sock, FileDescriptor fd, 1309 SSLHandshakeCallbacks callback) 1310 throws Exception { 1311 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0); 1312 super.afterHandshake(session, s, c, sock, fd, callback); 1313 } 1314 }; 1315 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1316 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1317 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1318 fail(); 1319 } catch (ExecutionException expected) { 1320 assertEquals(SocketTimeoutException.class, expected.getCause().getClass()); 1321 } 1322 } 1323 1324 public void test_SSL_write() throws Exception { 1325 try { 1326 NativeCrypto.SSL_write(NULL, null, null, null, 0, 0); 1327 fail(); 1328 } catch (NullPointerException expected) { 1329 } 1330 1331 // null FileDescriptor 1332 { 1333 int c = NativeCrypto.SSL_CTX_new(); 1334 int s = NativeCrypto.SSL_new(c); 1335 try { 1336 NativeCrypto.SSL_write(s, null, DUMMY_CB, null, 0, 1); 1337 fail(); 1338 } catch (NullPointerException expected) { 1339 } 1340 NativeCrypto.SSL_free(s); 1341 NativeCrypto.SSL_CTX_free(c); 1342 } 1343 1344 // null SSLHandshakeCallbacks 1345 { 1346 int c = NativeCrypto.SSL_CTX_new(); 1347 int s = NativeCrypto.SSL_new(c); 1348 try { 1349 NativeCrypto.SSL_write(s, INVALID_FD, null, null, 0, 1); 1350 fail(); 1351 } catch (NullPointerException expected) { 1352 } 1353 NativeCrypto.SSL_free(s); 1354 NativeCrypto.SSL_CTX_free(c); 1355 } 1356 1357 // null byte array 1358 { 1359 int c = NativeCrypto.SSL_CTX_new(); 1360 int s = NativeCrypto.SSL_new(c); 1361 try { 1362 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, null, 0, 1); 1363 fail(); 1364 } catch (NullPointerException expected) { 1365 } 1366 NativeCrypto.SSL_free(s); 1367 NativeCrypto.SSL_CTX_free(c); 1368 } 1369 1370 // handshaking not yet performed 1371 { 1372 int c = NativeCrypto.SSL_CTX_new(); 1373 int s = NativeCrypto.SSL_new(c); 1374 try { 1375 NativeCrypto.SSL_write(s, INVALID_FD, DUMMY_CB, new byte[1], 0, 1); 1376 fail(); 1377 } catch (SSLException expected) { 1378 } 1379 NativeCrypto.SSL_free(s); 1380 NativeCrypto.SSL_CTX_free(c); 1381 } 1382 1383 // positively tested by test_SSL_read 1384 } 1385 1386 public void test_SSL_interrupt() throws Exception { 1387 // SSL_interrupt is a rare case that tolerates a null SSL argument 1388 NativeCrypto.SSL_interrupt(NULL); 1389 1390 // also works without handshaking 1391 { 1392 int c = NativeCrypto.SSL_CTX_new(); 1393 int s = NativeCrypto.SSL_new(c); 1394 NativeCrypto.SSL_interrupt(s); 1395 NativeCrypto.SSL_free(s); 1396 NativeCrypto.SSL_CTX_free(c); 1397 } 1398 1399 final ServerSocket listener = new ServerSocket(0); 1400 1401 Hooks cHooks = new Hooks() { 1402 @Override 1403 public void afterHandshake(int session, int s, int c, 1404 Socket sock, FileDescriptor fd, 1405 SSLHandshakeCallbacks callback) 1406 throws Exception { 1407 NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0); 1408 super.afterHandshake(session, s, c, sock, fd, callback); 1409 } 1410 }; 1411 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1412 @Override 1413 public void afterHandshake(int session, final int s, int c, 1414 Socket sock, FileDescriptor fd, 1415 SSLHandshakeCallbacks callback) 1416 throws Exception { 1417 new Thread() { 1418 public void run() { 1419 try { 1420 Thread.sleep(1*1000); 1421 NativeCrypto.SSL_interrupt(s); 1422 } catch (Exception e) { 1423 } 1424 } 1425 }.start(); 1426 assertEquals(-1, NativeCrypto.SSL_read(s, fd, callback, new byte[1], 0, 1, 0)); 1427 super.afterHandshake(session, s, c, sock, fd, callback); 1428 } 1429 }; 1430 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1431 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1432 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1433 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1434 } 1435 1436 public void test_SSL_shutdown() throws Exception { 1437 1438 // null FileDescriptor 1439 try { 1440 NativeCrypto.SSL_shutdown(NULL, null, DUMMY_CB); 1441 } catch (NullPointerException expected) { 1442 } 1443 1444 // null SSLHandshakeCallbacks 1445 try { 1446 NativeCrypto.SSL_shutdown(NULL, INVALID_FD, null); 1447 } catch (NullPointerException expected) { 1448 } 1449 1450 // SSL_shutdown is a rare case that tolerates a null SSL argument 1451 NativeCrypto.SSL_shutdown(NULL, INVALID_FD, DUMMY_CB); 1452 1453 // handshaking not yet performed 1454 int c = NativeCrypto.SSL_CTX_new(); 1455 int s = NativeCrypto.SSL_new(c); 1456 try { 1457 NativeCrypto.SSL_shutdown(s, INVALID_FD, DUMMY_CB); 1458 } catch (SSLProtocolException expected) { 1459 } 1460 NativeCrypto.SSL_free(s); 1461 NativeCrypto.SSL_CTX_free(c); 1462 1463 // positively tested elsewhere because handshake uses use 1464 // SSL_shutdown to ensure SSL_SESSIONs are reused. 1465 } 1466 1467 public void test_SSL_free() throws Exception { 1468 try { 1469 NativeCrypto.SSL_free(NULL); 1470 fail(); 1471 } catch (NullPointerException expected) { 1472 } 1473 1474 int c = NativeCrypto.SSL_CTX_new(); 1475 NativeCrypto.SSL_free(NativeCrypto.SSL_new(c)); 1476 NativeCrypto.SSL_CTX_free(c); 1477 1478 // additional positive testing elsewhere because handshake 1479 // uses use SSL_free to cleanup in afterHandshake. 1480 } 1481 1482 public void test_SSL_SESSION_session_id() throws Exception { 1483 try { 1484 NativeCrypto.SSL_SESSION_session_id(NULL); 1485 fail(); 1486 } catch (NullPointerException expected) { 1487 } 1488 1489 final ServerSocket listener = new ServerSocket(0); 1490 1491 Hooks cHooks = new Hooks() { 1492 @Override 1493 public void afterHandshake(int session, int s, int c, 1494 Socket sock, FileDescriptor fd, 1495 SSLHandshakeCallbacks callback) 1496 throws Exception { 1497 byte[] id = NativeCrypto.SSL_SESSION_session_id(session); 1498 assertNotNull(id); 1499 assertEquals(32, id.length); 1500 super.afterHandshake(session, s, c, sock, fd, callback); 1501 } 1502 }; 1503 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1504 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1505 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1506 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1507 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1508 } 1509 1510 public void test_SSL_SESSION_get_time() throws Exception { 1511 try { 1512 NativeCrypto.SSL_SESSION_get_time(NULL); 1513 fail(); 1514 } catch (NullPointerException expected) { 1515 } 1516 1517 final ServerSocket listener = new ServerSocket(0); 1518 1519 { 1520 Hooks cHooks = new Hooks() { 1521 @Override 1522 public void afterHandshake(int session, int s, int c, 1523 Socket sock, FileDescriptor fd, 1524 SSLHandshakeCallbacks callback) 1525 throws Exception { 1526 long time = NativeCrypto.SSL_SESSION_get_time(session); 1527 assertTrue(time != 0); 1528 assertTrue(time < System.currentTimeMillis()); 1529 super.afterHandshake(session, s, c, sock, fd, callback); 1530 } 1531 }; 1532 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1533 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1534 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1535 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1536 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1537 } 1538 } 1539 1540 public void test_SSL_SESSION_get_version() throws Exception { 1541 try { 1542 NativeCrypto.SSL_SESSION_get_version(NULL); 1543 fail(); 1544 } catch (NullPointerException expected) { 1545 } 1546 1547 final ServerSocket listener = new ServerSocket(0); 1548 1549 Hooks cHooks = new Hooks() { 1550 @Override 1551 public void afterHandshake(int session, int s, int c, 1552 Socket sock, FileDescriptor fd, 1553 SSLHandshakeCallbacks callback) 1554 throws Exception { 1555 String v = NativeCrypto.SSL_SESSION_get_version(session); 1556 assertTrue(StandardNames.SSL_SOCKET_PROTOCOLS.contains(v)); 1557 super.afterHandshake(session, s, c, sock, fd, callback); 1558 } 1559 }; 1560 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1561 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1562 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1563 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1564 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1565 } 1566 1567 public void test_SSL_SESSION_cipher() throws Exception { 1568 try { 1569 NativeCrypto.SSL_SESSION_cipher(NULL); 1570 fail(); 1571 } catch (NullPointerException expected) { 1572 } 1573 1574 final ServerSocket listener = new ServerSocket(0); 1575 1576 Hooks cHooks = new Hooks() { 1577 @Override 1578 public void afterHandshake(int session, int s, int c, 1579 Socket sock, FileDescriptor fd, 1580 SSLHandshakeCallbacks callback) 1581 throws Exception { 1582 String a = NativeCrypto.SSL_SESSION_cipher(session); 1583 assertTrue(NativeCrypto.OPENSSL_TO_STANDARD_CIPHER_SUITES.containsKey(a)); 1584 super.afterHandshake(session, s, c, sock, fd, callback); 1585 } 1586 }; 1587 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1588 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1589 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1590 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1591 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1592 } 1593 1594 public void test_SSL_SESSION_compress_meth_null() throws Exception { 1595 try { 1596 NativeCrypto.SSL_SESSION_compress_meth(NULL, NULL); 1597 fail(); 1598 } catch (NullPointerException expected) { 1599 } 1600 1601 { 1602 int c = NativeCrypto.SSL_CTX_new(); 1603 try { 1604 NativeCrypto.SSL_SESSION_compress_meth(c, NULL); 1605 } catch (NullPointerException expected) { 1606 } 1607 NativeCrypto.SSL_CTX_free(c); 1608 } 1609 } 1610 1611 public void test_SSL_SESSION_compress_meth_NULL() throws Exception { 1612 final ServerSocket listener = new ServerSocket(0); 1613 1614 Hooks cHooks = new Hooks() { 1615 @Override 1616 public void afterHandshake(int session, int s, int c, 1617 Socket sock, FileDescriptor fd, 1618 SSLHandshakeCallbacks callback) 1619 throws Exception { 1620 assertEquals("NULL", NativeCrypto.SSL_SESSION_compress_meth(c, session)); 1621 super.afterHandshake(session, s, c, sock, fd, callback); 1622 } 1623 }; 1624 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1625 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1626 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1627 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1628 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1629 } 1630 1631 public void test_SSL_SESSION_compress_meth_ZLIB() throws Exception { 1632 final ServerSocket listener = new ServerSocket(0); 1633 1634 Hooks cHooks = new Hooks() { 1635 @Override 1636 public int beforeHandshake(int c) throws SSLException { 1637 int s = super.beforeHandshake(c); 1638 NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION); 1639 return s; 1640 } 1641 @Override 1642 public void afterHandshake(int session, int s, int c, 1643 Socket sock, FileDescriptor fd, 1644 SSLHandshakeCallbacks callback) 1645 throws Exception { 1646 assertEquals("ZLIB", NativeCrypto.SSL_SESSION_compress_meth(c, session)); 1647 super.afterHandshake(session, s, c, sock, fd, callback); 1648 } 1649 }; 1650 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()) { 1651 @Override 1652 public int beforeHandshake(int c) throws SSLException { 1653 int s = super.beforeHandshake(c); 1654 NativeCrypto.SSL_clear_options(s, NativeCrypto.SSL_OP_NO_COMPRESSION); 1655 return s; 1656 } 1657 }; 1658 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1659 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1660 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1661 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1662 } 1663 1664 public void test_SSL_SESSION_free() throws Exception { 1665 try { 1666 NativeCrypto.SSL_SESSION_free(NULL); 1667 fail(); 1668 } catch (NullPointerException expected) { 1669 } 1670 1671 // additional positive testing elsewhere because handshake 1672 // uses use SSL_SESSION_free to cleanup in afterHandshake. 1673 } 1674 1675 public void test_i2d_SSL_SESSION() throws Exception { 1676 try { 1677 NativeCrypto.i2d_SSL_SESSION(NULL); 1678 fail(); 1679 } catch (NullPointerException expected) { 1680 } 1681 1682 final ServerSocket listener = new ServerSocket(0); 1683 1684 Hooks cHooks = new Hooks() { 1685 @Override 1686 public void afterHandshake(int session, int s, int c, 1687 Socket sock, FileDescriptor fd, 1688 SSLHandshakeCallbacks callback) 1689 throws Exception { 1690 byte[] b = NativeCrypto.i2d_SSL_SESSION(session); 1691 assertNotNull(b); 1692 int session2 = NativeCrypto.d2i_SSL_SESSION(b); 1693 assertTrue(session2 != NULL); 1694 NativeCrypto.SSL_SESSION_free(session2); 1695 super.afterHandshake(session, s, c, sock, fd, callback); 1696 } 1697 }; 1698 Hooks sHooks = new ServerHooks(getServerPrivateKey(), getServerCertificates()); 1699 Future<TestSSLHandshakeCallbacks> client = handshake(listener, 0, true, cHooks); 1700 Future<TestSSLHandshakeCallbacks> server = handshake(listener, 0, false, sHooks); 1701 client.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1702 server.get(TIMEOUT_SECONDS, TimeUnit.SECONDS); 1703 } 1704 1705 public void test_d2i_SSL_SESSION() throws Exception { 1706 try { 1707 NativeCrypto.d2i_SSL_SESSION(null); 1708 fail(); 1709 } catch (NullPointerException expected) { 1710 } 1711 1712 assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[0])); 1713 assertEquals(NULL, NativeCrypto.d2i_SSL_SESSION(new byte[1])); 1714 1715 // positively testing by test_i2d_SSL_SESSION 1716 } 1717 1718 public void test_X509_NAME_hashes() { 1719 // ensure these hash functions are stable over time since the 1720 // /system/etc/security/cacerts CA filenames have to be 1721 // consistent with the output. 1722 X500Principal name = new X500Principal("CN=localhost"); 1723 assertEquals(-1372642656, NativeCrypto.X509_NAME_hash(name)); // SHA1 1724 assertEquals(-1626170662, NativeCrypto.X509_NAME_hash_old(name)); // MD5 1725 } 1726 } 1727