1 /* 2 * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 27 package sun.security.ssl; 28 29 import java.io.*; 30 import java.util.*; 31 import java.security.*; 32 import java.security.NoSuchAlgorithmException; 33 import java.security.AccessController; 34 import java.security.AlgorithmConstraints; 35 import java.security.AccessControlContext; 36 import java.security.PrivilegedExceptionAction; 37 import java.security.PrivilegedActionException; 38 39 import javax.crypto.*; 40 import javax.crypto.spec.*; 41 42 import javax.net.ssl.*; 43 import sun.misc.HexDumpEncoder; 44 45 import sun.security.internal.spec.*; 46 import sun.security.internal.interfaces.TlsMasterSecret; 47 48 import sun.security.ssl.HandshakeMessage.*; 49 import sun.security.ssl.CipherSuite.*; 50 51 import static sun.security.ssl.CipherSuite.PRF.*; 52 53 /** 54 * Handshaker ... processes handshake records from an SSL V3.0 55 * data stream, handling all the details of the handshake protocol. 56 * 57 * Note that the real protocol work is done in two subclasses, the base 58 * class just provides the control flow and key generation framework. 59 * 60 * @author David Brownell 61 */ 62 abstract class Handshaker { 63 64 // protocol version being established using this Handshaker 65 ProtocolVersion protocolVersion; 66 67 // the currently active protocol version during a renegotiation 68 ProtocolVersion activeProtocolVersion; 69 70 // security parameters for secure renegotiation. 71 boolean secureRenegotiation; 72 byte[] clientVerifyData; 73 byte[] serverVerifyData; 74 75 // Is it an initial negotiation or a renegotiation? 76 boolean isInitialHandshake; 77 78 // List of enabled protocols 79 private ProtocolList enabledProtocols; 80 81 // List of enabled CipherSuites 82 private CipherSuiteList enabledCipherSuites; 83 84 // The endpoint identification protocol 85 String identificationProtocol; 86 87 // The cryptographic algorithm constraints 88 private AlgorithmConstraints algorithmConstraints = null; 89 90 // Local supported signature and algorithms 91 Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs; 92 93 // Peer supported signature and algorithms 94 Collection<SignatureAndHashAlgorithm> peerSupportedSignAlgs; 95 96 /* 97 98 /* 99 * List of active protocols 100 * 101 * Active protocols is a subset of enabled protocols, and will 102 * contain only those protocols that have vaild cipher suites 103 * enabled. 104 */ 105 private ProtocolList activeProtocols; 106 107 /* 108 * List of active cipher suites 109 * 110 * Active cipher suites is a subset of enabled cipher suites, and will 111 * contain only those cipher suites available for the active protocols. 112 */ 113 private CipherSuiteList activeCipherSuites; 114 115 private boolean isClient; 116 private boolean needCertVerify; 117 118 SSLSocketImpl conn = null; 119 SSLEngineImpl engine = null; 120 121 HandshakeHash handshakeHash; 122 HandshakeInStream input; 123 HandshakeOutStream output; 124 int state; 125 SSLContextImpl sslContext; 126 RandomCookie clnt_random, svr_random; 127 SSLSessionImpl session; 128 129 // current CipherSuite. Never null, initially SSL_NULL_WITH_NULL_NULL 130 CipherSuite cipherSuite; 131 132 // current key exchange. Never null, initially K_NULL 133 KeyExchange keyExchange; 134 135 /* True if this session is being resumed (fast handshake) */ 136 boolean resumingSession; 137 138 /* True if it's OK to start a new SSL session */ 139 boolean enableNewSession; 140 141 // Temporary storage for the individual keys. Set by 142 // calculateConnectionKeys() and cleared once the ciphers are 143 // activated. 144 private SecretKey clntWriteKey, svrWriteKey; 145 private IvParameterSpec clntWriteIV, svrWriteIV; 146 private SecretKey clntMacSecret, svrMacSecret; 147 148 /* 149 * Delegated task subsystem data structures. 150 * 151 * If thrown is set, we need to propagate this back immediately 152 * on entry into processMessage(). 153 * 154 * Data is protected by the SSLEngine.this lock. 155 */ 156 private volatile boolean taskDelegated = false; 157 private volatile DelegatedTask delegatedTask = null; 158 private volatile Exception thrown = null; 159 160 // Could probably use a java.util.concurrent.atomic.AtomicReference 161 // here instead of using this lock. Consider changing. 162 private Object thrownLock = new Object(); 163 164 /* Class and subclass dynamic debugging support */ 165 static final Debug debug = Debug.getInstance("ssl"); 166 167 // By default, disable the unsafe legacy session renegotiation 168 static final boolean allowUnsafeRenegotiation = Debug.getBooleanProperty( 169 "sun.security.ssl.allowUnsafeRenegotiation", false); 170 171 // For maximum interoperability and backward compatibility, RFC 5746 172 // allows server (or client) to accept ClientHello (or ServerHello) 173 // message without the secure renegotiation_info extension or SCSV. 174 // 175 // For maximum security, RFC 5746 also allows server (or client) to 176 // reject such message with a fatal "handshake_failure" alert. 177 // 178 // By default, allow such legacy hello messages. 179 static final boolean allowLegacyHelloMessages = Debug.getBooleanProperty( 180 "sun.security.ssl.allowLegacyHelloMessages", true); 181 182 // need to dispose the object when it is invalidated 183 boolean invalidated; 184 Handshaker(SSLSocketImpl c, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData)185 Handshaker(SSLSocketImpl c, SSLContextImpl context, 186 ProtocolList enabledProtocols, boolean needCertVerify, 187 boolean isClient, ProtocolVersion activeProtocolVersion, 188 boolean isInitialHandshake, boolean secureRenegotiation, 189 byte[] clientVerifyData, byte[] serverVerifyData) { 190 this.conn = c; 191 init(context, enabledProtocols, needCertVerify, isClient, 192 activeProtocolVersion, isInitialHandshake, secureRenegotiation, 193 clientVerifyData, serverVerifyData); 194 } 195 Handshaker(SSLEngineImpl engine, SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData)196 Handshaker(SSLEngineImpl engine, SSLContextImpl context, 197 ProtocolList enabledProtocols, boolean needCertVerify, 198 boolean isClient, ProtocolVersion activeProtocolVersion, 199 boolean isInitialHandshake, boolean secureRenegotiation, 200 byte[] clientVerifyData, byte[] serverVerifyData) { 201 this.engine = engine; 202 init(context, enabledProtocols, needCertVerify, isClient, 203 activeProtocolVersion, isInitialHandshake, secureRenegotiation, 204 clientVerifyData, serverVerifyData); 205 } 206 init(SSLContextImpl context, ProtocolList enabledProtocols, boolean needCertVerify, boolean isClient, ProtocolVersion activeProtocolVersion, boolean isInitialHandshake, boolean secureRenegotiation, byte[] clientVerifyData, byte[] serverVerifyData)207 private void init(SSLContextImpl context, ProtocolList enabledProtocols, 208 boolean needCertVerify, boolean isClient, 209 ProtocolVersion activeProtocolVersion, 210 boolean isInitialHandshake, boolean secureRenegotiation, 211 byte[] clientVerifyData, byte[] serverVerifyData) { 212 213 if (debug != null && Debug.isOn("handshake")) { 214 System.out.println( 215 "Allow unsafe renegotiation: " + allowUnsafeRenegotiation + 216 "\nAllow legacy hello messages: " + allowLegacyHelloMessages + 217 "\nIs initial handshake: " + isInitialHandshake + 218 "\nIs secure renegotiation: " + secureRenegotiation); 219 } 220 221 this.sslContext = context; 222 this.isClient = isClient; 223 this.needCertVerify = needCertVerify; 224 this.activeProtocolVersion = activeProtocolVersion; 225 this.isInitialHandshake = isInitialHandshake; 226 this.secureRenegotiation = secureRenegotiation; 227 this.clientVerifyData = clientVerifyData; 228 this.serverVerifyData = serverVerifyData; 229 enableNewSession = true; 230 invalidated = false; 231 232 setCipherSuite(CipherSuite.C_NULL); 233 setEnabledProtocols(enabledProtocols); 234 235 if (conn != null) { 236 algorithmConstraints = new SSLAlgorithmConstraints(conn, true); 237 } else { // engine != null 238 algorithmConstraints = new SSLAlgorithmConstraints(engine, true); 239 } 240 241 242 // 243 // In addition to the connection state machine, controlling 244 // how the connection deals with the different sorts of records 245 // that get sent (notably handshake transitions!), there's 246 // also a handshaking state machine that controls message 247 // sequencing. 248 // 249 // It's a convenient artifact of the protocol that this can, 250 // with only a couple of minor exceptions, be driven by the 251 // type constant for the last message seen: except for the 252 // client's cert verify, those constants are in a convenient 253 // order to drastically simplify state machine checking. 254 // 255 state = -2; // initialized but not activated 256 } 257 258 /* 259 * Reroutes calls to the SSLSocket or SSLEngine (*SE). 260 * 261 * We could have also done it by extra classes 262 * and letting them override, but this seemed much 263 * less involved. 264 */ fatalSE(byte b, String diagnostic)265 void fatalSE(byte b, String diagnostic) throws IOException { 266 fatalSE(b, diagnostic, null); 267 } 268 fatalSE(byte b, Throwable cause)269 void fatalSE(byte b, Throwable cause) throws IOException { 270 fatalSE(b, null, cause); 271 } 272 fatalSE(byte b, String diagnostic, Throwable cause)273 void fatalSE(byte b, String diagnostic, Throwable cause) 274 throws IOException { 275 if (conn != null) { 276 conn.fatal(b, diagnostic, cause); 277 } else { 278 engine.fatal(b, diagnostic, cause); 279 } 280 } 281 warningSE(byte b)282 void warningSE(byte b) { 283 if (conn != null) { 284 conn.warning(b); 285 } else { 286 engine.warning(b); 287 } 288 } 289 getRawHostnameSE()290 String getRawHostnameSE() { 291 if (conn != null) { 292 return conn.getRawHostname(); 293 } else { 294 return engine.getPeerHost(); 295 } 296 } 297 getHostSE()298 String getHostSE() { 299 if (conn != null) { 300 return conn.getHost(); 301 } else { 302 return engine.getPeerHost(); 303 } 304 } 305 getHostAddressSE()306 String getHostAddressSE() { 307 if (conn != null) { 308 return conn.getInetAddress().getHostAddress(); 309 } else { 310 /* 311 * This is for caching only, doesn't matter that's is really 312 * a hostname. The main thing is that it doesn't do 313 * a reverse DNS lookup, potentially slowing things down. 314 */ 315 return engine.getPeerHost(); 316 } 317 } 318 isLoopbackSE()319 boolean isLoopbackSE() { 320 if (conn != null) { 321 return conn.getInetAddress().isLoopbackAddress(); 322 } else { 323 return false; 324 } 325 } 326 getPortSE()327 int getPortSE() { 328 if (conn != null) { 329 return conn.getPort(); 330 } else { 331 return engine.getPeerPort(); 332 } 333 } 334 getLocalPortSE()335 int getLocalPortSE() { 336 if (conn != null) { 337 return conn.getLocalPort(); 338 } else { 339 return -1; 340 } 341 } 342 getAccSE()343 AccessControlContext getAccSE() { 344 if (conn != null) { 345 return conn.getAcc(); 346 } else { 347 return engine.getAcc(); 348 } 349 } 350 setVersionSE(ProtocolVersion protocolVersion)351 private void setVersionSE(ProtocolVersion protocolVersion) { 352 if (conn != null) { 353 conn.setVersion(protocolVersion); 354 } else { 355 engine.setVersion(protocolVersion); 356 } 357 } 358 359 /** 360 * Set the active protocol version and propagate it to the SSLSocket 361 * and our handshake streams. Called from ClientHandshaker 362 * and ServerHandshaker with the negotiated protocol version. 363 */ setVersion(ProtocolVersion protocolVersion)364 void setVersion(ProtocolVersion protocolVersion) { 365 this.protocolVersion = protocolVersion; 366 setVersionSE(protocolVersion); 367 368 output.r.setVersion(protocolVersion); 369 } 370 371 /** 372 * Set the enabled protocols. Called from the constructor or 373 * SSLSocketImpl/SSLEngineImpl.setEnabledProtocols() (if the 374 * handshake is not yet in progress). 375 */ setEnabledProtocols(ProtocolList enabledProtocols)376 void setEnabledProtocols(ProtocolList enabledProtocols) { 377 activeCipherSuites = null; 378 activeProtocols = null; 379 380 this.enabledProtocols = enabledProtocols; 381 } 382 383 /** 384 * Set the enabled cipher suites. Called from 385 * SSLSocketImpl/SSLEngineImpl.setEnabledCipherSuites() (if the 386 * handshake is not yet in progress). 387 */ setEnabledCipherSuites(CipherSuiteList enabledCipherSuites)388 void setEnabledCipherSuites(CipherSuiteList enabledCipherSuites) { 389 activeCipherSuites = null; 390 activeProtocols = null; 391 this.enabledCipherSuites = enabledCipherSuites; 392 } 393 394 /** 395 * Set the algorithm constraints. Called from the constructor or 396 * SSLSocketImpl/SSLEngineImpl.setAlgorithmConstraints() (if the 397 * handshake is not yet in progress). 398 */ setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints)399 void setAlgorithmConstraints(AlgorithmConstraints algorithmConstraints) { 400 activeCipherSuites = null; 401 activeProtocols = null; 402 403 this.algorithmConstraints = 404 new SSLAlgorithmConstraints(algorithmConstraints); 405 this.localSupportedSignAlgs = null; 406 } 407 getLocalSupportedSignAlgs()408 Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() { 409 if (localSupportedSignAlgs == null) { 410 localSupportedSignAlgs = 411 SignatureAndHashAlgorithm.getSupportedAlgorithms( 412 algorithmConstraints); 413 } 414 415 return localSupportedSignAlgs; 416 } 417 setPeerSupportedSignAlgs( Collection<SignatureAndHashAlgorithm> algorithms)418 void setPeerSupportedSignAlgs( 419 Collection<SignatureAndHashAlgorithm> algorithms) { 420 peerSupportedSignAlgs = 421 new ArrayList<SignatureAndHashAlgorithm>(algorithms); 422 } 423 getPeerSupportedSignAlgs()424 Collection<SignatureAndHashAlgorithm> getPeerSupportedSignAlgs() { 425 return peerSupportedSignAlgs; 426 } 427 428 429 /** 430 * Set the identification protocol. Called from the constructor or 431 * SSLSocketImpl/SSLEngineImpl.setIdentificationProtocol() (if the 432 * handshake is not yet in progress). 433 */ setIdentificationProtocol(String protocol)434 void setIdentificationProtocol(String protocol) { 435 this.identificationProtocol = protocol; 436 } 437 438 /** 439 * Prior to handshaking, activate the handshake and initialize the version, 440 * input stream and output stream. 441 */ activate(ProtocolVersion helloVersion)442 void activate(ProtocolVersion helloVersion) throws IOException { 443 if (activeProtocols == null) { 444 activeProtocols = getActiveProtocols(); 445 } 446 447 if (activeProtocols.collection().isEmpty() || 448 activeProtocols.max.v == ProtocolVersion.NONE.v) { 449 throw new SSLHandshakeException("No appropriate protocol"); 450 } 451 452 if (activeCipherSuites == null) { 453 activeCipherSuites = getActiveCipherSuites(); 454 } 455 456 if (activeCipherSuites.collection().isEmpty()) { 457 throw new SSLHandshakeException("No appropriate cipher suite"); 458 } 459 460 // temporary protocol version until the actual protocol version 461 // is negotiated in the Hello exchange. This affects the record 462 // version we sent with the ClientHello. 463 if (!isInitialHandshake) { 464 protocolVersion = activeProtocolVersion; 465 } else { 466 protocolVersion = activeProtocols.max; 467 } 468 469 if (helloVersion == null || helloVersion.v == ProtocolVersion.NONE.v) { 470 helloVersion = activeProtocols.helloVersion; 471 } 472 473 // We accumulate digests of the handshake messages so that 474 // we can read/write CertificateVerify and Finished messages, 475 // getting assurance against some particular active attacks. 476 Set<String> localSupportedHashAlgorithms = 477 SignatureAndHashAlgorithm.getHashAlgorithmNames( 478 getLocalSupportedSignAlgs()); 479 handshakeHash = new HandshakeHash(!isClient, needCertVerify, 480 localSupportedHashAlgorithms); 481 482 // Generate handshake input/output stream. 483 input = new HandshakeInStream(handshakeHash); 484 if (conn != null) { 485 output = new HandshakeOutStream(protocolVersion, helloVersion, 486 handshakeHash, conn); 487 conn.getAppInputStream().r.setHandshakeHash(handshakeHash); 488 conn.getAppInputStream().r.setHelloVersion(helloVersion); 489 conn.getAppOutputStream().r.setHelloVersion(helloVersion); 490 } else { 491 output = new HandshakeOutStream(protocolVersion, helloVersion, 492 handshakeHash, engine); 493 engine.inputRecord.setHandshakeHash(handshakeHash); 494 engine.inputRecord.setHelloVersion(helloVersion); 495 engine.outputRecord.setHelloVersion(helloVersion); 496 } 497 498 // move state to activated 499 state = -1; 500 } 501 502 /** 503 * Set cipherSuite and keyExchange to the given CipherSuite. 504 * Does not perform any verification that this is a valid selection, 505 * this must be done before calling this method. 506 */ setCipherSuite(CipherSuite s)507 void setCipherSuite(CipherSuite s) { 508 this.cipherSuite = s; 509 this.keyExchange = s.keyExchange; 510 } 511 512 /** 513 * Check if the given ciphersuite is enabled and available. 514 * Does not check if the required server certificates are available. 515 */ isNegotiable(CipherSuite s)516 boolean isNegotiable(CipherSuite s) { 517 if (activeCipherSuites == null) { 518 activeCipherSuites = getActiveCipherSuites(); 519 } 520 521 return activeCipherSuites.contains(s) && s.isNegotiable(); 522 } 523 524 /** 525 * Check if the given protocol version is enabled and available. 526 */ isNegotiable(ProtocolVersion protocolVersion)527 boolean isNegotiable(ProtocolVersion protocolVersion) { 528 if (activeProtocols == null) { 529 activeProtocols = getActiveProtocols(); 530 } 531 532 return activeProtocols.contains(protocolVersion); 533 } 534 535 /** 536 * Select a protocol version from the list. Called from 537 * ServerHandshaker to negotiate protocol version. 538 * 539 * Return the lower of the protocol version suggested in the 540 * clien hello and the highest supported by the server. 541 */ selectProtocolVersion(ProtocolVersion protocolVersion)542 ProtocolVersion selectProtocolVersion(ProtocolVersion protocolVersion) { 543 if (activeProtocols == null) { 544 activeProtocols = getActiveProtocols(); 545 } 546 547 return activeProtocols.selectProtocolVersion(protocolVersion); 548 } 549 550 /** 551 * Get the active cipher suites. 552 * 553 * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted, 554 * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT 555 * negotiate these cipher suites in TLS 1.1 or later mode. 556 * 557 * Therefore, when the active protocols only include TLS 1.1 or later, 558 * the client cannot request to negotiate those obsoleted cipher 559 * suites. That is, the obsoleted suites should not be included in the 560 * client hello. So we need to create a subset of the enabled cipher 561 * suites, the active cipher suites, which does not contain obsoleted 562 * cipher suites of the minimum active protocol. 563 * 564 * Return empty list instead of null if no active cipher suites. 565 */ getActiveCipherSuites()566 CipherSuiteList getActiveCipherSuites() { 567 if (activeCipherSuites == null) { 568 if (activeProtocols == null) { 569 activeProtocols = getActiveProtocols(); 570 } 571 572 ArrayList<CipherSuite> suites = new ArrayList<>(); 573 if (!(activeProtocols.collection().isEmpty()) && 574 activeProtocols.min.v != ProtocolVersion.NONE.v) { 575 for (CipherSuite suite : enabledCipherSuites.collection()) { 576 if (suite.obsoleted > activeProtocols.min.v && 577 suite.supported <= activeProtocols.max.v) { 578 if (algorithmConstraints.permits( 579 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), 580 suite.name, null)) { 581 suites.add(suite); 582 } 583 } else if (debug != null && Debug.isOn("verbose")) { 584 if (suite.obsoleted <= activeProtocols.min.v) { 585 System.out.println( 586 "Ignoring obsoleted cipher suite: " + suite); 587 } else { 588 System.out.println( 589 "Ignoring unsupported cipher suite: " + suite); 590 } 591 } 592 } 593 } 594 activeCipherSuites = new CipherSuiteList(suites); 595 } 596 597 return activeCipherSuites; 598 } 599 600 /* 601 * Get the active protocol versions. 602 * 603 * In TLS 1.1, many weak or vulnerable cipher suites were obsoleted, 604 * such as TLS_RSA_EXPORT_WITH_RC4_40_MD5. The implementation MUST NOT 605 * negotiate these cipher suites in TLS 1.1 or later mode. 606 * 607 * For example, if "TLS_RSA_EXPORT_WITH_RC4_40_MD5" is the 608 * only enabled cipher suite, the client cannot request TLS 1.1 or 609 * later, even though TLS 1.1 or later is enabled. We need to create a 610 * subset of the enabled protocols, called the active protocols, which 611 * contains protocols appropriate to the list of enabled Ciphersuites. 612 * 613 * Return empty list instead of null if no active protocol versions. 614 */ getActiveProtocols()615 ProtocolList getActiveProtocols() { 616 if (activeProtocols == null) { 617 ArrayList<ProtocolVersion> protocols = new ArrayList<>(4); 618 for (ProtocolVersion protocol : enabledProtocols.collection()) { 619 boolean found = false; 620 for (CipherSuite suite : enabledCipherSuites.collection()) { 621 if (suite.isAvailable() && suite.obsoleted > protocol.v && 622 suite.supported <= protocol.v) { 623 if (algorithmConstraints.permits( 624 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), 625 suite.name, null)) { 626 protocols.add(protocol); 627 found = true; 628 break; 629 } else if (debug != null && Debug.isOn("verbose")) { 630 System.out.println( 631 "Ignoring disabled cipher suite: " + suite + 632 " for " + protocol); 633 } 634 } else if (debug != null && Debug.isOn("verbose")) { 635 System.out.println( 636 "Ignoring unsupported cipher suite: " + suite + 637 " for " + protocol); 638 } 639 } 640 if (!found && (debug != null) && Debug.isOn("handshake")) { 641 System.out.println( 642 "No available cipher suite for " + protocol); 643 } 644 } 645 activeProtocols = new ProtocolList(protocols); 646 } 647 648 return activeProtocols; 649 } 650 651 /** 652 * As long as handshaking has not activated, we can 653 * change whether session creations are allowed. 654 * 655 * Callers should do their own checking if handshaking 656 * has activated. 657 */ setEnableSessionCreation(boolean newSessions)658 void setEnableSessionCreation(boolean newSessions) { 659 enableNewSession = newSessions; 660 } 661 662 /** 663 * Create a new read cipher and return it to caller. 664 */ newReadCipher()665 CipherBox newReadCipher() throws NoSuchAlgorithmException { 666 BulkCipher cipher = cipherSuite.cipher; 667 CipherBox box; 668 if (isClient) { 669 box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV, 670 sslContext.getSecureRandom(), false); 671 svrWriteKey = null; 672 svrWriteIV = null; 673 } else { 674 box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV, 675 sslContext.getSecureRandom(), false); 676 clntWriteKey = null; 677 clntWriteIV = null; 678 } 679 return box; 680 } 681 682 /** 683 * Create a new write cipher and return it to caller. 684 */ newWriteCipher()685 CipherBox newWriteCipher() throws NoSuchAlgorithmException { 686 BulkCipher cipher = cipherSuite.cipher; 687 CipherBox box; 688 if (isClient) { 689 box = cipher.newCipher(protocolVersion, clntWriteKey, clntWriteIV, 690 sslContext.getSecureRandom(), true); 691 clntWriteKey = null; 692 clntWriteIV = null; 693 } else { 694 box = cipher.newCipher(protocolVersion, svrWriteKey, svrWriteIV, 695 sslContext.getSecureRandom(), true); 696 svrWriteKey = null; 697 svrWriteIV = null; 698 } 699 return box; 700 } 701 702 /** 703 * Create a new read MAC and return it to caller. 704 */ newReadMAC()705 MAC newReadMAC() throws NoSuchAlgorithmException, InvalidKeyException { 706 MacAlg macAlg = cipherSuite.macAlg; 707 MAC mac; 708 if (isClient) { 709 mac = macAlg.newMac(protocolVersion, svrMacSecret); 710 svrMacSecret = null; 711 } else { 712 mac = macAlg.newMac(protocolVersion, clntMacSecret); 713 clntMacSecret = null; 714 } 715 return mac; 716 } 717 718 /** 719 * Create a new write MAC and return it to caller. 720 */ newWriteMAC()721 MAC newWriteMAC() throws NoSuchAlgorithmException, InvalidKeyException { 722 MacAlg macAlg = cipherSuite.macAlg; 723 MAC mac; 724 if (isClient) { 725 mac = macAlg.newMac(protocolVersion, clntMacSecret); 726 clntMacSecret = null; 727 } else { 728 mac = macAlg.newMac(protocolVersion, svrMacSecret); 729 svrMacSecret = null; 730 } 731 return mac; 732 } 733 734 /* 735 * Returns true iff the handshake sequence is done, so that 736 * this freshly created session can become the current one. 737 */ isDone()738 boolean isDone() { 739 return state == HandshakeMessage.ht_finished; 740 } 741 742 743 /* 744 * Returns the session which was created through this 745 * handshake sequence ... should be called after isDone() 746 * returns true. 747 */ getSession()748 SSLSessionImpl getSession() { 749 return session; 750 } 751 752 /* 753 * Set the handshake session 754 */ setHandshakeSessionSE(SSLSessionImpl handshakeSession)755 void setHandshakeSessionSE(SSLSessionImpl handshakeSession) { 756 if (conn != null) { 757 conn.setHandshakeSession(handshakeSession); 758 } else { 759 engine.setHandshakeSession(handshakeSession); 760 } 761 } 762 763 /* 764 * Returns true if renegotiation is in use for this connection. 765 */ isSecureRenegotiation()766 boolean isSecureRenegotiation() { 767 return secureRenegotiation; 768 } 769 770 /* 771 * Returns the verify_data from the Finished message sent by the client. 772 */ getClientVerifyData()773 byte[] getClientVerifyData() { 774 return clientVerifyData; 775 } 776 777 /* 778 * Returns the verify_data from the Finished message sent by the server. 779 */ getServerVerifyData()780 byte[] getServerVerifyData() { 781 return serverVerifyData; 782 } 783 784 /* 785 * This routine is fed SSL handshake records when they become available, 786 * and processes messages found therein. 787 */ process_record(InputRecord r, boolean expectingFinished)788 void process_record(InputRecord r, boolean expectingFinished) 789 throws IOException { 790 791 checkThrown(); 792 793 /* 794 * Store the incoming handshake data, then see if we can 795 * now process any completed handshake messages 796 */ 797 input.incomingRecord(r); 798 799 /* 800 * We don't need to create a separate delegatable task 801 * for finished messages. 802 */ 803 if ((conn != null) || expectingFinished) { 804 processLoop(); 805 } else { 806 delegateTask(new PrivilegedExceptionAction<Void>() { 807 public Void run() throws Exception { 808 processLoop(); 809 return null; 810 } 811 }); 812 } 813 } 814 815 /* 816 * On input, we hash messages one at a time since servers may need 817 * to access an intermediate hash to validate a CertificateVerify 818 * message. 819 * 820 * Note that many handshake messages can come in one record (and often 821 * do, to reduce network resource utilization), and one message can also 822 * require multiple records (e.g. very large Certificate messages). 823 */ processLoop()824 void processLoop() throws IOException { 825 826 // need to read off 4 bytes at least to get the handshake 827 // message type and length. 828 while (input.available() >= 4) { 829 byte messageType; 830 int messageLen; 831 832 /* 833 * See if we can read the handshake message header, and 834 * then the entire handshake message. If not, wait till 835 * we can read and process an entire message. 836 */ 837 input.mark(4); 838 839 messageType = (byte)input.getInt8(); 840 messageLen = input.getInt24(); 841 842 if (input.available() < messageLen) { 843 input.reset(); 844 return; 845 } 846 847 /* 848 * Process the messsage. We require 849 * that processMessage() consumes the entire message. In 850 * lieu of explicit error checks (how?!) we assume that the 851 * data will look like garbage on encoding/processing errors, 852 * and that other protocol code will detect such errors. 853 * 854 * Note that digesting is normally deferred till after the 855 * message has been processed, though to process at least the 856 * client's Finished message (i.e. send the server's) we need 857 * to acccelerate that digesting. 858 * 859 * Also, note that hello request messages are never hashed; 860 * that includes the hello request header, too. 861 */ 862 if (messageType == HandshakeMessage.ht_hello_request) { 863 input.reset(); 864 processMessage(messageType, messageLen); 865 input.ignore(4 + messageLen); 866 } else { 867 input.mark(messageLen); 868 processMessage(messageType, messageLen); 869 input.digestNow(); 870 } 871 } 872 } 873 874 875 /** 876 * Returns true iff the handshaker has been activated. 877 * 878 * In activated state, the handshaker may not send any messages out. 879 */ activated()880 boolean activated() { 881 return state >= -1; 882 } 883 884 /** 885 * Returns true iff the handshaker has sent any messages. 886 */ started()887 boolean started() { 888 return state >= 0; // 0: HandshakeMessage.ht_hello_request 889 // 1: HandshakeMessage.ht_client_hello 890 } 891 892 893 /* 894 * Used to kickstart the negotiation ... either writing a 895 * ClientHello or a HelloRequest as appropriate, whichever 896 * the subclass returns. NOP if handshaking's already started. 897 */ kickstart()898 void kickstart() throws IOException { 899 if (state >= 0) { 900 return; 901 } 902 903 HandshakeMessage m = getKickstartMessage(); 904 905 if (debug != null && Debug.isOn("handshake")) { 906 m.print(System.out); 907 } 908 m.write(output); 909 output.flush(); 910 911 state = m.messageType(); 912 } 913 914 /** 915 * Both client and server modes can start handshaking; but the 916 * message they send to do so is different. 917 */ getKickstartMessage()918 abstract HandshakeMessage getKickstartMessage() throws SSLException; 919 920 /* 921 * Client and Server side protocols are each driven though this 922 * call, which processes a single message and drives the appropriate 923 * side of the protocol state machine (depending on the subclass). 924 */ processMessage(byte messageType, int messageLen)925 abstract void processMessage(byte messageType, int messageLen) 926 throws IOException; 927 928 /* 929 * Most alerts in the protocol relate to handshaking problems. 930 * Alerts are detected as the connection reads data. 931 */ handshakeAlert(byte description)932 abstract void handshakeAlert(byte description) throws SSLProtocolException; 933 934 /* 935 * Sends a change cipher spec message and updates the write side 936 * cipher state so that future messages use the just-negotiated spec. 937 */ sendChangeCipherSpec(Finished mesg, boolean lastMessage)938 void sendChangeCipherSpec(Finished mesg, boolean lastMessage) 939 throws IOException { 940 941 output.flush(); // i.e. handshake data 942 943 /* 944 * The write cipher state is protected by the connection write lock 945 * so we must grab it while making the change. We also 946 * make sure no writes occur between sending the ChangeCipherSpec 947 * message, installing the new cipher state, and sending the 948 * Finished message. 949 * 950 * We already hold SSLEngine/SSLSocket "this" by virtue 951 * of this being called from the readRecord code. 952 */ 953 OutputRecord r; 954 if (conn != null) { 955 r = new OutputRecord(Record.ct_change_cipher_spec); 956 } else { 957 r = new EngineOutputRecord(Record.ct_change_cipher_spec, engine); 958 } 959 960 r.setVersion(protocolVersion); 961 r.write(1); // single byte of data 962 963 if (conn != null) { 964 conn.writeLock.lock(); 965 try { 966 conn.writeRecord(r); 967 conn.changeWriteCiphers(); 968 if (debug != null && Debug.isOn("handshake")) { 969 mesg.print(System.out); 970 } 971 mesg.write(output); 972 output.flush(); 973 } finally { 974 conn.writeLock.unlock(); 975 } 976 } else { 977 synchronized (engine.writeLock) { 978 engine.writeRecord((EngineOutputRecord)r); 979 engine.changeWriteCiphers(); 980 if (debug != null && Debug.isOn("handshake")) { 981 mesg.print(System.out); 982 } 983 mesg.write(output); 984 985 if (lastMessage) { 986 output.setFinishedMsg(); 987 } 988 output.flush(); 989 } 990 } 991 } 992 993 /* 994 * Single access point to key calculation logic. Given the 995 * pre-master secret and the nonces from client and server, 996 * produce all the keying material to be used. 997 */ calculateKeys(SecretKey preMasterSecret, ProtocolVersion version)998 void calculateKeys(SecretKey preMasterSecret, ProtocolVersion version) { 999 SecretKey master = calculateMasterSecret(preMasterSecret, version); 1000 session.setMasterSecret(master); 1001 calculateConnectionKeys(master); 1002 } 1003 1004 1005 /* 1006 * Calculate the master secret from its various components. This is 1007 * used for key exchange by all cipher suites. 1008 * 1009 * The master secret is the catenation of three MD5 hashes, each 1010 * consisting of the pre-master secret and a SHA1 hash. Those three 1011 * SHA1 hashes are of (different) constant strings, the pre-master 1012 * secret, and the nonces provided by the client and the server. 1013 */ calculateMasterSecret(SecretKey preMasterSecret, ProtocolVersion requestedVersion)1014 private SecretKey calculateMasterSecret(SecretKey preMasterSecret, 1015 ProtocolVersion requestedVersion) { 1016 1017 if (debug != null && Debug.isOn("keygen")) { 1018 HexDumpEncoder dump = new HexDumpEncoder(); 1019 1020 System.out.println("SESSION KEYGEN:"); 1021 1022 System.out.println("PreMaster Secret:"); 1023 printHex(dump, preMasterSecret.getEncoded()); 1024 1025 // Nonces are dumped with connection keygen, no 1026 // benefit to doing it twice 1027 } 1028 1029 // What algs/params do we need to use? 1030 String masterAlg; 1031 PRF prf; 1032 1033 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 1034 masterAlg = "SunTls12MasterSecret"; 1035 prf = cipherSuite.prfAlg; 1036 } else { 1037 masterAlg = "SunTlsMasterSecret"; 1038 prf = P_NONE; 1039 } 1040 1041 String prfHashAlg = prf.getPRFHashAlg(); 1042 int prfHashLength = prf.getPRFHashLength(); 1043 int prfBlockSize = prf.getPRFBlockSize(); 1044 1045 TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec( 1046 preMasterSecret, protocolVersion.major, protocolVersion.minor, 1047 clnt_random.random_bytes, svr_random.random_bytes, 1048 prfHashAlg, prfHashLength, prfBlockSize); 1049 1050 SecretKey masterSecret; 1051 try { 1052 KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg); 1053 kg.init(spec); 1054 masterSecret = kg.generateKey(); 1055 } catch (GeneralSecurityException e) { 1056 // For RSA premaster secrets, do not signal a protocol error 1057 // due to the Bleichenbacher attack. See comments further down. 1058 if (!preMasterSecret.getAlgorithm().equals( 1059 "TlsRsaPremasterSecret")) { 1060 throw new ProviderException(e); 1061 } 1062 1063 if (debug != null && Debug.isOn("handshake")) { 1064 System.out.println("RSA master secret generation error:"); 1065 e.printStackTrace(System.out); 1066 } 1067 1068 if (requestedVersion != null) { 1069 preMasterSecret = 1070 RSAClientKeyExchange.generateDummySecret(requestedVersion); 1071 } else { 1072 preMasterSecret = 1073 RSAClientKeyExchange.generateDummySecret(protocolVersion); 1074 } 1075 1076 // recursive call with new premaster secret 1077 return calculateMasterSecret(preMasterSecret, null); 1078 } 1079 1080 // if no version check requested (client side handshake), or version 1081 // information is not available (not an RSA premaster secret), 1082 // return master secret immediately. 1083 if ((requestedVersion == null) || 1084 !(masterSecret instanceof TlsMasterSecret)) { 1085 return masterSecret; 1086 } 1087 1088 // we have checked the ClientKeyExchange message when reading TLS 1089 // record, the following check is necessary to ensure that 1090 // JCE provider does not ignore the checking, or the previous 1091 // checking process bypassed the premaster secret version checking. 1092 TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret; 1093 int major = tlsKey.getMajorVersion(); 1094 int minor = tlsKey.getMinorVersion(); 1095 if ((major < 0) || (minor < 0)) { 1096 return masterSecret; 1097 } 1098 1099 // check if the premaster secret version is ok 1100 // the specification says that it must be the maximum version supported 1101 // by the client from its ClientHello message. However, many 1102 // implementations send the negotiated version, so accept both 1103 // for SSL v3.0 and TLS v1.0. 1104 // NOTE that we may be comparing two unsupported version numbers, which 1105 // is why we cannot use object reference equality in this special case. 1106 ProtocolVersion premasterVersion = 1107 ProtocolVersion.valueOf(major, minor); 1108 boolean versionMismatch = (premasterVersion.v != requestedVersion.v); 1109 1110 /* 1111 * we never checked the client_version in server side 1112 * for TLS v1.0 and SSL v3.0. For compatibility, we 1113 * maintain this behavior. 1114 */ 1115 if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) { 1116 versionMismatch = (premasterVersion.v != protocolVersion.v); 1117 } 1118 1119 if (versionMismatch == false) { 1120 // check passed, return key 1121 return masterSecret; 1122 } 1123 1124 // Due to the Bleichenbacher attack, do not signal a protocol error. 1125 // Generate a random premaster secret and continue with the handshake, 1126 // which will fail when verifying the finished messages. 1127 // For more information, see comments in PreMasterSecret. 1128 if (debug != null && Debug.isOn("handshake")) { 1129 System.out.println("RSA PreMasterSecret version error: expected" 1130 + protocolVersion + " or " + requestedVersion + ", decrypted: " 1131 + premasterVersion); 1132 } 1133 preMasterSecret = 1134 RSAClientKeyExchange.generateDummySecret(requestedVersion); 1135 1136 // recursive call with new premaster secret 1137 return calculateMasterSecret(preMasterSecret, null); 1138 } 1139 1140 /* 1141 * Calculate the keys needed for this connection, once the session's 1142 * master secret has been calculated. Uses the master key and nonces; 1143 * the amount of keying material generated is a function of the cipher 1144 * suite that's been negotiated. 1145 * 1146 * This gets called both on the "full handshake" (where we exchanged 1147 * a premaster secret and started a new session) as well as on the 1148 * "fast handshake" (where we just resumed a pre-existing session). 1149 */ calculateConnectionKeys(SecretKey masterKey)1150 void calculateConnectionKeys(SecretKey masterKey) { 1151 /* 1152 * For both the read and write sides of the protocol, we use the 1153 * master to generate MAC secrets and cipher keying material. Block 1154 * ciphers need initialization vectors, which we also generate. 1155 * 1156 * First we figure out how much keying material is needed. 1157 */ 1158 int hashSize = cipherSuite.macAlg.size; 1159 boolean is_exportable = cipherSuite.exportable; 1160 BulkCipher cipher = cipherSuite.cipher; 1161 int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0; 1162 1163 // Which algs/params do we need to use? 1164 String keyMaterialAlg; 1165 PRF prf; 1166 1167 if (protocolVersion.v >= ProtocolVersion.TLS12.v) { 1168 keyMaterialAlg = "SunTls12KeyMaterial"; 1169 prf = cipherSuite.prfAlg; 1170 } else { 1171 keyMaterialAlg = "SunTlsKeyMaterial"; 1172 prf = P_NONE; 1173 } 1174 1175 String prfHashAlg = prf.getPRFHashAlg(); 1176 int prfHashLength = prf.getPRFHashLength(); 1177 int prfBlockSize = prf.getPRFBlockSize(); 1178 1179 TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec( 1180 masterKey, protocolVersion.major, protocolVersion.minor, 1181 clnt_random.random_bytes, svr_random.random_bytes, 1182 cipher.algorithm, cipher.keySize, expandedKeySize, 1183 cipher.ivSize, hashSize, 1184 prfHashAlg, prfHashLength, prfBlockSize); 1185 1186 try { 1187 KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg); 1188 kg.init(spec); 1189 TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey(); 1190 1191 clntWriteKey = keySpec.getClientCipherKey(); 1192 svrWriteKey = keySpec.getServerCipherKey(); 1193 1194 // Return null if IVs are not supposed to be generated. 1195 // e.g. TLS 1.1+. 1196 clntWriteIV = keySpec.getClientIv(); 1197 svrWriteIV = keySpec.getServerIv(); 1198 1199 clntMacSecret = keySpec.getClientMacKey(); 1200 svrMacSecret = keySpec.getServerMacKey(); 1201 } catch (GeneralSecurityException e) { 1202 throw new ProviderException(e); 1203 } 1204 1205 // 1206 // Dump the connection keys as they're generated. 1207 // 1208 if (debug != null && Debug.isOn("keygen")) { 1209 synchronized (System.out) { 1210 HexDumpEncoder dump = new HexDumpEncoder(); 1211 1212 System.out.println("CONNECTION KEYGEN:"); 1213 1214 // Inputs: 1215 System.out.println("Client Nonce:"); 1216 printHex(dump, clnt_random.random_bytes); 1217 System.out.println("Server Nonce:"); 1218 printHex(dump, svr_random.random_bytes); 1219 System.out.println("Master Secret:"); 1220 printHex(dump, masterKey.getEncoded()); 1221 1222 // Outputs: 1223 System.out.println("Client MAC write Secret:"); 1224 printHex(dump, clntMacSecret.getEncoded()); 1225 System.out.println("Server MAC write Secret:"); 1226 printHex(dump, svrMacSecret.getEncoded()); 1227 1228 if (clntWriteKey != null) { 1229 System.out.println("Client write key:"); 1230 printHex(dump, clntWriteKey.getEncoded()); 1231 System.out.println("Server write key:"); 1232 printHex(dump, svrWriteKey.getEncoded()); 1233 } else { 1234 System.out.println("... no encryption keys used"); 1235 } 1236 1237 if (clntWriteIV != null) { 1238 System.out.println("Client write IV:"); 1239 printHex(dump, clntWriteIV.getIV()); 1240 System.out.println("Server write IV:"); 1241 printHex(dump, svrWriteIV.getIV()); 1242 } else { 1243 if (protocolVersion.v >= ProtocolVersion.TLS11.v) { 1244 System.out.println( 1245 "... no IV derived for this protocol"); 1246 } else { 1247 System.out.println("... no IV used for this cipher"); 1248 } 1249 } 1250 System.out.flush(); 1251 } 1252 } 1253 } 1254 printHex(HexDumpEncoder dump, byte[] bytes)1255 private static void printHex(HexDumpEncoder dump, byte[] bytes) { 1256 if (bytes == null) { 1257 System.out.println("(key bytes not available)"); 1258 } else { 1259 try { 1260 dump.encodeBuffer(bytes, System.out); 1261 } catch (IOException e) { 1262 // just for debugging, ignore this 1263 } 1264 } 1265 } 1266 1267 /** 1268 * Throw an SSLException with the specified message and cause. 1269 * Shorthand until a new SSLException constructor is added. 1270 * This method never returns. 1271 */ throwSSLException(String msg, Throwable cause)1272 static void throwSSLException(String msg, Throwable cause) 1273 throws SSLException { 1274 SSLException e = new SSLException(msg); 1275 e.initCause(cause); 1276 throw e; 1277 } 1278 1279 1280 /* 1281 * Implement a simple task delegator. 1282 * 1283 * We are currently implementing this as a single delegator, may 1284 * try for parallel tasks later. Client Authentication could 1285 * benefit from this, where ClientKeyExchange/CertificateVerify 1286 * could be carried out in parallel. 1287 */ 1288 class DelegatedTask<E> implements Runnable { 1289 1290 private PrivilegedExceptionAction<E> pea; 1291 DelegatedTask(PrivilegedExceptionAction<E> pea)1292 DelegatedTask(PrivilegedExceptionAction<E> pea) { 1293 this.pea = pea; 1294 } 1295 run()1296 public void run() { 1297 synchronized (engine) { 1298 try { 1299 AccessController.doPrivileged(pea, engine.getAcc()); 1300 } catch (PrivilegedActionException pae) { 1301 thrown = pae.getException(); 1302 } catch (RuntimeException rte) { 1303 thrown = rte; 1304 } 1305 delegatedTask = null; 1306 taskDelegated = false; 1307 } 1308 } 1309 } 1310 delegateTask(PrivilegedExceptionAction<T> pea)1311 private <T> void delegateTask(PrivilegedExceptionAction<T> pea) { 1312 delegatedTask = new DelegatedTask<T>(pea); 1313 taskDelegated = false; 1314 thrown = null; 1315 } 1316 getTask()1317 DelegatedTask getTask() { 1318 if (!taskDelegated) { 1319 taskDelegated = true; 1320 return delegatedTask; 1321 } else { 1322 return null; 1323 } 1324 } 1325 1326 /* 1327 * See if there are any tasks which need to be delegated 1328 * 1329 * Locked by SSLEngine.this. 1330 */ taskOutstanding()1331 boolean taskOutstanding() { 1332 return (delegatedTask != null); 1333 } 1334 1335 /* 1336 * The previous caller failed for some reason, report back the 1337 * Exception. We won't worry about Error's. 1338 * 1339 * Locked by SSLEngine.this. 1340 */ checkThrown()1341 void checkThrown() throws SSLException { 1342 synchronized (thrownLock) { 1343 if (thrown != null) { 1344 1345 String msg = thrown.getMessage(); 1346 1347 if (msg == null) { 1348 msg = "Delegated task threw Exception/Error"; 1349 } 1350 1351 /* 1352 * See what the underlying type of exception is. We should 1353 * throw the same thing. Chain thrown to the new exception. 1354 */ 1355 Exception e = thrown; 1356 thrown = null; 1357 1358 if (e instanceof RuntimeException) { 1359 throw (RuntimeException) 1360 new RuntimeException(msg).initCause(e); 1361 } else if (e instanceof SSLHandshakeException) { 1362 throw (SSLHandshakeException) 1363 new SSLHandshakeException(msg).initCause(e); 1364 } else if (e instanceof SSLKeyException) { 1365 throw (SSLKeyException) 1366 new SSLKeyException(msg).initCause(e); 1367 } else if (e instanceof SSLPeerUnverifiedException) { 1368 throw (SSLPeerUnverifiedException) 1369 new SSLPeerUnverifiedException(msg).initCause(e); 1370 } else if (e instanceof SSLProtocolException) { 1371 throw (SSLProtocolException) 1372 new SSLProtocolException(msg).initCause(e); 1373 } else { 1374 /* 1375 * If it's SSLException or any other Exception, 1376 * we'll wrap it in an SSLException. 1377 */ 1378 throw (SSLException) 1379 new SSLException(msg).initCause(e); 1380 } 1381 } 1382 } 1383 } 1384 } 1385