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
26package sun.security.ssl;
27
28import java.io.*;
29import java.math.BigInteger;
30import java.security.*;
31import java.security.interfaces.*;
32import java.security.spec.*;
33import java.security.cert.*;
34import java.security.cert.Certificate;
35import java.util.*;
36import java.util.concurrent.ConcurrentHashMap;
37
38import java.lang.reflect.*;
39
40import javax.security.auth.x500.X500Principal;
41
42import javax.crypto.KeyGenerator;
43import javax.crypto.SecretKey;
44
45import javax.net.ssl.*;
46
47import sun.security.internal.spec.TlsPrfParameterSpec;
48import sun.security.ssl.CipherSuite.*;
49import 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 */
72public 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 */
172static 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 */
208static 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 */
333static final
334class 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 */
420static final
421class 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 */
533static 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 */
547static final
548class 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 */
678static final
679class 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 */
947static final
948class 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
1166static 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 */
1226static final
1227class 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 */
1479static final
1480class 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 */
1514static 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 */
1817static 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}