History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/Handshaker.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/Handshaker.java+1386−0
@@ -0,0 +1,1386 @@
1+/*
2+ * Copyright (c) 1996, 2011, 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+
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+
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+
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+ */
265+ void fatalSE(byte b, String diagnostic) throws IOException {
266+ fatalSE(b, diagnostic, null);
267+ }
268+
269+ void fatalSE(byte b, Throwable cause) throws IOException {
270+ fatalSE(b, null, cause);
271+ }
272+
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+
282+ void warningSE(byte b) {
283+ if (conn != null) {
284+ conn.warning(b);
285+ } else {
286+ engine.warning(b);
287+ }
288+ }
289+
290+ String getRawHostnameSE() {
291+ if (conn != null) {
292+ return conn.getRawHostname();
293+ } else {
294+ return engine.getPeerHost();
295+ }
296+ }
297+
298+ String getHostSE() {
299+ if (conn != null) {
300+ return conn.getHost();
301+ } else {
302+ return engine.getPeerHost();
303+ }
304+ }
305+
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+
319+ boolean isLoopbackSE() {
320+ if (conn != null) {
321+ return conn.getInetAddress().isLoopbackAddress();
322+ } else {
323+ return false;
324+ }
325+ }
326+
327+ int getPortSE() {
328+ if (conn != null) {
329+ return conn.getPort();
330+ } else {
331+ return engine.getPeerPort();
332+ }
333+ }
334+
335+ int getLocalPortSE() {
336+ if (conn != null) {
337+ return conn.getLocalPort();
338+ } else {
339+ return -1;
340+ }
341+ }
342+
343+ AccessControlContext getAccSE() {
344+ if (conn != null) {
345+ return conn.getAcc();
346+ } else {
347+ return engine.getAcc();
348+ }
349+ }
350+
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+ */
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+ */
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+ */
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+ */
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+
408+ Collection<SignatureAndHashAlgorithm> getLocalSupportedSignAlgs() {
409+ if (localSupportedSignAlgs == null) {
410+ localSupportedSignAlgs =
411+ SignatureAndHashAlgorithm.getSupportedAlgorithms(
412+ algorithmConstraints);
413+ }
414+
415+ return localSupportedSignAlgs;
416+ }
417+
418+ void setPeerSupportedSignAlgs(
419+ Collection<SignatureAndHashAlgorithm> algorithms) {
420+ peerSupportedSignAlgs =
421+ new ArrayList<SignatureAndHashAlgorithm>(algorithms);
422+ }
423+
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
658+ void setEnableSessionCreation(boolean newSessions) {
659+ enableNewSession = newSessions;
660+ }
661+
662+ /**
663+ * Create a new read cipher and return it to caller.
664+ */
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+ */
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+ */
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+ */
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+ */
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+ */
748+ SSLSessionImpl getSession() {
749+ return session;
750+ }
751+
752+ /*
753+ * Set the handshake session
754+ */
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+ */
766+ boolean isSecureRenegotiation() {
767+ return secureRenegotiation;
768+ }
769+
770+ /*
771+ * Returns the verify_data from the Finished message sent by the client.
772+ */
773+ byte[] getClientVerifyData() {
774+ return clientVerifyData;
775+ }
776+
777+ /*
778+ * Returns the verify_data from the Finished message sent by the server.
779+ */
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+ */
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+ */
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+ */
880+ boolean activated() {
881+ return state >= -1;
882+ }
883+
884+ /**
885+ * Returns true iff the handshaker has sent any messages.
886+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ */
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+ System.out.println("Generating new random premaster secret");
1067+ }
1068+
1069+ if (requestedVersion != null) {
1070+ preMasterSecret =
1071+ RSAClientKeyExchange.generateDummySecret(requestedVersion);
1072+ } else {
1073+ preMasterSecret =
1074+ RSAClientKeyExchange.generateDummySecret(protocolVersion);
1075+ }
1076+
1077+ // recursive call with new premaster secret
1078+ return calculateMasterSecret(preMasterSecret, null);
1079+ }
1080+
1081+ // if no version check requested (client side handshake), or version
1082+ // information is not available (not an RSA premaster secret),
1083+ // return master secret immediately.
1084+ if ((requestedVersion == null) ||
1085+ !(masterSecret instanceof TlsMasterSecret)) {
1086+ return masterSecret;
1087+ }
1088+
1089+ // we have checked the ClientKeyExchange message when reading TLS
1090+ // record, the following check is necessary to ensure that
1091+ // JCE provider does not ignore the checking, or the previous
1092+ // checking process bypassed the premaster secret version checking.
1093+ TlsMasterSecret tlsKey = (TlsMasterSecret)masterSecret;
1094+ int major = tlsKey.getMajorVersion();
1095+ int minor = tlsKey.getMinorVersion();
1096+ if ((major < 0) || (minor < 0)) {
1097+ return masterSecret;
1098+ }
1099+
1100+ // check if the premaster secret version is ok
1101+ // the specification says that it must be the maximum version supported
1102+ // by the client from its ClientHello message. However, many
1103+ // implementations send the negotiated version, so accept both
1104+ // for SSL v3.0 and TLS v1.0.
1105+ // NOTE that we may be comparing two unsupported version numbers, which
1106+ // is why we cannot use object reference equality in this special case.
1107+ ProtocolVersion premasterVersion =
1108+ ProtocolVersion.valueOf(major, minor);
1109+ boolean versionMismatch = (premasterVersion.v != requestedVersion.v);
1110+
1111+ /*
1112+ * we never checked the client_version in server side
1113+ * for TLS v1.0 and SSL v3.0. For compatibility, we
1114+ * maintain this behavior.
1115+ */
1116+ if (versionMismatch && requestedVersion.v <= ProtocolVersion.TLS10.v) {
1117+ versionMismatch = (premasterVersion.v != protocolVersion.v);
1118+ }
1119+
1120+ if (versionMismatch == false) {
1121+ // check passed, return key
1122+ return masterSecret;
1123+ }
1124+
1125+ // Due to the Bleichenbacher attack, do not signal a protocol error.
1126+ // Generate a random premaster secret and continue with the handshake,
1127+ // which will fail when verifying the finished messages.
1128+ // For more information, see comments in PreMasterSecret.
1129+ if (debug != null && Debug.isOn("handshake")) {
1130+ System.out.println("RSA PreMasterSecret version error: expected"
1131+ + protocolVersion + " or " + requestedVersion + ", decrypted: "
1132+ + premasterVersion);
1133+ System.out.println("Generating new random premaster secret");
1134+ }
1135+ preMasterSecret =
1136+ RSAClientKeyExchange.generateDummySecret(requestedVersion);
1137+
1138+ // recursive call with new premaster secret
1139+ return calculateMasterSecret(preMasterSecret, null);
1140+ }
1141+
1142+ /*
1143+ * Calculate the keys needed for this connection, once the session's
1144+ * master secret has been calculated. Uses the master key and nonces;
1145+ * the amount of keying material generated is a function of the cipher
1146+ * suite that's been negotiated.
1147+ *
1148+ * This gets called both on the "full handshake" (where we exchanged
1149+ * a premaster secret and started a new session) as well as on the
1150+ * "fast handshake" (where we just resumed a pre-existing session).
1151+ */
1152+ void calculateConnectionKeys(SecretKey masterKey) {
1153+ /*
1154+ * For both the read and write sides of the protocol, we use the
1155+ * master to generate MAC secrets and cipher keying material. Block
1156+ * ciphers need initialization vectors, which we also generate.
1157+ *
1158+ * First we figure out how much keying material is needed.
1159+ */
1160+ int hashSize = cipherSuite.macAlg.size;
1161+ boolean is_exportable = cipherSuite.exportable;
1162+ BulkCipher cipher = cipherSuite.cipher;
1163+ int expandedKeySize = is_exportable ? cipher.expandedKeySize : 0;
1164+
1165+ // Which algs/params do we need to use?
1166+ String keyMaterialAlg;
1167+ PRF prf;
1168+
1169+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1170+ keyMaterialAlg = "SunTls12KeyMaterial";
1171+ prf = cipherSuite.prfAlg;
1172+ } else {
1173+ keyMaterialAlg = "SunTlsKeyMaterial";
1174+ prf = P_NONE;
1175+ }
1176+
1177+ String prfHashAlg = prf.getPRFHashAlg();
1178+ int prfHashLength = prf.getPRFHashLength();
1179+ int prfBlockSize = prf.getPRFBlockSize();
1180+
1181+ TlsKeyMaterialParameterSpec spec = new TlsKeyMaterialParameterSpec(
1182+ masterKey, protocolVersion.major, protocolVersion.minor,
1183+ clnt_random.random_bytes, svr_random.random_bytes,
1184+ cipher.algorithm, cipher.keySize, expandedKeySize,
1185+ cipher.ivSize, hashSize,
1186+ prfHashAlg, prfHashLength, prfBlockSize);
1187+
1188+ try {
1189+ KeyGenerator kg = JsseJce.getKeyGenerator(keyMaterialAlg);
1190+ kg.init(spec);
1191+ TlsKeyMaterialSpec keySpec = (TlsKeyMaterialSpec)kg.generateKey();
1192+
1193+ clntWriteKey = keySpec.getClientCipherKey();
1194+ svrWriteKey = keySpec.getServerCipherKey();
1195+
1196+ // Return null if IVs are not supposed to be generated.
1197+ // e.g. TLS 1.1+.
1198+ clntWriteIV = keySpec.getClientIv();
1199+ svrWriteIV = keySpec.getServerIv();
1200+
1201+ clntMacSecret = keySpec.getClientMacKey();
1202+ svrMacSecret = keySpec.getServerMacKey();
1203+ } catch (GeneralSecurityException e) {
1204+ throw new ProviderException(e);
1205+ }
1206+
1207+ //
1208+ // Dump the connection keys as they're generated.
1209+ //
1210+ if (debug != null && Debug.isOn("keygen")) {
1211+ synchronized (System.out) {
1212+ HexDumpEncoder dump = new HexDumpEncoder();
1213+
1214+ System.out.println("CONNECTION KEYGEN:");
1215+
1216+ // Inputs:
1217+ System.out.println("Client Nonce:");
1218+ printHex(dump, clnt_random.random_bytes);
1219+ System.out.println("Server Nonce:");
1220+ printHex(dump, svr_random.random_bytes);
1221+ System.out.println("Master Secret:");
1222+ printHex(dump, masterKey.getEncoded());
1223+
1224+ // Outputs:
1225+ System.out.println("Client MAC write Secret:");
1226+ printHex(dump, clntMacSecret.getEncoded());
1227+ System.out.println("Server MAC write Secret:");
1228+ printHex(dump, svrMacSecret.getEncoded());
1229+
1230+ if (clntWriteKey != null) {
1231+ System.out.println("Client write key:");
1232+ printHex(dump, clntWriteKey.getEncoded());
1233+ System.out.println("Server write key:");
1234+ printHex(dump, svrWriteKey.getEncoded());
1235+ } else {
1236+ System.out.println("... no encryption keys used");
1237+ }
1238+
1239+ if (clntWriteIV != null) {
1240+ System.out.println("Client write IV:");
1241+ printHex(dump, clntWriteIV.getIV());
1242+ System.out.println("Server write IV:");
1243+ printHex(dump, svrWriteIV.getIV());
1244+ } else {
1245+ if (protocolVersion.v >= ProtocolVersion.TLS11.v) {
1246+ System.out.println(
1247+ "... no IV derived for this protocol");
1248+ } else {
1249+ System.out.println("... no IV used for this cipher");
1250+ }
1251+ }
1252+ System.out.flush();
1253+ }
1254+ }
1255+ }
1256+
1257+ private static void printHex(HexDumpEncoder dump, byte[] bytes) {
1258+ if (bytes == null) {
1259+ System.out.println("(key bytes not available)");
1260+ } else {
1261+ try {
1262+ dump.encodeBuffer(bytes, System.out);
1263+ } catch (IOException e) {
1264+ // just for debugging, ignore this
1265+ }
1266+ }
1267+ }
1268+
1269+ /**
1270+ * Throw an SSLException with the specified message and cause.
1271+ * Shorthand until a new SSLException constructor is added.
1272+ * This method never returns.
1273+ */
1274+ static void throwSSLException(String msg, Throwable cause)
1275+ throws SSLException {
1276+ SSLException e = new SSLException(msg);
1277+ e.initCause(cause);
1278+ throw e;
1279+ }
1280+
1281+
1282+ /*
1283+ * Implement a simple task delegator.
1284+ *
1285+ * We are currently implementing this as a single delegator, may
1286+ * try for parallel tasks later. Client Authentication could
1287+ * benefit from this, where ClientKeyExchange/CertificateVerify
1288+ * could be carried out in parallel.
1289+ */
1290+ class DelegatedTask<E> implements Runnable {
1291+
1292+ private PrivilegedExceptionAction<E> pea;
1293+
1294+ DelegatedTask(PrivilegedExceptionAction<E> pea) {
1295+ this.pea = pea;
1296+ }
1297+
1298+ public void run() {
1299+ synchronized (engine) {
1300+ try {
1301+ AccessController.doPrivileged(pea, engine.getAcc());
1302+ } catch (PrivilegedActionException pae) {
1303+ thrown = pae.getException();
1304+ } catch (RuntimeException rte) {
1305+ thrown = rte;
1306+ }
1307+ delegatedTask = null;
1308+ taskDelegated = false;
1309+ }
1310+ }
1311+ }
1312+
1313+ private <T> void delegateTask(PrivilegedExceptionAction<T> pea) {
1314+ delegatedTask = new DelegatedTask<T>(pea);
1315+ taskDelegated = false;
1316+ thrown = null;
1317+ }
1318+
1319+ DelegatedTask getTask() {
1320+ if (!taskDelegated) {
1321+ taskDelegated = true;
1322+ return delegatedTask;
1323+ } else {
1324+ return null;
1325+ }
1326+ }
1327+
1328+ /*
1329+ * See if there are any tasks which need to be delegated
1330+ *
1331+ * Locked by SSLEngine.this.
1332+ */
1333+ boolean taskOutstanding() {
1334+ return (delegatedTask != null);
1335+ }
1336+
1337+ /*
1338+ * The previous caller failed for some reason, report back the
1339+ * Exception. We won't worry about Error's.
1340+ *
1341+ * Locked by SSLEngine.this.
1342+ */
1343+ void checkThrown() throws SSLException {
1344+ synchronized (thrownLock) {
1345+ if (thrown != null) {
1346+
1347+ String msg = thrown.getMessage();
1348+
1349+ if (msg == null) {
1350+ msg = "Delegated task threw Exception/Error";
1351+ }
1352+
1353+ /*
1354+ * See what the underlying type of exception is. We should
1355+ * throw the same thing. Chain thrown to the new exception.
1356+ */
1357+ Exception e = thrown;
1358+ thrown = null;
1359+
1360+ if (e instanceof RuntimeException) {
1361+ throw (RuntimeException)
1362+ new RuntimeException(msg).initCause(e);
1363+ } else if (e instanceof SSLHandshakeException) {
1364+ throw (SSLHandshakeException)
1365+ new SSLHandshakeException(msg).initCause(e);
1366+ } else if (e instanceof SSLKeyException) {
1367+ throw (SSLKeyException)
1368+ new SSLKeyException(msg).initCause(e);
1369+ } else if (e instanceof SSLPeerUnverifiedException) {
1370+ throw (SSLPeerUnverifiedException)
1371+ new SSLPeerUnverifiedException(msg).initCause(e);
1372+ } else if (e instanceof SSLProtocolException) {
1373+ throw (SSLProtocolException)
1374+ new SSLProtocolException(msg).initCause(e);
1375+ } else {
1376+ /*
1377+ * If it's SSLException or any other Exception,
1378+ * we'll wrap it in an SSLException.
1379+ */
1380+ throw (SSLException)
1381+ new SSLException(msg).initCause(e);
1382+ }
1383+ }
1384+ }
1385+ }
1386+}