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/HandshakeMessage.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/HandshakeMessage.java+2006−0
@@ -0,0 +1,2006 @@
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+package sun.security.ssl;
27+
28+import java.io.*;
29+import java.math.BigInteger;
30+import java.security.*;
31+import java.security.interfaces.*;
32+import java.security.spec.*;
33+import java.security.cert.*;
34+import java.security.cert.Certificate;
35+import java.util.*;
36+import java.util.concurrent.ConcurrentHashMap;
37+
38+import java.lang.reflect.*;
39+
40+import javax.security.auth.x500.X500Principal;
41+
42+import javax.crypto.KeyGenerator;
43+import javax.crypto.SecretKey;
44+
45+import javax.net.ssl.*;
46+
47+import sun.security.internal.spec.TlsPrfParameterSpec;
48+import sun.security.ssl.CipherSuite.*;
49+import static sun.security.ssl.CipherSuite.PRF.*;
50+
51+/**
52+ * Many data structures are involved in the handshake messages. These
53+ * classes are used as structures, with public data members. They are
54+ * not visible outside the SSL package.
55+ *
56+ * Handshake messages all have a common header format, and they are all
57+ * encoded in a "handshake data" SSL record substream. The base class
58+ * here (HandshakeMessage) provides a common framework and records the
59+ * SSL record type of the particular handshake message.
60+ *
61+ * This file contains subclasses for all the basic handshake messages.
62+ * All handshake messages know how to encode and decode themselves on
63+ * SSL streams; this facilitates using the same code on SSL client and
64+ * server sides, although they don't send and receive the same messages.
65+ *
66+ * Messages also know how to print themselves, which is quite handy
67+ * for debugging. They always identify their type, and can optionally
68+ * dump all of their content.
69+ *
70+ * @author David Brownell
71+ */
72+public abstract class HandshakeMessage {
73+
74+ HandshakeMessage() { }
75+
76+ // enum HandshakeType:
77+ static final byte ht_hello_request = 0;
78+ static final byte ht_client_hello = 1;
79+ static final byte ht_server_hello = 2;
80+
81+ static final byte ht_certificate = 11;
82+ static final byte ht_server_key_exchange = 12;
83+ static final byte ht_certificate_request = 13;
84+ static final byte ht_server_hello_done = 14;
85+ static final byte ht_certificate_verify = 15;
86+ static final byte ht_client_key_exchange = 16;
87+
88+ static final byte ht_finished = 20;
89+
90+ /* Class and subclass dynamic debugging support */
91+ public static final Debug debug = Debug.getInstance("ssl");
92+
93+ /**
94+ * Utility method to convert a BigInteger to a byte array in unsigned
95+ * format as needed in the handshake messages. BigInteger uses
96+ * 2's complement format, i.e. it prepends an extra zero if the MSB
97+ * is set. We remove that.
98+ */
99+ static byte[] toByteArray(BigInteger bi) {
100+ byte[] b = bi.toByteArray();
101+ if ((b.length > 1) && (b[0] == 0)) {
102+ int n = b.length - 1;
103+ byte[] newarray = new byte[n];
104+ System.arraycopy(b, 1, newarray, 0, n);
105+ b = newarray;
106+ }
107+ return b;
108+ }
109+
110+ /*
111+ * SSL 3.0 MAC padding constants.
112+ * Also used by CertificateVerify and Finished during the handshake.
113+ */
114+ static final byte[] MD5_pad1 = genPad(0x36, 48);
115+ static final byte[] MD5_pad2 = genPad(0x5c, 48);
116+
117+ static final byte[] SHA_pad1 = genPad(0x36, 40);
118+ static final byte[] SHA_pad2 = genPad(0x5c, 40);
119+
120+ private static byte[] genPad(int b, int count) {
121+ byte[] padding = new byte[count];
122+ Arrays.fill(padding, (byte)b);
123+ return padding;
124+ }
125+
126+ /*
127+ * Write a handshake message on the (handshake) output stream.
128+ * This is just a four byte header followed by the data.
129+ *
130+ * NOTE that huge messages -- notably, ones with huge cert
131+ * chains -- are handled correctly.
132+ */
133+ final void write(HandshakeOutStream s) throws IOException {
134+ int len = messageLength();
135+ if (len > (1 << 24)) {
136+ throw new SSLException("Handshake message too big"
137+ + ", type = " + messageType() + ", len = " + len);
138+ }
139+ s.write(messageType());
140+ s.putInt24(len);
141+ send(s);
142+ }
143+
144+ /*
145+ * Subclasses implement these methods so those kinds of
146+ * messages can be emitted. Base class delegates to subclass.
147+ */
148+ abstract int messageType();
149+ abstract int messageLength();
150+ abstract void send(HandshakeOutStream s) throws IOException;
151+
152+ /*
153+ * Write a descriptive message on the output stream; for debugging.
154+ */
155+ abstract void print(PrintStream p) throws IOException;
156+
157+//
158+// NOTE: the rest of these classes are nested within this one, and are
159+// imported by other classes in this package. There are a few other
160+// handshake message classes, not neatly nested here because of current
161+// licensing requirement for native (RSA) methods. They belong here,
162+// but those native methods complicate things a lot!
163+//
164+
165+
166+/*
167+ * HelloRequest ... SERVER --> CLIENT
168+ *
169+ * Server can ask the client to initiate a new handshake, e.g. to change
170+ * session parameters after a connection has been (re)established.
171+ */
172+static final class HelloRequest extends HandshakeMessage {
173+ int messageType() { return ht_hello_request; }
174+
175+ HelloRequest() { }
176+
177+ HelloRequest(HandshakeInStream in) throws IOException
178+ {
179+ // nothing in this message
180+ }
181+
182+ int messageLength() { return 0; }
183+
184+ void send(HandshakeOutStream out) throws IOException
185+ {
186+ // nothing in this messaage
187+ }
188+
189+ void print(PrintStream out) throws IOException
190+ {
191+ out.println("*** HelloRequest (empty)");
192+ }
193+
194+}
195+
196+
197+/*
198+ * ClientHello ... CLIENT --> SERVER
199+ *
200+ * Client initiates handshake by telling server what it wants, and what it
201+ * can support (prioritized by what's first in the ciphe suite list).
202+ *
203+ * By RFC2246:7.4.1.2 it's explicitly anticipated that this message
204+ * will have more data added at the end ... e.g. what CAs the client trusts.
205+ * Until we know how to parse it, we will just read what we know
206+ * about, and let our caller handle the jumps over unknown data.
207+ */
208+static final class ClientHello extends HandshakeMessage {
209+
210+ ProtocolVersion protocolVersion;
211+ RandomCookie clnt_random;
212+ SessionId sessionId;
213+ private CipherSuiteList cipherSuites;
214+ byte[] compression_methods;
215+
216+ HelloExtensions extensions = new HelloExtensions();
217+
218+ private final static byte[] NULL_COMPRESSION = new byte[] {0};
219+
220+ ClientHello(SecureRandom generator, ProtocolVersion protocolVersion,
221+ SessionId sessionId, CipherSuiteList cipherSuites) {
222+
223+ this.protocolVersion = protocolVersion;
224+ this.sessionId = sessionId;
225+ this.cipherSuites = cipherSuites;
226+
227+ if (cipherSuites.containsEC()) {
228+ extensions.add(SupportedEllipticCurvesExtension.DEFAULT);
229+ extensions.add(SupportedEllipticPointFormatsExtension.DEFAULT);
230+ }
231+
232+ clnt_random = new RandomCookie(generator);
233+ compression_methods = NULL_COMPRESSION;
234+ }
235+
236+ ClientHello(HandshakeInStream s, int messageLength) throws IOException {
237+ protocolVersion = ProtocolVersion.valueOf(s.getInt8(), s.getInt8());
238+ clnt_random = new RandomCookie(s);
239+ sessionId = new SessionId(s.getBytes8());
240+ cipherSuites = new CipherSuiteList(s);
241+ compression_methods = s.getBytes8();
242+ if (messageLength() != messageLength) {
243+ extensions = new HelloExtensions(s);
244+ }
245+ }
246+
247+ CipherSuiteList getCipherSuites() {
248+ return cipherSuites;
249+ }
250+
251+ // add renegotiation_info extension
252+ void addRenegotiationInfoExtension(byte[] clientVerifyData) {
253+ HelloExtension renegotiationInfo = new RenegotiationInfoExtension(
254+ clientVerifyData, new byte[0]);
255+ extensions.add(renegotiationInfo);
256+ }
257+
258+ // add server_name extension
259+ void addServerNameIndicationExtension(String hostname) {
260+ // We would have checked that the hostname ia a FQDN.
261+ ArrayList<String> hostnames = new ArrayList<>(1);
262+ hostnames.add(hostname);
263+
264+ try {
265+ extensions.add(new ServerNameExtension(hostnames));
266+ } catch (IOException ioe) {
267+ // ignore the exception and return
268+ }
269+ }
270+
271+ // add signature_algorithm extension
272+ void addSignatureAlgorithmsExtension(
273+ Collection<SignatureAndHashAlgorithm> algorithms) {
274+ HelloExtension signatureAlgorithm =
275+ new SignatureAlgorithmsExtension(algorithms);
276+ extensions.add(signatureAlgorithm);
277+ }
278+
279+ @Override
280+ int messageType() { return ht_client_hello; }
281+
282+ @Override
283+ int messageLength() {
284+ /*
285+ * Add fixed size parts of each field...
286+ * version + random + session + cipher + compress
287+ */
288+ return (2 + 32 + 1 + 2 + 1
289+ + sessionId.length() /* ... + variable parts */
290+ + (cipherSuites.size() * 2)
291+ + compression_methods.length)
292+ + extensions.length();
293+ }
294+
295+ @Override
296+ void send(HandshakeOutStream s) throws IOException {
297+ s.putInt8(protocolVersion.major);
298+ s.putInt8(protocolVersion.minor);
299+ clnt_random.send(s);
300+ s.putBytes8(sessionId.getId());
301+ cipherSuites.send(s);
302+ s.putBytes8(compression_methods);
303+ extensions.send(s);
304+ }
305+
306+ @Override
307+ void print(PrintStream s) throws IOException {
308+ s.println("*** ClientHello, " + protocolVersion);
309+
310+ if (debug != null && Debug.isOn("verbose")) {
311+ s.print("RandomCookie: ");
312+ clnt_random.print(s);
313+
314+ s.print("Session ID: ");
315+ s.println(sessionId);
316+
317+ s.println("Cipher Suites: " + cipherSuites);
318+
319+ Debug.println(s, "Compression Methods", compression_methods);
320+ extensions.print(s);
321+ s.println("***");
322+ }
323+ }
324+}
325+
326+/*
327+ * ServerHello ... SERVER --> CLIENT
328+ *
329+ * Server chooses protocol options from among those it supports and the
330+ * client supports. Then it sends the basic session descriptive parameters
331+ * back to the client.
332+ */
333+static final
334+class ServerHello extends HandshakeMessage
335+{
336+ int messageType() { return ht_server_hello; }
337+
338+ ProtocolVersion protocolVersion;
339+ RandomCookie svr_random;
340+ SessionId sessionId;
341+ CipherSuite cipherSuite;
342+ byte compression_method;
343+ HelloExtensions extensions = new HelloExtensions();
344+
345+ ServerHello() {
346+ // empty
347+ }
348+
349+ ServerHello(HandshakeInStream input, int messageLength)
350+ throws IOException {
351+ protocolVersion = ProtocolVersion.valueOf(input.getInt8(),
352+ input.getInt8());
353+ svr_random = new RandomCookie(input);
354+ sessionId = new SessionId(input.getBytes8());
355+ cipherSuite = CipherSuite.valueOf(input.getInt8(), input.getInt8());
356+ compression_method = (byte)input.getInt8();
357+ if (messageLength() != messageLength) {
358+ extensions = new HelloExtensions(input);
359+ }
360+ }
361+
362+ int messageLength()
363+ {
364+ // almost fixed size, except session ID and extensions:
365+ // major + minor = 2
366+ // random = 32
367+ // session ID len field = 1
368+ // cipher suite + compression = 3
369+ // extensions: if present, 2 + length of extensions
370+ return 38 + sessionId.length() + extensions.length();
371+ }
372+
373+ void send(HandshakeOutStream s) throws IOException
374+ {
375+ s.putInt8(protocolVersion.major);
376+ s.putInt8(protocolVersion.minor);
377+ svr_random.send(s);
378+ s.putBytes8(sessionId.getId());
379+ s.putInt8(cipherSuite.id >> 8);
380+ s.putInt8(cipherSuite.id & 0xff);
381+ s.putInt8(compression_method);
382+ extensions.send(s);
383+ }
384+
385+ void print(PrintStream s) throws IOException
386+ {
387+ s.println("*** ServerHello, " + protocolVersion);
388+
389+ if (debug != null && Debug.isOn("verbose")) {
390+ s.print("RandomCookie: ");
391+ svr_random.print(s);
392+
393+ int i;
394+
395+ s.print("Session ID: ");
396+ s.println(sessionId);
397+
398+ s.println("Cipher Suite: " + cipherSuite);
399+ s.println("Compression Method: " + compression_method);
400+ extensions.print(s);
401+ s.println("***");
402+ }
403+ }
404+}
405+
406+
407+/*
408+ * CertificateMsg ... send by both CLIENT and SERVER
409+ *
410+ * Each end of a connection may need to pass its certificate chain to
411+ * the other end. Such chains are intended to validate an identity with
412+ * reference to some certifying authority. Examples include companies
413+ * like Verisign, or financial institutions. There's some control over
414+ * the certifying authorities which are sent.
415+ *
416+ * NOTE: that these messages might be huge, taking many handshake records.
417+ * Up to 2^48 bytes of certificate may be sent, in records of at most 2^14
418+ * bytes each ... up to 2^32 records sent on the output stream.
419+ */
420+static final
421+class CertificateMsg extends HandshakeMessage
422+{
423+ int messageType() { return ht_certificate; }
424+
425+ private X509Certificate[] chain;
426+
427+ private List<byte[]> encodedChain;
428+
429+ private int messageLength;
430+
431+ CertificateMsg(X509Certificate[] certs) {
432+ chain = certs;
433+ }
434+
435+ CertificateMsg(HandshakeInStream input) throws IOException {
436+ int chainLen = input.getInt24();
437+ List<Certificate> v = new ArrayList<>(4);
438+
439+ CertificateFactory cf = null;
440+ while (chainLen > 0) {
441+ byte[] cert = input.getBytes24();
442+ chainLen -= (3 + cert.length);
443+ try {
444+ if (cf == null) {
445+ cf = CertificateFactory.getInstance("X.509");
446+ }
447+ v.add(cf.generateCertificate(new ByteArrayInputStream(cert)));
448+ } catch (CertificateException e) {
449+ throw (SSLProtocolException)new SSLProtocolException(
450+ e.getMessage()).initCause(e);
451+ }
452+ }
453+
454+ chain = v.toArray(new X509Certificate[v.size()]);
455+ }
456+
457+ int messageLength() {
458+ if (encodedChain == null) {
459+ messageLength = 3;
460+ encodedChain = new ArrayList<byte[]>(chain.length);
461+ try {
462+ for (X509Certificate cert : chain) {
463+ byte[] b = cert.getEncoded();
464+ encodedChain.add(b);
465+ messageLength += b.length + 3;
466+ }
467+ } catch (CertificateEncodingException e) {
468+ encodedChain = null;
469+ throw new RuntimeException("Could not encode certificates", e);
470+ }
471+ }
472+ return messageLength;
473+ }
474+
475+ void send(HandshakeOutStream s) throws IOException {
476+ s.putInt24(messageLength() - 3);
477+ for (byte[] b : encodedChain) {
478+ s.putBytes24(b);
479+ }
480+ }
481+
482+ void print(PrintStream s) throws IOException {
483+ s.println("*** Certificate chain");
484+
485+ if (debug != null && Debug.isOn("verbose")) {
486+ for (int i = 0; i < chain.length; i++)
487+ s.println("chain [" + i + "] = " + chain[i]);
488+ s.println("***");
489+ }
490+ }
491+
492+ X509Certificate[] getCertificateChain() {
493+ return chain.clone();
494+ }
495+}
496+
497+/*
498+ * ServerKeyExchange ... SERVER --> CLIENT
499+ *
500+ * The cipher suite selected, when combined with the certificate exchanged,
501+ * implies one of several different kinds of key exchange. Most current
502+ * cipher suites require the server to send more than its certificate.
503+ *
504+ * The primary exceptions are when a server sends an encryption-capable
505+ * RSA public key in its cert, to be used with RSA (or RSA_export) key
506+ * exchange; and when a server sends its Diffie-Hellman cert. Those kinds
507+ * of key exchange do not require a ServerKeyExchange message.
508+ *
509+ * Key exchange can be viewed as having three modes, which are explicit
510+ * for the Diffie-Hellman flavors and poorly specified for RSA ones:
511+ *
512+ * - "Ephemeral" keys. Here, a "temporary" key is allocated by the
513+ * server, and signed. Diffie-Hellman keys signed using RSA or
514+ * DSS are ephemeral (DHE flavor). RSA keys get used to do the same
515+ * thing, to cut the key size down to 512 bits (export restrictions)
516+ * or for signing-only RSA certificates.
517+ *
518+ * - Anonymity. Here no server certificate is sent, only the public
519+ * key of the server. This case is subject to man-in-the-middle
520+ * attacks. This can be done with Diffie-Hellman keys (DH_anon) or
521+ * with RSA keys, but is only used in SSLv3 for DH_anon.
522+ *
523+ * - "Normal" case. Here a server certificate is sent, and the public
524+ * key there is used directly in exchanging the premaster secret.
525+ * For example, Diffie-Hellman "DH" flavor, and any RSA flavor with
526+ * only 512 bit keys.
527+ *
528+ * If a server certificate is sent, there is no anonymity. However,
529+ * when a certificate is sent, ephemeral keys may still be used to
530+ * exchange the premaster secret. That's how RSA_EXPORT often works,
531+ * as well as how the DHE_* flavors work.
532+ */
533+static abstract class ServerKeyExchange extends HandshakeMessage
534+{
535+ int messageType() { return ht_server_key_exchange; }
536+}
537+
538+
539+/*
540+ * Using RSA for Key Exchange: exchange a session key that's not as big
541+ * as the signing-only key. Used for export applications, since exported
542+ * RSA encryption keys can't be bigger than 512 bytes.
543+ *
544+ * This is never used when keys are 512 bits or smaller, and isn't used
545+ * on "US Domestic" ciphers in any case.
546+ */
547+static final
548+class RSA_ServerKeyExchange extends ServerKeyExchange
549+{
550+ private byte rsa_modulus[]; // 1 to 2^16 - 1 bytes
551+ private byte rsa_exponent[]; // 1 to 2^16 - 1 bytes
552+
553+ private Signature signature;
554+ private byte[] signatureBytes;
555+
556+ /*
557+ * Hash the nonces and the ephemeral RSA public key.
558+ */
559+ private void updateSignature(byte clntNonce[], byte svrNonce[])
560+ throws SignatureException {
561+ int tmp;
562+
563+ signature.update(clntNonce);
564+ signature.update(svrNonce);
565+
566+ tmp = rsa_modulus.length;
567+ signature.update((byte)(tmp >> 8));
568+ signature.update((byte)(tmp & 0x0ff));
569+ signature.update(rsa_modulus);
570+
571+ tmp = rsa_exponent.length;
572+ signature.update((byte)(tmp >> 8));
573+ signature.update((byte)(tmp & 0x0ff));
574+ signature.update(rsa_exponent);
575+ }
576+
577+
578+ /*
579+ * Construct an RSA server key exchange message, using data
580+ * known _only_ to the server.
581+ *
582+ * The client knows the public key corresponding to this private
583+ * key, from the Certificate message sent previously. To comply
584+ * with US export regulations we use short RSA keys ... either
585+ * long term ones in the server's X509 cert, or else ephemeral
586+ * ones sent using this message.
587+ */
588+ RSA_ServerKeyExchange(PublicKey ephemeralKey, PrivateKey privateKey,
589+ RandomCookie clntNonce, RandomCookie svrNonce, SecureRandom sr)
590+ throws GeneralSecurityException {
591+ RSAPublicKeySpec rsaKey = JsseJce.getRSAPublicKeySpec(ephemeralKey);
592+ rsa_modulus = toByteArray(rsaKey.getModulus());
593+ rsa_exponent = toByteArray(rsaKey.getPublicExponent());
594+ signature = RSASignature.getInstance();
595+ signature.initSign(privateKey, sr);
596+ updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
597+ signatureBytes = signature.sign();
598+ }
599+
600+
601+ /*
602+ * Parse an RSA server key exchange message, using data known
603+ * to the client (and, in some situations, eavesdroppers).
604+ */
605+ RSA_ServerKeyExchange(HandshakeInStream input)
606+ throws IOException, NoSuchAlgorithmException {
607+ signature = RSASignature.getInstance();
608+ rsa_modulus = input.getBytes16();
609+ rsa_exponent = input.getBytes16();
610+ signatureBytes = input.getBytes16();
611+ }
612+
613+ /*
614+ * Get the ephemeral RSA public key that will be used in this
615+ * SSL connection.
616+ */
617+ PublicKey getPublicKey() {
618+ try {
619+ KeyFactory kfac = JsseJce.getKeyFactory("RSA");
620+ // modulus and exponent are always positive
621+ RSAPublicKeySpec kspec = new RSAPublicKeySpec(
622+ new BigInteger(1, rsa_modulus),
623+ new BigInteger(1, rsa_exponent));
624+ return kfac.generatePublic(kspec);
625+ } catch (Exception e) {
626+ throw new RuntimeException(e);
627+ }
628+ }
629+
630+ /*
631+ * Verify the signed temporary key using the hashes computed
632+ * from it and the two nonces. This is called by clients
633+ * with "exportable" RSA flavors.
634+ */
635+ boolean verify(PublicKey certifiedKey, RandomCookie clntNonce,
636+ RandomCookie svrNonce) throws GeneralSecurityException {
637+ signature.initVerify(certifiedKey);
638+ updateSignature(clntNonce.random_bytes, svrNonce.random_bytes);
639+ return signature.verify(signatureBytes);
640+ }
641+
642+ int messageLength() {
643+ return 6 + rsa_modulus.length + rsa_exponent.length
644+ + signatureBytes.length;
645+ }
646+
647+ void send(HandshakeOutStream s) throws IOException {
648+ s.putBytes16(rsa_modulus);
649+ s.putBytes16(rsa_exponent);
650+ s.putBytes16(signatureBytes);
651+ }
652+
653+ void print(PrintStream s) throws IOException {
654+ s.println("*** RSA ServerKeyExchange");
655+
656+ if (debug != null && Debug.isOn("verbose")) {
657+ Debug.println(s, "RSA Modulus", rsa_modulus);
658+ Debug.println(s, "RSA Public Exponent", rsa_exponent);
659+ }
660+ }
661+}
662+
663+
664+/*
665+ * Using Diffie-Hellman algorithm for key exchange. All we really need to
666+ * do is securely get Diffie-Hellman keys (using the same P, G parameters)
667+ * to our peer, then we automatically have a shared secret without need
668+ * to exchange any more data. (D-H only solutions, such as SKIP, could
669+ * eliminate key exchange negotiations and get faster connection setup.
670+ * But they still need a signature algorithm like DSS/DSA to support the
671+ * trusted distribution of keys without relying on unscalable physical
672+ * key distribution systems.)
673+ *
674+ * This class supports several DH-based key exchange algorithms, though
675+ * perhaps eventually each deserves its own class. Notably, this has
676+ * basic support for DH_anon and its DHE_DSS and DHE_RSA signed variants.
677+ */
678+static final
679+class DH_ServerKeyExchange extends ServerKeyExchange
680+{
681+ // Fix message encoding, see 4348279
682+ private final static boolean dhKeyExchangeFix =
683+ Debug.getBooleanProperty("com.sun.net.ssl.dhKeyExchangeFix", true);
684+
685+ private byte dh_p []; // 1 to 2^16 - 1 bytes
686+ private byte dh_g []; // 1 to 2^16 - 1 bytes
687+ private byte dh_Ys []; // 1 to 2^16 - 1 bytes
688+
689+ private byte signature [];
690+
691+ // protocol version being established using this ServerKeyExchange message
692+ ProtocolVersion protocolVersion;
693+
694+ // the preferable signature algorithm used by this ServerKeyExchange message
695+ private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
696+
697+ /*
698+ * Construct from initialized DH key object, for DH_anon
699+ * key exchange.
700+ */
701+ DH_ServerKeyExchange(DHCrypt obj, ProtocolVersion protocolVersion) {
702+ this.protocolVersion = protocolVersion;
703+ this.preferableSignatureAlgorithm = null;
704+
705+ setValues(obj);
706+ signature = null;
707+ }
708+
709+ /*
710+ * Construct from initialized DH key object and the key associated
711+ * with the cert chain which was sent ... for DHE_DSS and DHE_RSA
712+ * key exchange. (Constructor called by server.)
713+ */
714+ DH_ServerKeyExchange(DHCrypt obj, PrivateKey key, byte clntNonce[],
715+ byte svrNonce[], SecureRandom sr,
716+ SignatureAndHashAlgorithm signAlgorithm,
717+ ProtocolVersion protocolVersion) throws GeneralSecurityException {
718+
719+ this.protocolVersion = protocolVersion;
720+
721+ setValues(obj);
722+
723+ Signature sig;
724+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
725+ this.preferableSignatureAlgorithm = signAlgorithm;
726+ sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
727+ } else {
728+ this.preferableSignatureAlgorithm = null;
729+ if (key.getAlgorithm().equals("DSA")) {
730+ sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
731+ } else {
732+ sig = RSASignature.getInstance();
733+ }
734+ }
735+
736+ sig.initSign(key, sr);
737+ updateSignature(sig, clntNonce, svrNonce);
738+ signature = sig.sign();
739+ }
740+
741+ /*
742+ * Construct a DH_ServerKeyExchange message from an input
743+ * stream, as if sent from server to client for use with
744+ * DH_anon key exchange
745+ */
746+ DH_ServerKeyExchange(HandshakeInStream input,
747+ ProtocolVersion protocolVersion) throws IOException {
748+
749+ this.protocolVersion = protocolVersion;
750+ this.preferableSignatureAlgorithm = null;
751+
752+ dh_p = input.getBytes16();
753+ dh_g = input.getBytes16();
754+ dh_Ys = input.getBytes16();
755+ signature = null;
756+ }
757+
758+ /*
759+ * Construct a DH_ServerKeyExchange message from an input stream
760+ * and a certificate, as if sent from server to client for use with
761+ * DHE_DSS or DHE_RSA key exchange. (Called by client.)
762+ */
763+ DH_ServerKeyExchange(HandshakeInStream input, PublicKey publicKey,
764+ byte clntNonce[], byte svrNonce[], int messageSize,
765+ Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
766+ ProtocolVersion protocolVersion)
767+ throws IOException, GeneralSecurityException {
768+
769+ this.protocolVersion = protocolVersion;
770+
771+ // read params: ServerDHParams
772+ dh_p = input.getBytes16();
773+ dh_g = input.getBytes16();
774+ dh_Ys = input.getBytes16();
775+
776+ // read the signature and hash algorithm
777+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
778+ int hash = input.getInt8(); // hash algorithm
779+ int signature = input.getInt8(); // signature algorithm
780+
781+ preferableSignatureAlgorithm =
782+ SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
783+
784+ // Is it a local supported signature algorithm?
785+ if (!localSupportedSignAlgs.contains(
786+ preferableSignatureAlgorithm)) {
787+ throw new SSLHandshakeException(
788+ "Unsupported SignatureAndHashAlgorithm in " +
789+ "ServerKeyExchange message");
790+ }
791+ } else {
792+ this.preferableSignatureAlgorithm = null;
793+ }
794+
795+ // read the signature
796+ byte signature[];
797+ if (dhKeyExchangeFix) {
798+ signature = input.getBytes16();
799+ } else {
800+ messageSize -= (dh_p.length + 2);
801+ messageSize -= (dh_g.length + 2);
802+ messageSize -= (dh_Ys.length + 2);
803+
804+ signature = new byte[messageSize];
805+ input.read(signature);
806+ }
807+
808+ Signature sig;
809+ String algorithm = publicKey.getAlgorithm();
810+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
811+ sig = JsseJce.getSignature(
812+ preferableSignatureAlgorithm.getAlgorithmName());
813+ } else {
814+ if (algorithm.equals("DSA")) {
815+ sig = JsseJce.getSignature(JsseJce.SIGNATURE_DSA);
816+ } else if (algorithm.equals("RSA")) {
817+ sig = RSASignature.getInstance();
818+ } else {
819+ throw new SSLKeyException("neither an RSA or a DSA key");
820+ }
821+ }
822+
823+ sig.initVerify(publicKey);
824+ updateSignature(sig, clntNonce, svrNonce);
825+
826+ if (sig.verify(signature) == false ) {
827+ throw new SSLKeyException("Server D-H key verification failed");
828+ }
829+ }
830+
831+ /* Return the Diffie-Hellman modulus */
832+ BigInteger getModulus() {
833+ return new BigInteger(1, dh_p);
834+ }
835+
836+ /* Return the Diffie-Hellman base/generator */
837+ BigInteger getBase() {
838+ return new BigInteger(1, dh_g);
839+ }
840+
841+ /* Return the server's Diffie-Hellman public key */
842+ BigInteger getServerPublicKey() {
843+ return new BigInteger(1, dh_Ys);
844+ }
845+
846+ /*
847+ * Update sig with nonces and Diffie-Hellman public key.
848+ */
849+ private void updateSignature(Signature sig, byte clntNonce[],
850+ byte svrNonce[]) throws SignatureException {
851+ int tmp;
852+
853+ sig.update(clntNonce);
854+ sig.update(svrNonce);
855+
856+ tmp = dh_p.length;
857+ sig.update((byte)(tmp >> 8));
858+ sig.update((byte)(tmp & 0x0ff));
859+ sig.update(dh_p);
860+
861+ tmp = dh_g.length;
862+ sig.update((byte)(tmp >> 8));
863+ sig.update((byte)(tmp & 0x0ff));
864+ sig.update(dh_g);
865+
866+ tmp = dh_Ys.length;
867+ sig.update((byte)(tmp >> 8));
868+ sig.update((byte)(tmp & 0x0ff));
869+ sig.update(dh_Ys);
870+ }
871+
872+ private void setValues(DHCrypt obj) {
873+ dh_p = toByteArray(obj.getModulus());
874+ dh_g = toByteArray(obj.getBase());
875+ dh_Ys = toByteArray(obj.getPublicKey());
876+ }
877+
878+ int messageLength() {
879+ int temp = 6; // overhead for p, g, y(s) values.
880+
881+ temp += dh_p.length;
882+ temp += dh_g.length;
883+ temp += dh_Ys.length;
884+
885+ if (signature != null) {
886+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
887+ temp += SignatureAndHashAlgorithm.sizeInRecord();
888+ }
889+
890+ temp += signature.length;
891+ if (dhKeyExchangeFix) {
892+ temp += 2;
893+ }
894+ }
895+
896+ return temp;
897+ }
898+
899+ void send(HandshakeOutStream s) throws IOException {
900+ s.putBytes16(dh_p);
901+ s.putBytes16(dh_g);
902+ s.putBytes16(dh_Ys);
903+
904+ if (signature != null) {
905+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
906+ s.putInt8(preferableSignatureAlgorithm.getHashValue());
907+ s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
908+ }
909+
910+ if (dhKeyExchangeFix) {
911+ s.putBytes16(signature);
912+ } else {
913+ s.write(signature);
914+ }
915+ }
916+ }
917+
918+ void print(PrintStream s) throws IOException {
919+ s.println("*** Diffie-Hellman ServerKeyExchange");
920+
921+ if (debug != null && Debug.isOn("verbose")) {
922+ Debug.println(s, "DH Modulus", dh_p);
923+ Debug.println(s, "DH Base", dh_g);
924+ Debug.println(s, "Server DH Public Key", dh_Ys);
925+
926+ if (signature == null) {
927+ s.println("Anonymous");
928+ } else {
929+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
930+ s.println("Signature Algorithm " +
931+ preferableSignatureAlgorithm.getAlgorithmName());
932+ }
933+
934+ s.println("Signed with a DSA or RSA public key");
935+ }
936+ }
937+ }
938+}
939+
940+/*
941+ * ECDH server key exchange message. Sent by the server for ECDHE and ECDH_anon
942+ * ciphersuites to communicate its ephemeral public key (including the
943+ * EC domain parameters).
944+ *
945+ * We support named curves only, no explicitly encoded curves.
946+ */
947+static final
948+class ECDH_ServerKeyExchange extends ServerKeyExchange {
949+
950+ // constants for ECCurveType
951+ private final static int CURVE_EXPLICIT_PRIME = 1;
952+ private final static int CURVE_EXPLICIT_CHAR2 = 2;
953+ private final static int CURVE_NAMED_CURVE = 3;
954+
955+ // id of the curve we are using
956+ private int curveId;
957+ // encoded public point
958+ private byte[] pointBytes;
959+
960+ // signature bytes (or null if anonymous)
961+ private byte[] signatureBytes;
962+
963+ // public key object encapsulated in this message
964+ private ECPublicKey publicKey;
965+
966+ // protocol version being established using this ServerKeyExchange message
967+ ProtocolVersion protocolVersion;
968+
969+ // the preferable signature algorithm used by this ServerKeyExchange message
970+ private SignatureAndHashAlgorithm preferableSignatureAlgorithm;
971+
972+ ECDH_ServerKeyExchange(ECDHCrypt obj, PrivateKey privateKey,
973+ byte[] clntNonce, byte[] svrNonce, SecureRandom sr,
974+ SignatureAndHashAlgorithm signAlgorithm,
975+ ProtocolVersion protocolVersion) throws GeneralSecurityException {
976+
977+ this.protocolVersion = protocolVersion;
978+
979+ publicKey = (ECPublicKey)obj.getPublicKey();
980+ ECParameterSpec params = publicKey.getParams();
981+ ECPoint point = publicKey.getW();
982+ pointBytes = JsseJce.encodePoint(point, params.getCurve());
983+ curveId = SupportedEllipticCurvesExtension.getCurveIndex(params);
984+
985+ if (privateKey == null) {
986+ // ECDH_anon
987+ return;
988+ }
989+
990+ Signature sig;
991+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
992+ this.preferableSignatureAlgorithm = signAlgorithm;
993+ sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
994+ } else {
995+ sig = getSignature(privateKey.getAlgorithm());
996+ }
997+ sig.initSign(privateKey); // where is the SecureRandom?
998+
999+ updateSignature(sig, clntNonce, svrNonce);
1000+ signatureBytes = sig.sign();
1001+ }
1002+
1003+ /*
1004+ * Parse an ECDH server key exchange message.
1005+ */
1006+ ECDH_ServerKeyExchange(HandshakeInStream input, PublicKey signingKey,
1007+ byte[] clntNonce, byte[] svrNonce,
1008+ Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
1009+ ProtocolVersion protocolVersion)
1010+ throws IOException, GeneralSecurityException {
1011+
1012+ this.protocolVersion = protocolVersion;
1013+
1014+ // read params: ServerECDHParams
1015+ int curveType = input.getInt8();
1016+ ECParameterSpec parameters;
1017+ // These parsing errors should never occur as we negotiated
1018+ // the supported curves during the exchange of the Hello messages.
1019+ if (curveType == CURVE_NAMED_CURVE) {
1020+ curveId = input.getInt16();
1021+ if (SupportedEllipticCurvesExtension.isSupported(curveId)
1022+ == false) {
1023+ throw new SSLHandshakeException(
1024+ "Unsupported curveId: " + curveId);
1025+ }
1026+ String curveOid =
1027+ SupportedEllipticCurvesExtension.getCurveOid(curveId);
1028+ if (curveOid == null) {
1029+ throw new SSLHandshakeException(
1030+ "Unknown named curve: " + curveId);
1031+ }
1032+ parameters = JsseJce.getECParameterSpec(curveOid);
1033+ if (parameters == null) {
1034+ throw new SSLHandshakeException(
1035+ "Unsupported curve: " + curveOid);
1036+ }
1037+ } else {
1038+ throw new SSLHandshakeException(
1039+ "Unsupported ECCurveType: " + curveType);
1040+ }
1041+ pointBytes = input.getBytes8();
1042+
1043+ ECPoint point = JsseJce.decodePoint(pointBytes, parameters.getCurve());
1044+ KeyFactory factory = JsseJce.getKeyFactory("EC");
1045+ publicKey = (ECPublicKey)factory.generatePublic(
1046+ new ECPublicKeySpec(point, parameters));
1047+
1048+ if (signingKey == null) {
1049+ // ECDH_anon
1050+ return;
1051+ }
1052+
1053+ // read the signature and hash algorithm
1054+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1055+ int hash = input.getInt8(); // hash algorithm
1056+ int signature = input.getInt8(); // signature algorithm
1057+
1058+ preferableSignatureAlgorithm =
1059+ SignatureAndHashAlgorithm.valueOf(hash, signature, 0);
1060+
1061+ // Is it a local supported signature algorithm?
1062+ if (!localSupportedSignAlgs.contains(
1063+ preferableSignatureAlgorithm)) {
1064+ throw new SSLHandshakeException(
1065+ "Unsupported SignatureAndHashAlgorithm in " +
1066+ "ServerKeyExchange message");
1067+ }
1068+ }
1069+
1070+ // read the signature
1071+ signatureBytes = input.getBytes16();
1072+
1073+ // verify the signature
1074+ Signature sig;
1075+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1076+ sig = JsseJce.getSignature(
1077+ preferableSignatureAlgorithm.getAlgorithmName());
1078+ } else {
1079+ sig = getSignature(signingKey.getAlgorithm());
1080+ }
1081+ sig.initVerify(signingKey);
1082+
1083+ updateSignature(sig, clntNonce, svrNonce);
1084+
1085+ if (sig.verify(signatureBytes) == false ) {
1086+ throw new SSLKeyException(
1087+ "Invalid signature on ECDH server key exchange message");
1088+ }
1089+ }
1090+
1091+ /*
1092+ * Get the ephemeral EC public key encapsulated in this message.
1093+ */
1094+ ECPublicKey getPublicKey() {
1095+ return publicKey;
1096+ }
1097+
1098+ private static Signature getSignature(String keyAlgorithm)
1099+ throws NoSuchAlgorithmException {
1100+ if (keyAlgorithm.equals("EC")) {
1101+ return JsseJce.getSignature(JsseJce.SIGNATURE_ECDSA);
1102+ } else if (keyAlgorithm.equals("RSA")) {
1103+ return RSASignature.getInstance();
1104+ } else {
1105+ throw new NoSuchAlgorithmException("neither an RSA or a EC key");
1106+ }
1107+ }
1108+
1109+ private void updateSignature(Signature sig, byte clntNonce[],
1110+ byte svrNonce[]) throws SignatureException {
1111+ sig.update(clntNonce);
1112+ sig.update(svrNonce);
1113+
1114+ sig.update((byte)CURVE_NAMED_CURVE);
1115+ sig.update((byte)(curveId >> 8));
1116+ sig.update((byte)curveId);
1117+ sig.update((byte)pointBytes.length);
1118+ sig.update(pointBytes);
1119+ }
1120+
1121+ int messageLength() {
1122+ int sigLen = 0;
1123+ if (signatureBytes != null) {
1124+ sigLen = 2 + signatureBytes.length;
1125+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1126+ sigLen += SignatureAndHashAlgorithm.sizeInRecord();
1127+ }
1128+ }
1129+
1130+ return 4 + pointBytes.length + sigLen;
1131+ }
1132+
1133+ void send(HandshakeOutStream s) throws IOException {
1134+ s.putInt8(CURVE_NAMED_CURVE);
1135+ s.putInt16(curveId);
1136+ s.putBytes8(pointBytes);
1137+
1138+ if (signatureBytes != null) {
1139+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1140+ s.putInt8(preferableSignatureAlgorithm.getHashValue());
1141+ s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
1142+ }
1143+
1144+ s.putBytes16(signatureBytes);
1145+ }
1146+ }
1147+
1148+ void print(PrintStream s) throws IOException {
1149+ s.println("*** ECDH ServerKeyExchange");
1150+
1151+ if (debug != null && Debug.isOn("verbose")) {
1152+ if (signatureBytes == null) {
1153+ s.println("Anonymous");
1154+ } else {
1155+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1156+ s.println("Signature Algorithm " +
1157+ preferableSignatureAlgorithm.getAlgorithmName());
1158+ }
1159+ }
1160+
1161+ s.println("Server key: " + publicKey);
1162+ }
1163+ }
1164+}
1165+
1166+static final class DistinguishedName {
1167+
1168+ /*
1169+ * DER encoded distinguished name.
1170+ * TLS requires that its not longer than 65535 bytes.
1171+ */
1172+ byte name[];
1173+
1174+ DistinguishedName(HandshakeInStream input) throws IOException {
1175+ name = input.getBytes16();
1176+ }
1177+
1178+ DistinguishedName(X500Principal dn) {
1179+ name = dn.getEncoded();
1180+ }
1181+
1182+ X500Principal getX500Principal() throws IOException {
1183+ try {
1184+ return new X500Principal(name);
1185+ } catch (IllegalArgumentException e) {
1186+ throw (SSLProtocolException)new SSLProtocolException(
1187+ e.getMessage()).initCause(e);
1188+ }
1189+ }
1190+
1191+ int length() {
1192+ return 2 + name.length;
1193+ }
1194+
1195+ void send(HandshakeOutStream output) throws IOException {
1196+ output.putBytes16(name);
1197+ }
1198+
1199+ void print(PrintStream output) throws IOException {
1200+ X500Principal principal = new X500Principal(name);
1201+ output.println("<" + principal.toString() + ">");
1202+ }
1203+}
1204+
1205+/*
1206+ * CertificateRequest ... SERVER --> CLIENT
1207+ *
1208+ * Authenticated servers may ask clients to authenticate themselves
1209+ * in turn, using this message.
1210+ *
1211+ * Prior to TLS 1.2, the structure of the message is defined as:
1212+ * struct {
1213+ * ClientCertificateType certificate_types<1..2^8-1>;
1214+ * DistinguishedName certificate_authorities<0..2^16-1>;
1215+ * } CertificateRequest;
1216+ *
1217+ * In TLS 1.2, the structure is changed to:
1218+ * struct {
1219+ * ClientCertificateType certificate_types<1..2^8-1>;
1220+ * SignatureAndHashAlgorithm
1221+ * supported_signature_algorithms<2^16-1>;
1222+ * DistinguishedName certificate_authorities<0..2^16-1>;
1223+ * } CertificateRequest;
1224+ *
1225+ */
1226+static final
1227+class CertificateRequest extends HandshakeMessage
1228+{
1229+ // enum ClientCertificateType
1230+ static final int cct_rsa_sign = 1;
1231+ static final int cct_dss_sign = 2;
1232+ static final int cct_rsa_fixed_dh = 3;
1233+ static final int cct_dss_fixed_dh = 4;
1234+
1235+ // The existance of these two values is a bug in the SSL specification.
1236+ // They are never used in the protocol.
1237+ static final int cct_rsa_ephemeral_dh = 5;
1238+ static final int cct_dss_ephemeral_dh = 6;
1239+
1240+ // From RFC 4492 (ECC)
1241+ static final int cct_ecdsa_sign = 64;
1242+ static final int cct_rsa_fixed_ecdh = 65;
1243+ static final int cct_ecdsa_fixed_ecdh = 66;
1244+
1245+ private final static byte[] TYPES_NO_ECC = { cct_rsa_sign, cct_dss_sign };
1246+ private final static byte[] TYPES_ECC =
1247+ { cct_rsa_sign, cct_dss_sign, cct_ecdsa_sign };
1248+
1249+ byte types []; // 1 to 255 types
1250+ DistinguishedName authorities []; // 3 to 2^16 - 1
1251+ // ... "3" because that's the smallest DER-encoded X500 DN
1252+
1253+ // protocol version being established using this CertificateRequest message
1254+ ProtocolVersion protocolVersion;
1255+
1256+ // supported_signature_algorithms for TLS 1.2 or later
1257+ private Collection<SignatureAndHashAlgorithm> algorithms;
1258+
1259+ // length of supported_signature_algorithms
1260+ private int algorithmsLen;
1261+
1262+ CertificateRequest(X509Certificate ca[], KeyExchange keyExchange,
1263+ Collection<SignatureAndHashAlgorithm> signAlgs,
1264+ ProtocolVersion protocolVersion) throws IOException {
1265+
1266+ this.protocolVersion = protocolVersion;
1267+
1268+ // always use X500Principal
1269+ authorities = new DistinguishedName[ca.length];
1270+ for (int i = 0; i < ca.length; i++) {
1271+ X500Principal x500Principal = ca[i].getSubjectX500Principal();
1272+ authorities[i] = new DistinguishedName(x500Principal);
1273+ }
1274+ // we support RSA, DSS, and ECDSA client authentication and they
1275+ // can be used with all ciphersuites. If this changes, the code
1276+ // needs to be adapted to take keyExchange into account.
1277+ // We only request ECDSA client auth if we have ECC crypto available.
1278+ this.types = JsseJce.isEcAvailable() ? TYPES_ECC : TYPES_NO_ECC;
1279+
1280+ // Use supported_signature_algorithms for TLS 1.2 or later.
1281+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1282+ if (signAlgs == null || signAlgs.isEmpty()) {
1283+ throw new SSLProtocolException(
1284+ "No supported signature algorithms");
1285+ }
1286+
1287+ algorithms = new ArrayList<SignatureAndHashAlgorithm>(signAlgs);
1288+ algorithmsLen =
1289+ SignatureAndHashAlgorithm.sizeInRecord() * algorithms.size();
1290+ } else {
1291+ algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1292+ algorithmsLen = 0;
1293+ }
1294+ }
1295+
1296+ CertificateRequest(HandshakeInStream input,
1297+ ProtocolVersion protocolVersion) throws IOException {
1298+
1299+ this.protocolVersion = protocolVersion;
1300+
1301+ // Read the certificate_types.
1302+ types = input.getBytes8();
1303+
1304+ // Read the supported_signature_algorithms for TLS 1.2 or later.
1305+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1306+ algorithmsLen = input.getInt16();
1307+ if (algorithmsLen < 2) {
1308+ throw new SSLProtocolException(
1309+ "Invalid supported_signature_algorithms field");
1310+ }
1311+
1312+ algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1313+ int remains = algorithmsLen;
1314+ int sequence = 0;
1315+ while (remains > 1) { // needs at least two bytes
1316+ int hash = input.getInt8(); // hash algorithm
1317+ int signature = input.getInt8(); // signature algorithm
1318+
1319+ SignatureAndHashAlgorithm algorithm =
1320+ SignatureAndHashAlgorithm.valueOf(hash, signature,
1321+ ++sequence);
1322+ algorithms.add(algorithm);
1323+ remains -= 2; // one byte for hash, one byte for signature
1324+ }
1325+
1326+ if (remains != 0) {
1327+ throw new SSLProtocolException(
1328+ "Invalid supported_signature_algorithms field");
1329+ }
1330+ } else {
1331+ algorithms = new ArrayList<SignatureAndHashAlgorithm>();
1332+ algorithmsLen = 0;
1333+ }
1334+
1335+ // read the certificate_authorities
1336+ int len = input.getInt16();
1337+ ArrayList<DistinguishedName> v = new ArrayList<>();
1338+ while (len >= 3) {
1339+ DistinguishedName dn = new DistinguishedName(input);
1340+ v.add(dn);
1341+ len -= dn.length();
1342+ }
1343+
1344+ if (len != 0) {
1345+ throw new SSLProtocolException("Bad CertificateRequest DN length");
1346+ }
1347+
1348+ authorities = v.toArray(new DistinguishedName[v.size()]);
1349+ }
1350+
1351+ X500Principal[] getAuthorities() throws IOException {
1352+ X500Principal[] ret = new X500Principal[authorities.length];
1353+ for (int i = 0; i < authorities.length; i++) {
1354+ ret[i] = authorities[i].getX500Principal();
1355+ }
1356+ return ret;
1357+ }
1358+
1359+ Collection<SignatureAndHashAlgorithm> getSignAlgorithms() {
1360+ return algorithms;
1361+ }
1362+
1363+ @Override
1364+ int messageType() {
1365+ return ht_certificate_request;
1366+ }
1367+
1368+ @Override
1369+ int messageLength() {
1370+ int len = 1 + types.length + 2;
1371+
1372+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1373+ len += algorithmsLen + 2;
1374+ }
1375+
1376+ for (int i = 0; i < authorities.length; i++) {
1377+ len += authorities[i].length();
1378+ }
1379+
1380+ return len;
1381+ }
1382+
1383+ @Override
1384+ void send(HandshakeOutStream output) throws IOException {
1385+ // put certificate_types
1386+ output.putBytes8(types);
1387+
1388+ // put supported_signature_algorithms
1389+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1390+ output.putInt16(algorithmsLen);
1391+ for (SignatureAndHashAlgorithm algorithm : algorithms) {
1392+ output.putInt8(algorithm.getHashValue()); // hash
1393+ output.putInt8(algorithm.getSignatureValue()); // signature
1394+ }
1395+ }
1396+
1397+ // put certificate_authorities
1398+ int len = 0;
1399+ for (int i = 0; i < authorities.length; i++) {
1400+ len += authorities[i].length();
1401+ }
1402+
1403+ output.putInt16(len);
1404+ for (int i = 0; i < authorities.length; i++) {
1405+ authorities[i].send(output);
1406+ }
1407+ }
1408+
1409+ @Override
1410+ void print(PrintStream s) throws IOException {
1411+ s.println("*** CertificateRequest");
1412+
1413+ if (debug != null && Debug.isOn("verbose")) {
1414+ s.print("Cert Types: ");
1415+ for (int i = 0; i < types.length; i++) {
1416+ switch (types[i]) {
1417+ case cct_rsa_sign:
1418+ s.print("RSA"); break;
1419+ case cct_dss_sign:
1420+ s.print("DSS"); break;
1421+ case cct_rsa_fixed_dh:
1422+ s.print("Fixed DH (RSA sig)"); break;
1423+ case cct_dss_fixed_dh:
1424+ s.print("Fixed DH (DSS sig)"); break;
1425+ case cct_rsa_ephemeral_dh:
1426+ s.print("Ephemeral DH (RSA sig)"); break;
1427+ case cct_dss_ephemeral_dh:
1428+ s.print("Ephemeral DH (DSS sig)"); break;
1429+ case cct_ecdsa_sign:
1430+ s.print("ECDSA"); break;
1431+ case cct_rsa_fixed_ecdh:
1432+ s.print("Fixed ECDH (RSA sig)"); break;
1433+ case cct_ecdsa_fixed_ecdh:
1434+ s.print("Fixed ECDH (ECDSA sig)"); break;
1435+ default:
1436+ s.print("Type-" + (types[i] & 0xff)); break;
1437+ }
1438+ if (i != types.length - 1) {
1439+ s.print(", ");
1440+ }
1441+ }
1442+ s.println();
1443+
1444+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1445+ StringBuffer buffer = new StringBuffer();
1446+ boolean opened = false;
1447+ for (SignatureAndHashAlgorithm signAlg : algorithms) {
1448+ if (opened) {
1449+ buffer.append(", " + signAlg.getAlgorithmName());
1450+ } else {
1451+ buffer.append(signAlg.getAlgorithmName());
1452+ opened = true;
1453+ }
1454+ }
1455+ s.println("Supported Signature Algorithms: " + buffer);
1456+ }
1457+
1458+ s.println("Cert Authorities:");
1459+ if (authorities.length == 0) {
1460+ s.println("<Empty>");
1461+ } else {
1462+ for (int i = 0; i < authorities.length; i++) {
1463+ authorities[i].print(s);
1464+ }
1465+ }
1466+ }
1467+ }
1468+}
1469+
1470+
1471+/*
1472+ * ServerHelloDone ... SERVER --> CLIENT
1473+ *
1474+ * When server's done sending its messages in response to the client's
1475+ * "hello" (e.g. its own hello, certificate, key exchange message, perhaps
1476+ * client certificate request) it sends this message to flag that it's
1477+ * done that part of the handshake.
1478+ */
1479+static final
1480+class ServerHelloDone extends HandshakeMessage
1481+{
1482+ int messageType() { return ht_server_hello_done; }
1483+
1484+ ServerHelloDone() { }
1485+
1486+ ServerHelloDone(HandshakeInStream input)
1487+ {
1488+ // nothing to do
1489+ }
1490+
1491+ int messageLength()
1492+ {
1493+ return 0;
1494+ }
1495+
1496+ void send(HandshakeOutStream s) throws IOException
1497+ {
1498+ // nothing to send
1499+ }
1500+
1501+ void print(PrintStream s) throws IOException
1502+ {
1503+ s.println("*** ServerHelloDone");
1504+ }
1505+}
1506+
1507+
1508+/*
1509+ * CertificateVerify ... CLIENT --> SERVER
1510+ *
1511+ * Sent after client sends signature-capable certificates (e.g. not
1512+ * Diffie-Hellman) to verify.
1513+ */
1514+static final class CertificateVerify extends HandshakeMessage {
1515+
1516+ // the signature bytes
1517+ private byte[] signature;
1518+
1519+ // protocol version being established using this ServerKeyExchange message
1520+ ProtocolVersion protocolVersion;
1521+
1522+ // the preferable signature algorithm used by this CertificateVerify message
1523+ private SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
1524+
1525+ /*
1526+ * Create an RSA or DSA signed certificate verify message.
1527+ */
1528+ CertificateVerify(ProtocolVersion protocolVersion,
1529+ HandshakeHash handshakeHash, PrivateKey privateKey,
1530+ SecretKey masterSecret, SecureRandom sr,
1531+ SignatureAndHashAlgorithm signAlgorithm)
1532+ throws GeneralSecurityException {
1533+
1534+ this.protocolVersion = protocolVersion;
1535+
1536+ String algorithm = privateKey.getAlgorithm();
1537+ Signature sig = null;
1538+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1539+ this.preferableSignatureAlgorithm = signAlgorithm;
1540+ sig = JsseJce.getSignature(signAlgorithm.getAlgorithmName());
1541+ } else {
1542+ sig = getSignature(protocolVersion, algorithm);
1543+ }
1544+ sig.initSign(privateKey, sr);
1545+ updateSignature(sig, protocolVersion, handshakeHash, algorithm,
1546+ masterSecret);
1547+ signature = sig.sign();
1548+ }
1549+
1550+ //
1551+ // Unmarshal the signed data from the input stream.
1552+ //
1553+ CertificateVerify(HandshakeInStream input,
1554+ Collection<SignatureAndHashAlgorithm> localSupportedSignAlgs,
1555+ ProtocolVersion protocolVersion) throws IOException {
1556+
1557+ this.protocolVersion = protocolVersion;
1558+
1559+ // read the signature and hash algorithm
1560+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1561+ int hashAlg = input.getInt8(); // hash algorithm
1562+ int signAlg = input.getInt8(); // signature algorithm
1563+
1564+ preferableSignatureAlgorithm =
1565+ SignatureAndHashAlgorithm.valueOf(hashAlg, signAlg, 0);
1566+
1567+ // Is it a local supported signature algorithm?
1568+ if (!localSupportedSignAlgs.contains(
1569+ preferableSignatureAlgorithm)) {
1570+ throw new SSLHandshakeException(
1571+ "Unsupported SignatureAndHashAlgorithm in " +
1572+ "ServerKeyExchange message");
1573+ }
1574+ }
1575+
1576+ // read the signature
1577+ signature = input.getBytes16();
1578+ }
1579+
1580+ /*
1581+ * Get the preferable signature algorithm used by this message
1582+ */
1583+ SignatureAndHashAlgorithm getPreferableSignatureAlgorithm() {
1584+ return preferableSignatureAlgorithm;
1585+ }
1586+
1587+ /*
1588+ * Verify a certificate verify message. Return the result of verification,
1589+ * if there is a problem throw a GeneralSecurityException.
1590+ */
1591+ boolean verify(ProtocolVersion protocolVersion,
1592+ HandshakeHash handshakeHash, PublicKey publicKey,
1593+ SecretKey masterSecret) throws GeneralSecurityException {
1594+ String algorithm = publicKey.getAlgorithm();
1595+ Signature sig = null;
1596+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1597+ sig = JsseJce.getSignature(
1598+ preferableSignatureAlgorithm.getAlgorithmName());
1599+ } else {
1600+ sig = getSignature(protocolVersion, algorithm);
1601+ }
1602+ sig.initVerify(publicKey);
1603+ updateSignature(sig, protocolVersion, handshakeHash, algorithm,
1604+ masterSecret);
1605+ return sig.verify(signature);
1606+ }
1607+
1608+ /*
1609+ * Get the Signature object appropriate for verification using the
1610+ * given signature algorithm and protocol version.
1611+ */
1612+ private static Signature getSignature(ProtocolVersion protocolVersion,
1613+ String algorithm) throws GeneralSecurityException {
1614+ if (algorithm.equals("RSA")) {
1615+ return RSASignature.getInternalInstance();
1616+ } else if (algorithm.equals("DSA")) {
1617+ return JsseJce.getSignature(JsseJce.SIGNATURE_RAWDSA);
1618+ } else if (algorithm.equals("EC")) {
1619+ return JsseJce.getSignature(JsseJce.SIGNATURE_RAWECDSA);
1620+ } else {
1621+ throw new SignatureException("Unrecognized algorithm: "
1622+ + algorithm);
1623+ }
1624+ }
1625+
1626+ /*
1627+ * Update the Signature with the data appropriate for the given
1628+ * signature algorithm and protocol version so that the object is
1629+ * ready for signing or verifying.
1630+ */
1631+ private static void updateSignature(Signature sig,
1632+ ProtocolVersion protocolVersion,
1633+ HandshakeHash handshakeHash, String algorithm, SecretKey masterKey)
1634+ throws SignatureException {
1635+
1636+ if (algorithm.equals("RSA")) {
1637+ if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
1638+ MessageDigest md5Clone = handshakeHash.getMD5Clone();
1639+ MessageDigest shaClone = handshakeHash.getSHAClone();
1640+
1641+ if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
1642+ updateDigest(md5Clone, MD5_pad1, MD5_pad2, masterKey);
1643+ updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
1644+ }
1645+
1646+ // The signature must be an instance of RSASignature, need
1647+ // to use these hashes directly.
1648+ RSASignature.setHashes(sig, md5Clone, shaClone);
1649+ } else { // TLS1.2+
1650+ sig.update(handshakeHash.getAllHandshakeMessages());
1651+ }
1652+ } else { // DSA, ECDSA
1653+ if (protocolVersion.v < ProtocolVersion.TLS12.v) { // TLS1.1-
1654+ MessageDigest shaClone = handshakeHash.getSHAClone();
1655+
1656+ if (protocolVersion.v < ProtocolVersion.TLS10.v) { // SSLv3
1657+ updateDigest(shaClone, SHA_pad1, SHA_pad2, masterKey);
1658+ }
1659+
1660+ sig.update(shaClone.digest());
1661+ } else { // TLS1.2+
1662+ sig.update(handshakeHash.getAllHandshakeMessages());
1663+ }
1664+ }
1665+ }
1666+
1667+ /*
1668+ * Update the MessageDigest for SSLv3 certificate verify or finished
1669+ * message calculation. The digest must already have been updated with
1670+ * all preceding handshake messages.
1671+ * Used by the Finished class as well.
1672+ */
1673+ private static void updateDigest(MessageDigest md,
1674+ byte[] pad1, byte[] pad2,
1675+ SecretKey masterSecret) {
1676+ // Digest the key bytes if available.
1677+ // Otherwise (sensitive key), try digesting the key directly.
1678+ // That is currently only implemented in SunPKCS11 using a private
1679+ // reflection API, so we avoid that if possible.
1680+ byte[] keyBytes = "RAW".equals(masterSecret.getFormat())
1681+ ? masterSecret.getEncoded() : null;
1682+ if (keyBytes != null) {
1683+ md.update(keyBytes);
1684+ } else {
1685+ digestKey(md, masterSecret);
1686+ }
1687+ md.update(pad1);
1688+ byte[] temp = md.digest();
1689+
1690+ if (keyBytes != null) {
1691+ md.update(keyBytes);
1692+ } else {
1693+ digestKey(md, masterSecret);
1694+ }
1695+ md.update(pad2);
1696+ md.update(temp);
1697+ }
1698+
1699+ private final static Class delegate;
1700+ private final static Field spiField;
1701+
1702+ static {
1703+ try {
1704+ delegate = Class.forName("java.security.MessageDigest$Delegate");
1705+ spiField = delegate.getDeclaredField("digestSpi");
1706+ } catch (Exception e) {
1707+ throw new RuntimeException("Reflection failed", e);
1708+ }
1709+ makeAccessible(spiField);
1710+ }
1711+
1712+ private static void makeAccessible(final AccessibleObject o) {
1713+ AccessController.doPrivileged(new PrivilegedAction<Object>() {
1714+ public Object run() {
1715+ o.setAccessible(true);
1716+ return null;
1717+ }
1718+ });
1719+ }
1720+
1721+ // ConcurrentHashMap does not allow null values, use this marker object
1722+ private final static Object NULL_OBJECT = new Object();
1723+
1724+ // cache Method objects per Spi class
1725+ // Note that this will prevent the Spi classes from being GC'd. We assume
1726+ // that is not a problem.
1727+ private final static Map<Class,Object> methodCache =
1728+ new ConcurrentHashMap<>();
1729+
1730+ private static void digestKey(MessageDigest md, SecretKey key) {
1731+ try {
1732+ // Verify that md is implemented via MessageDigestSpi, not
1733+ // via JDK 1.1 style MessageDigest subclassing.
1734+ if (md.getClass() != delegate) {
1735+ throw new Exception("Digest is not a MessageDigestSpi");
1736+ }
1737+ MessageDigestSpi spi = (MessageDigestSpi)spiField.get(md);
1738+ Class<?> clazz = spi.getClass();
1739+ Object r = methodCache.get(clazz);
1740+ if (r == null) {
1741+ try {
1742+ r = clazz.getDeclaredMethod("implUpdate", SecretKey.class);
1743+ makeAccessible((Method)r);
1744+ } catch (NoSuchMethodException e) {
1745+ r = NULL_OBJECT;
1746+ }
1747+ methodCache.put(clazz, r);
1748+ }
1749+ if (r == NULL_OBJECT) {
1750+ throw new Exception(
1751+ "Digest does not support implUpdate(SecretKey)");
1752+ }
1753+ Method update = (Method)r;
1754+ update.invoke(spi, key);
1755+ } catch (Exception e) {
1756+ throw new RuntimeException(
1757+ "Could not obtain encoded key and "
1758+ + "MessageDigest cannot digest key", e);
1759+ }
1760+ }
1761+
1762+ @Override
1763+ int messageType() {
1764+ return ht_certificate_verify;
1765+ }
1766+
1767+ @Override
1768+ int messageLength() {
1769+ int temp = 2;
1770+
1771+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1772+ temp += SignatureAndHashAlgorithm.sizeInRecord();
1773+ }
1774+
1775+ return temp + signature.length;
1776+ }
1777+
1778+ @Override
1779+ void send(HandshakeOutStream s) throws IOException {
1780+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1781+ s.putInt8(preferableSignatureAlgorithm.getHashValue());
1782+ s.putInt8(preferableSignatureAlgorithm.getSignatureValue());
1783+ }
1784+
1785+ s.putBytes16(signature);
1786+ }
1787+
1788+ @Override
1789+ void print(PrintStream s) throws IOException {
1790+ s.println("*** CertificateVerify");
1791+
1792+ if (debug != null && Debug.isOn("verbose")) {
1793+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1794+ s.println("Signature Algorithm " +
1795+ preferableSignatureAlgorithm.getAlgorithmName());
1796+ }
1797+ }
1798+ }
1799+}
1800+
1801+
1802+/*
1803+ * FINISHED ... sent by both CLIENT and SERVER
1804+ *
1805+ * This is the FINISHED message as defined in the SSL and TLS protocols.
1806+ * Both protocols define this handshake message slightly differently.
1807+ * This class supports both formats.
1808+ *
1809+ * When handshaking is finished, each side sends a "change_cipher_spec"
1810+ * record, then immediately sends a "finished" handshake message prepared
1811+ * according to the newly adopted cipher spec.
1812+ *
1813+ * NOTE that until this is sent, no application data may be passed, unless
1814+ * some non-default cipher suite has already been set up on this connection
1815+ * connection (e.g. a previous handshake arranged one).
1816+ */
1817+static final class Finished extends HandshakeMessage {
1818+
1819+ // constant for a Finished message sent by the client
1820+ final static int CLIENT = 1;
1821+
1822+ // constant for a Finished message sent by the server
1823+ final static int SERVER = 2;
1824+
1825+ // enum Sender: "CLNT" and "SRVR"
1826+ private static final byte[] SSL_CLIENT = { 0x43, 0x4C, 0x4E, 0x54 };
1827+ private static final byte[] SSL_SERVER = { 0x53, 0x52, 0x56, 0x52 };
1828+
1829+ /*
1830+ * Contents of the finished message ("checksum"). For TLS, it
1831+ * is 12 bytes long, for SSLv3 36 bytes.
1832+ */
1833+ private byte[] verifyData;
1834+
1835+ /*
1836+ * Current cipher suite we are negotiating. TLS 1.2 has
1837+ * ciphersuite-defined PRF algorithms.
1838+ */
1839+ private ProtocolVersion protocolVersion;
1840+ private CipherSuite cipherSuite;
1841+
1842+ /*
1843+ * Create a finished message to send to the remote peer.
1844+ */
1845+ Finished(ProtocolVersion protocolVersion, HandshakeHash handshakeHash,
1846+ int sender, SecretKey master, CipherSuite cipherSuite) {
1847+ this.protocolVersion = protocolVersion;
1848+ this.cipherSuite = cipherSuite;
1849+ verifyData = getFinished(handshakeHash, sender, master);
1850+ }
1851+
1852+ /*
1853+ * Constructor that reads FINISHED message from stream.
1854+ */
1855+ Finished(ProtocolVersion protocolVersion, HandshakeInStream input,
1856+ CipherSuite cipherSuite) throws IOException {
1857+ this.protocolVersion = protocolVersion;
1858+ this.cipherSuite = cipherSuite;
1859+ int msgLen = (protocolVersion.v >= ProtocolVersion.TLS10.v) ? 12 : 36;
1860+ verifyData = new byte[msgLen];
1861+ input.read(verifyData);
1862+ }
1863+
1864+ /*
1865+ * Verify that the hashes here are what would have been produced
1866+ * according to a given set of inputs. This is used to ensure that
1867+ * both client and server are fully in sync, and that the handshake
1868+ * computations have been successful.
1869+ */
1870+ boolean verify(HandshakeHash handshakeHash, int sender, SecretKey master) {
1871+ byte[] myFinished = getFinished(handshakeHash, sender, master);
1872+ return Arrays.equals(myFinished, verifyData);
1873+ }
1874+
1875+ /*
1876+ * Perform the actual finished message calculation.
1877+ */
1878+ private byte[] getFinished(HandshakeHash handshakeHash,
1879+ int sender, SecretKey masterKey) {
1880+ byte[] sslLabel;
1881+ String tlsLabel;
1882+ if (sender == CLIENT) {
1883+ sslLabel = SSL_CLIENT;
1884+ tlsLabel = "client finished";
1885+ } else if (sender == SERVER) {
1886+ sslLabel = SSL_SERVER;
1887+ tlsLabel = "server finished";
1888+ } else {
1889+ throw new RuntimeException("Invalid sender: " + sender);
1890+ }
1891+
1892+ if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
1893+ // TLS 1.0+
1894+ try {
1895+ byte [] seed;
1896+ String prfAlg;
1897+ PRF prf;
1898+
1899+ // Get the KeyGenerator alg and calculate the seed.
1900+ if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1901+ // TLS 1.2
1902+ seed = handshakeHash.getFinishedHash();
1903+
1904+ prfAlg = "SunTls12Prf";
1905+ prf = cipherSuite.prfAlg;
1906+ } else {
1907+ // TLS 1.0/1.1
1908+ MessageDigest md5Clone = handshakeHash.getMD5Clone();
1909+ MessageDigest shaClone = handshakeHash.getSHAClone();
1910+ seed = new byte[36];
1911+ md5Clone.digest(seed, 0, 16);
1912+ shaClone.digest(seed, 16, 20);
1913+
1914+ prfAlg = "SunTlsPrf";
1915+ prf = P_NONE;
1916+ }
1917+
1918+ String prfHashAlg = prf.getPRFHashAlg();
1919+ int prfHashLength = prf.getPRFHashLength();
1920+ int prfBlockSize = prf.getPRFBlockSize();
1921+
1922+ /*
1923+ * RFC 5246/7.4.9 says that finished messages can
1924+ * be ciphersuite-specific in both length/PRF hash
1925+ * algorithm. If we ever run across a different
1926+ * length, this call will need to be updated.
1927+ */
1928+ TlsPrfParameterSpec spec = new TlsPrfParameterSpec(
1929+ masterKey, tlsLabel, seed, 12,
1930+ prfHashAlg, prfHashLength, prfBlockSize);
1931+
1932+ KeyGenerator kg = JsseJce.getKeyGenerator(prfAlg);
1933+ kg.init(spec);
1934+ SecretKey prfKey = kg.generateKey();
1935+ if ("RAW".equals(prfKey.getFormat()) == false) {
1936+ throw new ProviderException(
1937+ "Invalid PRF output, format must be RAW");
1938+ }
1939+ byte[] finished = prfKey.getEncoded();
1940+ return finished;
1941+ } catch (GeneralSecurityException e) {
1942+ throw new RuntimeException("PRF failed", e);
1943+ }
1944+ } else {
1945+ // SSLv3
1946+ MessageDigest md5Clone = handshakeHash.getMD5Clone();
1947+ MessageDigest shaClone = handshakeHash.getSHAClone();
1948+ updateDigest(md5Clone, sslLabel, MD5_pad1, MD5_pad2, masterKey);
1949+ updateDigest(shaClone, sslLabel, SHA_pad1, SHA_pad2, masterKey);
1950+ byte[] finished = new byte[36];
1951+ try {
1952+ md5Clone.digest(finished, 0, 16);
1953+ shaClone.digest(finished, 16, 20);
1954+ } catch (DigestException e) {
1955+ // cannot occur
1956+ throw new RuntimeException("Digest failed", e);
1957+ }
1958+ return finished;
1959+ }
1960+ }
1961+
1962+ /*
1963+ * Update the MessageDigest for SSLv3 finished message calculation.
1964+ * The digest must already have been updated with all preceding handshake
1965+ * messages. This operation is almost identical to the certificate verify
1966+ * hash, reuse that code.
1967+ */
1968+ private static void updateDigest(MessageDigest md, byte[] sender,
1969+ byte[] pad1, byte[] pad2, SecretKey masterSecret) {
1970+ md.update(sender);
1971+ CertificateVerify.updateDigest(md, pad1, pad2, masterSecret);
1972+ }
1973+
1974+ // get the verify_data of the finished message
1975+ byte[] getVerifyData() {
1976+ return verifyData;
1977+ }
1978+
1979+ @Override
1980+ int messageType() { return ht_finished; }
1981+
1982+ @Override
1983+ int messageLength() {
1984+ return verifyData.length;
1985+ }
1986+
1987+ @Override
1988+ void send(HandshakeOutStream out) throws IOException {
1989+ out.write(verifyData);
1990+ }
1991+
1992+ @Override
1993+ void print(PrintStream s) throws IOException {
1994+ s.println("*** Finished");
1995+ if (debug != null && Debug.isOn("verbose")) {
1996+ Debug.println(s, "verify_data", verifyData);
1997+ s.println("***");
1998+ }
1999+ }
2000+}
2001+
2002+//
2003+// END of nested classes
2004+//
2005+
2006+}