1/* 2 * Copyright (C) 2007 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 17package org.conscrypt; 18 19import org.conscrypt.util.Arrays; 20import dalvik.system.BlockGuard; 21import dalvik.system.CloseGuard; 22import java.io.FileDescriptor; 23import java.io.IOException; 24import java.io.InputStream; 25import java.io.OutputStream; 26import java.net.InetAddress; 27import java.net.Socket; 28import java.net.SocketException; 29import java.security.InvalidKeyException; 30import java.security.PrivateKey; 31import java.security.SecureRandom; 32import java.security.cert.CertificateEncodingException; 33import java.security.cert.CertificateException; 34import java.util.ArrayList; 35import javax.crypto.SecretKey; 36import javax.net.ssl.HandshakeCompletedEvent; 37import javax.net.ssl.HandshakeCompletedListener; 38import javax.net.ssl.SSLException; 39import javax.net.ssl.SSLHandshakeException; 40import javax.net.ssl.SSLParameters; 41import javax.net.ssl.SSLProtocolException; 42import javax.net.ssl.SSLSession; 43import javax.net.ssl.X509KeyManager; 44import javax.net.ssl.X509TrustManager; 45import javax.security.auth.x500.X500Principal; 46 47/** 48 * Implementation of the class OpenSSLSocketImpl based on OpenSSL. 49 * <p> 50 * Extensions to SSLSocket include: 51 * <ul> 52 * <li>handshake timeout 53 * <li>session tickets 54 * <li>Server Name Indication 55 * </ul> 56 */ 57public class OpenSSLSocketImpl 58 extends javax.net.ssl.SSLSocket 59 implements NativeCrypto.SSLHandshakeCallbacks, SSLParametersImpl.AliasChooser, 60 SSLParametersImpl.PSKCallbacks { 61 62 private static final boolean DBG_STATE = false; 63 64 /** 65 * Protects handshakeStarted and handshakeCompleted. 66 */ 67 private final Object stateLock = new Object(); 68 69 /** 70 * The {@link OpenSSLSocketImpl} object is constructed, but {@link #startHandshake()} 71 * has not yet been called. 72 */ 73 private static final int STATE_NEW = 0; 74 75 /** 76 * {@link #startHandshake()} has been called at least once. 77 */ 78 private static final int STATE_HANDSHAKE_STARTED = 1; 79 80 /** 81 * {@link #handshakeCompleted()} has been called, but {@link #startHandshake()} hasn't 82 * returned yet. 83 */ 84 private static final int STATE_HANDSHAKE_COMPLETED = 2; 85 86 /** 87 * {@link #startHandshake()} has completed but {@link #handshakeCompleted()} hasn't 88 * been called. This is expected behaviour in cut-through mode, where SSL_do_handshake 89 * returns before the handshake is complete. We can now start writing data to the socket. 90 */ 91 private static final int STATE_READY_HANDSHAKE_CUT_THROUGH = 3; 92 93 /** 94 * {@link #startHandshake()} has completed and {@link #handshakeCompleted()} has been 95 * called. 96 */ 97 private static final int STATE_READY = 4; 98 99 /** 100 * {@link #close()} has been called at least once. 101 */ 102 private static final int STATE_CLOSED = 5; 103 104 // @GuardedBy("stateLock"); 105 private int state = STATE_NEW; 106 107 /** 108 * Protected by synchronizing on stateLock. Starts as 0, set by 109 * startHandshake, reset to 0 on close. 110 */ 111 // @GuardedBy("stateLock"); 112 private long sslNativePointer; 113 114 /** 115 * Protected by synchronizing on stateLock. Starts as null, set by 116 * getInputStream. 117 */ 118 // @GuardedBy("stateLock"); 119 private SSLInputStream is; 120 121 /** 122 * Protected by synchronizing on stateLock. Starts as null, set by 123 * getInputStream. 124 */ 125 // @GuardedBy("stateLock"); 126 private SSLOutputStream os; 127 128 private final Socket socket; 129 private final boolean autoClose; 130 private String wrappedHost; 131 private final int wrappedPort; 132 private final SSLParametersImpl sslParameters; 133 private final CloseGuard guard = CloseGuard.get(); 134 135 private ArrayList<HandshakeCompletedListener> listeners; 136 137 /** 138 * Private key for the TLS Channel ID extension. This field is client-side 139 * only. Set during startHandshake. 140 */ 141 OpenSSLKey channelIdPrivateKey; 142 143 /** Set during startHandshake. */ 144 private OpenSSLSessionImpl sslSession; 145 146 /** Used during handshake callbacks. */ 147 private OpenSSLSessionImpl handshakeSession; 148 149 /** 150 * Local cache of timeout to avoid getsockopt on every read and 151 * write for non-wrapped sockets. Note that 152 * OpenSSLSocketImplWrapper overrides setSoTimeout and 153 * getSoTimeout to delegate to the wrapped socket. 154 */ 155 private int readTimeoutMilliseconds = 0; 156 private int writeTimeoutMilliseconds = 0; 157 158 private int handshakeTimeoutMilliseconds = -1; // -1 = same as timeout; 0 = infinite 159 160 protected OpenSSLSocketImpl(SSLParametersImpl sslParameters) throws IOException { 161 this.socket = this; 162 this.wrappedHost = null; 163 this.wrappedPort = -1; 164 this.autoClose = false; 165 this.sslParameters = sslParameters; 166 } 167 168 protected OpenSSLSocketImpl(String host, int port, SSLParametersImpl sslParameters) 169 throws IOException { 170 super(host, port); 171 this.socket = this; 172 this.wrappedHost = null; 173 this.wrappedPort = -1; 174 this.autoClose = false; 175 this.sslParameters = sslParameters; 176 } 177 178 protected OpenSSLSocketImpl(InetAddress address, int port, SSLParametersImpl sslParameters) 179 throws IOException { 180 super(address, port); 181 this.socket = this; 182 this.wrappedHost = null; 183 this.wrappedPort = -1; 184 this.autoClose = false; 185 this.sslParameters = sslParameters; 186 } 187 188 189 protected OpenSSLSocketImpl(String host, int port, 190 InetAddress clientAddress, int clientPort, 191 SSLParametersImpl sslParameters) throws IOException { 192 super(host, port, clientAddress, clientPort); 193 this.socket = this; 194 this.wrappedHost = null; 195 this.wrappedPort = -1; 196 this.autoClose = false; 197 this.sslParameters = sslParameters; 198 } 199 200 protected OpenSSLSocketImpl(InetAddress address, int port, 201 InetAddress clientAddress, int clientPort, 202 SSLParametersImpl sslParameters) throws IOException { 203 super(address, port, clientAddress, clientPort); 204 this.socket = this; 205 this.wrappedHost = null; 206 this.wrappedPort = -1; 207 this.autoClose = false; 208 this.sslParameters = sslParameters; 209 } 210 211 /** 212 * Create an SSL socket that wraps another socket. Invoked by 213 * OpenSSLSocketImplWrapper constructor. 214 */ 215 protected OpenSSLSocketImpl(Socket socket, String host, int port, 216 boolean autoClose, SSLParametersImpl sslParameters) throws IOException { 217 this.socket = socket; 218 this.wrappedHost = host; 219 this.wrappedPort = port; 220 this.autoClose = autoClose; 221 this.sslParameters = sslParameters; 222 223 // this.timeout is not set intentionally. 224 // OpenSSLSocketImplWrapper.getSoTimeout will delegate timeout 225 // to wrapped socket 226 } 227 228 private void checkOpen() throws SocketException { 229 if (isClosed()) { 230 throw new SocketException("Socket is closed"); 231 } 232 } 233 234 /** 235 * Starts a TLS/SSL handshake on this connection using some native methods 236 * from the OpenSSL library. It can negotiate new encryption keys, change 237 * cipher suites, or initiate a new session. The certificate chain is 238 * verified if the correspondent property in java.Security is set. All 239 * listeners are notified at the end of the TLS/SSL handshake. 240 */ 241 @Override 242 public void startHandshake() throws IOException { 243 checkOpen(); 244 synchronized (stateLock) { 245 if (state == STATE_NEW) { 246 state = STATE_HANDSHAKE_STARTED; 247 } else { 248 // We've either started the handshake already or have been closed. 249 // Do nothing in both cases. 250 return; 251 } 252 } 253 254 // note that this modifies the global seed, not something specific to the connection 255 final int seedLengthInBytes = NativeCrypto.RAND_SEED_LENGTH_IN_BYTES; 256 final SecureRandom secureRandom = sslParameters.getSecureRandomMember(); 257 if (secureRandom == null) { 258 NativeCrypto.RAND_load_file("/dev/urandom", seedLengthInBytes); 259 } else { 260 NativeCrypto.RAND_seed(secureRandom.generateSeed(seedLengthInBytes)); 261 } 262 263 final boolean client = sslParameters.getUseClientMode(); 264 265 sslNativePointer = 0; 266 boolean releaseResources = true; 267 try { 268 final AbstractSessionContext sessionContext = sslParameters.getSessionContext(); 269 final long sslCtxNativePointer = sessionContext.sslCtxNativePointer; 270 sslNativePointer = NativeCrypto.SSL_new(sslCtxNativePointer); 271 guard.open("close"); 272 273 boolean enableSessionCreation = getEnableSessionCreation(); 274 if (!enableSessionCreation) { 275 NativeCrypto.SSL_set_session_creation_enabled(sslNativePointer, 276 enableSessionCreation); 277 } 278 279 final OpenSSLSessionImpl sessionToReuse = sslParameters.getSessionToReuse( 280 sslNativePointer, getPeerHostName(), getPeerPort()); 281 sslParameters.setSSLParameters(sslCtxNativePointer, sslNativePointer, this, this, 282 getPeerHostName()); 283 sslParameters.setCertificateValidation(sslNativePointer); 284 sslParameters.setTlsChannelId(sslNativePointer, channelIdPrivateKey); 285 286 // Temporarily use a different timeout for the handshake process 287 int savedReadTimeoutMilliseconds = getSoTimeout(); 288 int savedWriteTimeoutMilliseconds = getSoWriteTimeout(); 289 if (handshakeTimeoutMilliseconds >= 0) { 290 setSoTimeout(handshakeTimeoutMilliseconds); 291 setSoWriteTimeout(handshakeTimeoutMilliseconds); 292 } 293 294 synchronized (stateLock) { 295 if (state == STATE_CLOSED) { 296 return; 297 } 298 } 299 300 long sslSessionNativePointer; 301 try { 302 sslSessionNativePointer = NativeCrypto.SSL_do_handshake(sslNativePointer, 303 Platform.getFileDescriptor(socket), this, getSoTimeout(), client, 304 sslParameters.npnProtocols, client ? null : sslParameters.alpnProtocols); 305 } catch (CertificateException e) { 306 SSLHandshakeException wrapper = new SSLHandshakeException(e.getMessage()); 307 wrapper.initCause(e); 308 throw wrapper; 309 } catch (SSLException e) { 310 // Swallow this exception if it's thrown as the result of an interruption. 311 // 312 // TODO: SSL_read and SSL_write return -1 when interrupted, but SSL_do_handshake 313 // will throw the last sslError that it saw before sslSelect, usually SSL_WANT_READ 314 // (or WANT_WRITE). Catching that exception here doesn't seem much worse than 315 // changing the native code to return a "special" native pointer value when that 316 // happens. 317 synchronized (stateLock) { 318 if (state == STATE_CLOSED) { 319 return; 320 } 321 } 322 323 // Write CCS errors to EventLog 324 String message = e.getMessage(); 325 // Must match error string of SSL_R_UNEXPECTED_CCS 326 if (message.contains("unexpected CCS")) { 327 String logMessage = String.format("ssl_unexpected_ccs: host=%s", 328 getPeerHostName()); 329 Platform.logEvent(logMessage); 330 } 331 332 throw e; 333 } 334 335 boolean handshakeCompleted = false; 336 synchronized (stateLock) { 337 if (state == STATE_HANDSHAKE_COMPLETED) { 338 handshakeCompleted = true; 339 } else if (state == STATE_CLOSED) { 340 return; 341 } 342 } 343 344 sslSession = sslParameters.setupSession(sslSessionNativePointer, sslNativePointer, 345 sessionToReuse, getPeerHostName(), getPeerPort(), handshakeCompleted); 346 347 // Restore the original timeout now that the handshake is complete 348 if (handshakeTimeoutMilliseconds >= 0) { 349 setSoTimeout(savedReadTimeoutMilliseconds); 350 setSoWriteTimeout(savedWriteTimeoutMilliseconds); 351 } 352 353 // if not, notifyHandshakeCompletedListeners later in handshakeCompleted() callback 354 if (handshakeCompleted) { 355 notifyHandshakeCompletedListeners(); 356 } 357 358 synchronized (stateLock) { 359 releaseResources = (state == STATE_CLOSED); 360 361 if (state == STATE_HANDSHAKE_STARTED) { 362 state = STATE_READY_HANDSHAKE_CUT_THROUGH; 363 } else if (state == STATE_HANDSHAKE_COMPLETED) { 364 state = STATE_READY; 365 } 366 367 if (!releaseResources) { 368 // Unblock threads that are waiting for our state to transition 369 // into STATE_READY or STATE_READY_HANDSHAKE_CUT_THROUGH. 370 stateLock.notifyAll(); 371 } 372 } 373 } catch (SSLProtocolException e) { 374 throw (SSLHandshakeException) new SSLHandshakeException("Handshake failed") 375 .initCause(e); 376 } finally { 377 // on exceptional exit, treat the socket as closed 378 if (releaseResources) { 379 synchronized (stateLock) { 380 // Mark the socket as closed since we might have reached this as 381 // a result on an exception thrown by the handshake process. 382 // 383 // The state will already be set to closed if we reach this as a result of 384 // an early return or an interruption due to a concurrent call to close(). 385 state = STATE_CLOSED; 386 stateLock.notifyAll(); 387 } 388 389 try { 390 shutdownAndFreeSslNative(); 391 } catch (IOException ignored) { 392 393 } 394 } 395 } 396 } 397 398 String getPeerHostName() { 399 if (wrappedHost != null) { 400 return wrappedHost; 401 } 402 InetAddress inetAddress = super.getInetAddress(); 403 if (inetAddress != null) { 404 return inetAddress.getHostName(); 405 } 406 return null; 407 } 408 409 int getPeerPort() { 410 return wrappedHost == null ? super.getPort() : wrappedPort; 411 } 412 413 @Override 414 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / client_cert_cb 415 public void clientCertificateRequested(byte[] keyTypeBytes, byte[][] asn1DerEncodedPrincipals) 416 throws CertificateEncodingException, SSLException { 417 sslParameters.chooseClientCertificate(keyTypeBytes, asn1DerEncodedPrincipals, 418 sslNativePointer, this); 419 } 420 421 @Override 422 @SuppressWarnings("unused") // used by native psk_client_callback 423 public int clientPSKKeyRequested(String identityHint, byte[] identity, byte[] key) { 424 return sslParameters.clientPSKKeyRequested(identityHint, identity, key, this); 425 } 426 427 @Override 428 @SuppressWarnings("unused") // used by native psk_server_callback 429 public int serverPSKKeyRequested(String identityHint, String identity, byte[] key) { 430 return sslParameters.serverPSKKeyRequested(identityHint, identity, key, this); 431 } 432 433 @Override 434 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks / info_callback 435 public void onSSLStateChange(long sslSessionNativePtr, int type, int val) { 436 if (type != NativeCrypto.SSL_CB_HANDSHAKE_DONE) { 437 return; 438 } 439 440 synchronized (stateLock) { 441 if (state == STATE_HANDSHAKE_STARTED) { 442 // If sslSession is null, the handshake was completed during 443 // the call to NativeCrypto.SSL_do_handshake and not during a 444 // later read operation. That means we do not need to fix up 445 // the SSLSession and session cache or notify 446 // HandshakeCompletedListeners, it will be done in 447 // startHandshake. 448 449 state = STATE_HANDSHAKE_COMPLETED; 450 return; 451 } else if (state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 452 // We've returned from startHandshake, which means we've set a sslSession etc. 453 // we need to fix them up, which we'll do outside this lock. 454 } else if (state == STATE_CLOSED) { 455 // Someone called "close" but the handshake hasn't been interrupted yet. 456 return; 457 } 458 } 459 460 // reset session id from the native pointer and update the 461 // appropriate cache. 462 sslSession.resetId(); 463 AbstractSessionContext sessionContext = 464 (sslParameters.getUseClientMode()) 465 ? sslParameters.getClientSessionContext() 466 : sslParameters.getServerSessionContext(); 467 sessionContext.putSession(sslSession); 468 469 // let listeners know we are finally done 470 notifyHandshakeCompletedListeners(); 471 472 synchronized (stateLock) { 473 // Now that we've fixed up our state, we can tell waiting threads that 474 // we're ready. 475 state = STATE_READY; 476 // Notify all threads waiting for the handshake to complete. 477 stateLock.notifyAll(); 478 } 479 } 480 481 private void notifyHandshakeCompletedListeners() { 482 if (listeners != null && !listeners.isEmpty()) { 483 // notify the listeners 484 HandshakeCompletedEvent event = 485 new HandshakeCompletedEvent(this, sslSession); 486 for (HandshakeCompletedListener listener : listeners) { 487 try { 488 listener.handshakeCompleted(event); 489 } catch (RuntimeException e) { 490 // The RI runs the handlers in a separate thread, 491 // which we do not. But we try to preserve their 492 // behavior of logging a problem and not killing 493 // the handshaking thread just because a listener 494 // has a problem. 495 Thread thread = Thread.currentThread(); 496 thread.getUncaughtExceptionHandler().uncaughtException(thread, e); 497 } 498 } 499 } 500 } 501 502 @SuppressWarnings("unused") // used by NativeCrypto.SSLHandshakeCallbacks 503 @Override 504 public void verifyCertificateChain(long sslSessionNativePtr, long[] certRefs, String authMethod) 505 throws CertificateException { 506 try { 507 X509TrustManager x509tm = sslParameters.getX509TrustManager(); 508 if (x509tm == null) { 509 throw new CertificateException("No X.509 TrustManager"); 510 } 511 if (certRefs == null || certRefs.length == 0) { 512 throw new SSLException("Peer sent no certificate"); 513 } 514 OpenSSLX509Certificate[] peerCertChain = new OpenSSLX509Certificate[certRefs.length]; 515 for (int i = 0; i < certRefs.length; i++) { 516 peerCertChain[i] = new OpenSSLX509Certificate(certRefs[i]); 517 } 518 519 // Used for verifyCertificateChain callback 520 handshakeSession = new OpenSSLSessionImpl(sslSessionNativePtr, null, peerCertChain, 521 getPeerHostName(), getPeerPort(), null); 522 523 boolean client = sslParameters.getUseClientMode(); 524 if (client) { 525 Platform.checkServerTrusted(x509tm, peerCertChain, authMethod, getPeerHostName()); 526 } else { 527 String authType = peerCertChain[0].getPublicKey().getAlgorithm(); 528 x509tm.checkClientTrusted(peerCertChain, authType); 529 } 530 } catch (CertificateException e) { 531 throw e; 532 } catch (Exception e) { 533 throw new CertificateException(e); 534 } finally { 535 // Clear this before notifying handshake completed listeners 536 handshakeSession = null; 537 } 538 } 539 540 @Override 541 public InputStream getInputStream() throws IOException { 542 checkOpen(); 543 544 InputStream returnVal; 545 synchronized (stateLock) { 546 if (state == STATE_CLOSED) { 547 throw new SocketException("Socket is closed."); 548 } 549 550 if (is == null) { 551 is = new SSLInputStream(); 552 } 553 554 returnVal = is; 555 } 556 557 // Block waiting for a handshake without a lock held. It's possible that the socket 558 // is closed at this point. If that happens, we'll still return the input stream but 559 // all reads on it will throw. 560 waitForHandshake(); 561 return returnVal; 562 } 563 564 @Override 565 public OutputStream getOutputStream() throws IOException { 566 checkOpen(); 567 568 OutputStream returnVal; 569 synchronized (stateLock) { 570 if (state == STATE_CLOSED) { 571 throw new SocketException("Socket is closed."); 572 } 573 574 if (os == null) { 575 os = new SSLOutputStream(); 576 } 577 578 returnVal = os; 579 } 580 581 // Block waiting for a handshake without a lock held. It's possible that the socket 582 // is closed at this point. If that happens, we'll still return the output stream but 583 // all writes on it will throw. 584 waitForHandshake(); 585 return returnVal; 586 } 587 588 private void assertReadableOrWriteableState() { 589 if (state == STATE_READY || state == STATE_READY_HANDSHAKE_CUT_THROUGH) { 590 return; 591 } 592 593 throw new AssertionError("Invalid state: " + state); 594 } 595 596 597 private void waitForHandshake() throws IOException { 598 startHandshake(); 599 600 synchronized (stateLock) { 601 while (state != STATE_READY && 602 state != STATE_READY_HANDSHAKE_CUT_THROUGH && 603 state != STATE_CLOSED) { 604 try { 605 stateLock.wait(); 606 } catch (InterruptedException e) { 607 Thread.currentThread().interrupt(); 608 IOException ioe = new IOException("Interrupted waiting for handshake"); 609 ioe.initCause(e); 610 611 throw ioe; 612 } 613 } 614 615 if (state == STATE_CLOSED) { 616 throw new SocketException("Socket is closed"); 617 } 618 } 619 } 620 621 /** 622 * This inner class provides input data stream functionality 623 * for the OpenSSL native implementation. It is used to 624 * read data received via SSL protocol. 625 */ 626 private class SSLInputStream extends InputStream { 627 /** 628 * OpenSSL only lets one thread read at a time, so this is used to 629 * make sure we serialize callers of SSL_read. Thread is already 630 * expected to have completed handshaking. 631 */ 632 private final Object readLock = new Object(); 633 634 SSLInputStream() { 635 } 636 637 /** 638 * Reads one byte. If there is no data in the underlying buffer, 639 * this operation can block until the data will be 640 * available. 641 * @return read value. 642 * @throws IOException 643 */ 644 @Override 645 public int read() throws IOException { 646 byte[] buffer = new byte[1]; 647 int result = read(buffer, 0, 1); 648 return (result != -1) ? buffer[0] & 0xff : -1; 649 } 650 651 /** 652 * Method acts as described in spec for superclass. 653 * @see java.io.InputStream#read(byte[],int,int) 654 */ 655 @Override 656 public int read(byte[] buf, int offset, int byteCount) throws IOException { 657 BlockGuard.getThreadPolicy().onNetwork(); 658 659 checkOpen(); 660 Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 661 if (byteCount == 0) { 662 return 0; 663 } 664 665 synchronized (readLock) { 666 synchronized (stateLock) { 667 if (state == STATE_CLOSED) { 668 throw new SocketException("socket is closed"); 669 } 670 671 if (DBG_STATE) assertReadableOrWriteableState(); 672 } 673 674 return NativeCrypto.SSL_read(sslNativePointer, Platform.getFileDescriptor(socket), 675 OpenSSLSocketImpl.this, buf, offset, byteCount, getSoTimeout()); 676 } 677 } 678 679 public void awaitPendingOps() { 680 if (DBG_STATE) { 681 synchronized (stateLock) { 682 if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 683 } 684 } 685 686 synchronized (readLock) { } 687 } 688 } 689 690 /** 691 * This inner class provides output data stream functionality 692 * for the OpenSSL native implementation. It is used to 693 * write data according to the encryption parameters given in SSL context. 694 */ 695 private class SSLOutputStream extends OutputStream { 696 697 /** 698 * OpenSSL only lets one thread write at a time, so this is used 699 * to make sure we serialize callers of SSL_write. Thread is 700 * already expected to have completed handshaking. 701 */ 702 private final Object writeLock = new Object(); 703 704 SSLOutputStream() { 705 } 706 707 /** 708 * Method acts as described in spec for superclass. 709 * @see java.io.OutputStream#write(int) 710 */ 711 @Override 712 public void write(int oneByte) throws IOException { 713 byte[] buffer = new byte[1]; 714 buffer[0] = (byte) (oneByte & 0xff); 715 write(buffer); 716 } 717 718 /** 719 * Method acts as described in spec for superclass. 720 * @see java.io.OutputStream#write(byte[],int,int) 721 */ 722 @Override 723 public void write(byte[] buf, int offset, int byteCount) throws IOException { 724 BlockGuard.getThreadPolicy().onNetwork(); 725 checkOpen(); 726 Arrays.checkOffsetAndCount(buf.length, offset, byteCount); 727 if (byteCount == 0) { 728 return; 729 } 730 731 synchronized (writeLock) { 732 synchronized (stateLock) { 733 if (state == STATE_CLOSED) { 734 throw new SocketException("socket is closed"); 735 } 736 737 if (DBG_STATE) assertReadableOrWriteableState(); 738 } 739 740 NativeCrypto.SSL_write(sslNativePointer, Platform.getFileDescriptor(socket), 741 OpenSSLSocketImpl.this, buf, offset, byteCount, writeTimeoutMilliseconds); 742 } 743 } 744 745 746 public void awaitPendingOps() { 747 if (DBG_STATE) { 748 synchronized (stateLock) { 749 if (state != STATE_CLOSED) throw new AssertionError("State is: " + state); 750 } 751 } 752 753 synchronized (writeLock) { } 754 } 755 } 756 757 758 @Override 759 public SSLSession getSession() { 760 if (sslSession == null) { 761 try { 762 waitForHandshake(); 763 } catch (IOException e) { 764 // return an invalid session with 765 // invalid cipher suite of "SSL_NULL_WITH_NULL_NULL" 766 return SSLNullSession.getNullSession(); 767 } 768 } 769 return sslSession; 770 } 771 772 @Override 773 public void addHandshakeCompletedListener( 774 HandshakeCompletedListener listener) { 775 if (listener == null) { 776 throw new IllegalArgumentException("Provided listener is null"); 777 } 778 if (listeners == null) { 779 listeners = new ArrayList<HandshakeCompletedListener>(); 780 } 781 listeners.add(listener); 782 } 783 784 @Override 785 public void removeHandshakeCompletedListener( 786 HandshakeCompletedListener listener) { 787 if (listener == null) { 788 throw new IllegalArgumentException("Provided listener is null"); 789 } 790 if (listeners == null) { 791 throw new IllegalArgumentException( 792 "Provided listener is not registered"); 793 } 794 if (!listeners.remove(listener)) { 795 throw new IllegalArgumentException( 796 "Provided listener is not registered"); 797 } 798 } 799 800 @Override 801 public boolean getEnableSessionCreation() { 802 return sslParameters.getEnableSessionCreation(); 803 } 804 805 @Override 806 public void setEnableSessionCreation(boolean flag) { 807 sslParameters.setEnableSessionCreation(flag); 808 } 809 810 @Override 811 public String[] getSupportedCipherSuites() { 812 return NativeCrypto.getSupportedCipherSuites(); 813 } 814 815 @Override 816 public String[] getEnabledCipherSuites() { 817 return sslParameters.getEnabledCipherSuites(); 818 } 819 820 @Override 821 public void setEnabledCipherSuites(String[] suites) { 822 sslParameters.setEnabledCipherSuites(suites); 823 } 824 825 @Override 826 public String[] getSupportedProtocols() { 827 return NativeCrypto.getSupportedProtocols(); 828 } 829 830 @Override 831 public String[] getEnabledProtocols() { 832 return sslParameters.getEnabledProtocols(); 833 } 834 835 @Override 836 public void setEnabledProtocols(String[] protocols) { 837 sslParameters.setEnabledProtocols(protocols); 838 } 839 840 /** 841 * This method enables session ticket support. 842 * 843 * @param useSessionTickets True to enable session tickets 844 */ 845 public void setUseSessionTickets(boolean useSessionTickets) { 846 sslParameters.useSessionTickets = useSessionTickets; 847 } 848 849 /** 850 * This method enables Server Name Indication 851 * 852 * @param hostname the desired SNI hostname, or null to disable 853 */ 854 public void setHostname(String hostname) { 855 sslParameters.setUseSni(hostname != null); 856 wrappedHost = hostname; 857 } 858 859 /** 860 * Enables/disables TLS Channel ID for this server socket. 861 * 862 * <p>This method needs to be invoked before the handshake starts. 863 * 864 * @throws IllegalStateException if this is a client socket or if the handshake has already 865 * started. 866 867 */ 868 public void setChannelIdEnabled(boolean enabled) { 869 if (getUseClientMode()) { 870 throw new IllegalStateException("Client mode"); 871 } 872 873 synchronized (stateLock) { 874 if (state != STATE_NEW) { 875 throw new IllegalStateException( 876 "Could not enable/disable Channel ID after the initial handshake has" 877 + " begun."); 878 } 879 } 880 sslParameters.channelIdEnabled = enabled; 881 } 882 883 /** 884 * Gets the TLS Channel ID for this server socket. Channel ID is only available once the 885 * handshake completes. 886 * 887 * @return channel ID or {@code null} if not available. 888 * 889 * @throws IllegalStateException if this is a client socket or if the handshake has not yet 890 * completed. 891 * @throws SSLException if channel ID is available but could not be obtained. 892 */ 893 public byte[] getChannelId() throws SSLException { 894 if (getUseClientMode()) { 895 throw new IllegalStateException("Client mode"); 896 } 897 898 synchronized (stateLock) { 899 if (state != STATE_READY) { 900 throw new IllegalStateException( 901 "Channel ID is only available after handshake completes"); 902 } 903 } 904 return NativeCrypto.SSL_get_tls_channel_id(sslNativePointer); 905 } 906 907 /** 908 * Sets the {@link PrivateKey} to be used for TLS Channel ID by this client socket. 909 * 910 * <p>This method needs to be invoked before the handshake starts. 911 * 912 * @param privateKey private key (enables TLS Channel ID) or {@code null} for no key (disables 913 * TLS Channel ID). The private key must be an Elliptic Curve (EC) key based on the NIST 914 * P-256 curve (aka SECG secp256r1 or ANSI X9.62 prime256v1). 915 * 916 * @throws IllegalStateException if this is a server socket or if the handshake has already 917 * started. 918 */ 919 public void setChannelIdPrivateKey(PrivateKey privateKey) { 920 if (!getUseClientMode()) { 921 throw new IllegalStateException("Server mode"); 922 } 923 924 synchronized (stateLock) { 925 if (state != STATE_NEW) { 926 throw new IllegalStateException( 927 "Could not change Channel ID private key after the initial handshake has" 928 + " begun."); 929 } 930 } 931 932 if (privateKey == null) { 933 sslParameters.channelIdEnabled = false; 934 channelIdPrivateKey = null; 935 } else { 936 sslParameters.channelIdEnabled = true; 937 try { 938 channelIdPrivateKey = OpenSSLKey.fromPrivateKey(privateKey); 939 } catch (InvalidKeyException e) { 940 // Will have error in startHandshake 941 } 942 } 943 } 944 945 @Override 946 public boolean getUseClientMode() { 947 return sslParameters.getUseClientMode(); 948 } 949 950 @Override 951 public void setUseClientMode(boolean mode) { 952 synchronized (stateLock) { 953 if (state != STATE_NEW) { 954 throw new IllegalArgumentException( 955 "Could not change the mode after the initial handshake has begun."); 956 } 957 } 958 sslParameters.setUseClientMode(mode); 959 } 960 961 @Override 962 public boolean getWantClientAuth() { 963 return sslParameters.getWantClientAuth(); 964 } 965 966 @Override 967 public boolean getNeedClientAuth() { 968 return sslParameters.getNeedClientAuth(); 969 } 970 971 @Override 972 public void setNeedClientAuth(boolean need) { 973 sslParameters.setNeedClientAuth(need); 974 } 975 976 @Override 977 public void setWantClientAuth(boolean want) { 978 sslParameters.setWantClientAuth(want); 979 } 980 981 @Override 982 public void sendUrgentData(int data) throws IOException { 983 throw new SocketException("Method sendUrgentData() is not supported."); 984 } 985 986 @Override 987 public void setOOBInline(boolean on) throws SocketException { 988 throw new SocketException("Methods sendUrgentData, setOOBInline are not supported."); 989 } 990 991 @Override 992 public void setSoTimeout(int readTimeoutMilliseconds) throws SocketException { 993 super.setSoTimeout(readTimeoutMilliseconds); 994 this.readTimeoutMilliseconds = readTimeoutMilliseconds; 995 } 996 997 @Override 998 public int getSoTimeout() throws SocketException { 999 return readTimeoutMilliseconds; 1000 } 1001 1002 /** 1003 * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1004 */ 1005 public void setSoWriteTimeout(int writeTimeoutMilliseconds) throws SocketException { 1006 this.writeTimeoutMilliseconds = writeTimeoutMilliseconds; 1007 1008 Platform.setSocketTimeout(this, writeTimeoutMilliseconds); 1009 } 1010 1011 /** 1012 * Note write timeouts are not part of the javax.net.ssl.SSLSocket API 1013 */ 1014 public int getSoWriteTimeout() throws SocketException { 1015 return writeTimeoutMilliseconds; 1016 } 1017 1018 /** 1019 * Set the handshake timeout on this socket. This timeout is specified in 1020 * milliseconds and will be used only during the handshake process. 1021 */ 1022 public void setHandshakeTimeout(int handshakeTimeoutMilliseconds) throws SocketException { 1023 this.handshakeTimeoutMilliseconds = handshakeTimeoutMilliseconds; 1024 } 1025 1026 @Override 1027 public void close() throws IOException { 1028 // TODO: Close SSL sockets using a background thread so they close gracefully. 1029 1030 SSLInputStream sslInputStream = null; 1031 SSLOutputStream sslOutputStream = null; 1032 1033 synchronized (stateLock) { 1034 if (state == STATE_CLOSED) { 1035 // close() has already been called, so do nothing and return. 1036 return; 1037 } 1038 1039 int oldState = state; 1040 state = STATE_CLOSED; 1041 1042 if (oldState == STATE_NEW) { 1043 // The handshake hasn't been started yet, so there's no OpenSSL related 1044 // state to clean up. We still need to close the underlying socket if 1045 // we're wrapping it and were asked to autoClose. 1046 closeUnderlyingSocket(); 1047 1048 stateLock.notifyAll(); 1049 return; 1050 } 1051 1052 if (oldState != STATE_READY && oldState != STATE_READY_HANDSHAKE_CUT_THROUGH) { 1053 // If we're in these states, we still haven't returned from startHandshake. 1054 // We call SSL_interrupt so that we can interrupt SSL_do_handshake and then 1055 // set the state to STATE_CLOSED. startHandshake will handle all cleanup 1056 // after SSL_do_handshake returns, so we don't have anything to do here. 1057 NativeCrypto.SSL_interrupt(sslNativePointer); 1058 1059 stateLock.notifyAll(); 1060 return; 1061 } 1062 1063 stateLock.notifyAll(); 1064 // We've already returned from startHandshake, so we potentially have 1065 // input and output streams to clean up. 1066 sslInputStream = is; 1067 sslOutputStream = os; 1068 } 1069 1070 // Don't bother interrupting unless we have something to interrupt. 1071 if (sslInputStream != null || sslOutputStream != null) { 1072 NativeCrypto.SSL_interrupt(sslNativePointer); 1073 } 1074 1075 // Wait for the input and output streams to finish any reads they have in 1076 // progress. If there are no reads in progress at this point, future reads will 1077 // throw because state == STATE_CLOSED 1078 if (sslInputStream != null) { 1079 sslInputStream.awaitPendingOps(); 1080 } 1081 if (sslOutputStream != null) { 1082 sslOutputStream.awaitPendingOps(); 1083 } 1084 1085 shutdownAndFreeSslNative(); 1086 } 1087 1088 private void shutdownAndFreeSslNative() throws IOException { 1089 try { 1090 BlockGuard.getThreadPolicy().onNetwork(); 1091 NativeCrypto.SSL_shutdown(sslNativePointer, Platform.getFileDescriptor(socket), 1092 this); 1093 } catch (IOException ignored) { 1094 /* 1095 * Note that although close() can throw 1096 * IOException, the RI does not throw if there 1097 * is problem sending a "close notify" which 1098 * can happen if the underlying socket is closed. 1099 */ 1100 } finally { 1101 free(); 1102 closeUnderlyingSocket(); 1103 } 1104 } 1105 1106 private void closeUnderlyingSocket() throws IOException { 1107 if (socket != this) { 1108 if (autoClose && !socket.isClosed()) { 1109 socket.close(); 1110 } 1111 } else { 1112 if (!super.isClosed()) { 1113 super.close(); 1114 } 1115 } 1116 } 1117 1118 private void free() { 1119 if (sslNativePointer == 0) { 1120 return; 1121 } 1122 NativeCrypto.SSL_free(sslNativePointer); 1123 sslNativePointer = 0; 1124 guard.close(); 1125 } 1126 1127 @Override 1128 protected void finalize() throws Throwable { 1129 try { 1130 /* 1131 * Just worry about our own state. Notably we do not try and 1132 * close anything. The SocketImpl, either our own 1133 * PlainSocketImpl, or the Socket we are wrapping, will do 1134 * that. This might mean we do not properly SSL_shutdown, but 1135 * if you want to do that, properly close the socket yourself. 1136 * 1137 * The reason why we don't try to SSL_shutdown, is that there 1138 * can be a race between finalizers where the PlainSocketImpl 1139 * finalizer runs first and closes the socket. However, in the 1140 * meanwhile, the underlying file descriptor could be reused 1141 * for another purpose. If we call SSL_shutdown, the 1142 * underlying socket BIOs still have the old file descriptor 1143 * and will write the close notify to some unsuspecting 1144 * reader. 1145 */ 1146 if (guard != null) { 1147 guard.warnIfOpen(); 1148 } 1149 free(); 1150 } finally { 1151 super.finalize(); 1152 } 1153 } 1154 1155 /* @Override */ 1156 public FileDescriptor getFileDescriptor$() { 1157 if (socket == this) { 1158 return Platform.getFileDescriptorFromSSLSocket(this); 1159 } else { 1160 return Platform.getFileDescriptor(socket); 1161 } 1162 } 1163 1164 /** 1165 * Returns the protocol agreed upon by client and server, or null if no 1166 * protocol was agreed upon. 1167 */ 1168 public byte[] getNpnSelectedProtocol() { 1169 return NativeCrypto.SSL_get_npn_negotiated_protocol(sslNativePointer); 1170 } 1171 1172 /** 1173 * Returns the protocol agreed upon by client and server, or {@code null} if 1174 * no protocol was agreed upon. 1175 */ 1176 public byte[] getAlpnSelectedProtocol() { 1177 return NativeCrypto.SSL_get0_alpn_selected(sslNativePointer); 1178 } 1179 1180 /** 1181 * Sets the list of protocols this peer is interested in. If null no 1182 * protocols will be used. 1183 * 1184 * @param npnProtocols a non-empty array of protocol names. From 1185 * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1186 * strings. The length byte itself is not included in the length. A byte 1187 * string of length 0 is invalid. No byte string may be truncated.". 1188 */ 1189 public void setNpnProtocols(byte[] npnProtocols) { 1190 if (npnProtocols != null && npnProtocols.length == 0) { 1191 throw new IllegalArgumentException("npnProtocols.length == 0"); 1192 } 1193 sslParameters.npnProtocols = npnProtocols; 1194 } 1195 1196 /** 1197 * Sets the list of protocols this peer is interested in. If the list is 1198 * {@code null}, no protocols will be used. 1199 * 1200 * @param alpnProtocols a non-empty array of protocol names. From 1201 * SSL_select_next_proto, "vector of 8-bit, length prefixed byte 1202 * strings. The length byte itself is not included in the length. 1203 * A byte string of length 0 is invalid. No byte string may be 1204 * truncated.". 1205 */ 1206 public void setAlpnProtocols(byte[] alpnProtocols) { 1207 if (alpnProtocols != null && alpnProtocols.length == 0) { 1208 throw new IllegalArgumentException("alpnProtocols.length == 0"); 1209 } 1210 sslParameters.alpnProtocols = alpnProtocols; 1211 } 1212 1213 @Override 1214 public String chooseServerAlias(X509KeyManager keyManager, String keyType) { 1215 return keyManager.chooseServerAlias(keyType, null, this); 1216 } 1217 1218 @Override 1219 public String chooseClientAlias(X509KeyManager keyManager, X500Principal[] issuers, 1220 String[] keyTypes) { 1221 return keyManager.chooseClientAlias(keyTypes, null, this); 1222 } 1223 1224 @Override 1225 public String chooseServerPSKIdentityHint(PSKKeyManager keyManager) { 1226 return keyManager.chooseServerKeyIdentityHint(this); 1227 } 1228 1229 @Override 1230 public String chooseClientPSKIdentity(PSKKeyManager keyManager, String identityHint) { 1231 return keyManager.chooseClientKeyIdentity(identityHint, this); 1232 } 1233 1234 @Override 1235 public SecretKey getPSKKey(PSKKeyManager keyManager, String identityHint, String identity) { 1236 return keyManager.getKey(identityHint, identity, this); 1237 } 1238} 1239