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

Unified · Split

java/pkg/sun/security/ssl/ClientHandshaker.java+1341−0
@@ -0,0 +1,1341 @@
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.util.*;
32
33import java.security.interfaces.ECPublicKey;
34import java.security.interfaces.RSAPublicKey;
35import java.security.spec.ECParameterSpec;
36
37import java.security.cert.X509Certificate;
38import java.security.cert.CertificateException;
39
40import javax.crypto.SecretKey;
41import javax.crypto.spec.SecretKeySpec;
42
43import javax.net.ssl.*;
44
45import javax.security.auth.Subject;
46
47import sun.security.ssl.HandshakeMessage.*;
48import sun.security.ssl.CipherSuite.*;
49import static sun.security.ssl.CipherSuite.KeyExchange.*;
50
51import sun.net.util.IPAddressUtil;
52
53/**
54 * ClientHandshaker does the protocol handshaking from the point
55 * of view of a client. It is driven asychronously by handshake messages
56 * as delivered by the parent Handshaker class, and also uses
57 * common functionality (e.g. key generation) that is provided there.
58 *
59 * @author David Brownell
60 */
61final class ClientHandshaker extends Handshaker {
62
63 // the server's public key from its certificate.
64 private PublicKey serverKey;
65
66 // the server's ephemeral public key from the server key exchange message
67 // for ECDHE/ECDH_anon and RSA_EXPORT.
68 private PublicKey ephemeralServerKey;
69
70 // server's ephemeral public value for DHE/DH_anon key exchanges
71 private BigInteger serverDH;
72
73 private DHCrypt dh;
74
75 private ECDHCrypt ecdh;
76
77 private CertificateRequest certRequest;
78
79 private boolean serverKeyExchangeReceived;
80
81 /*
82 * The RSA PreMasterSecret needs to know the version of
83 * ClientHello that was used on this handshake. This represents
84 * the "max version" this client is supporting. In the
85 * case of an initial handshake, it's the max version enabled,
86 * but in the case of a resumption attempt, it's the version
87 * of the session we're trying to resume.
88 */
89 private ProtocolVersion maxProtocolVersion;
90
91 // To switch off the SNI extension.
92 private final static boolean enableSNIExtension =
93 Debug.getBooleanProperty("jsse.enableSNIExtension", true);
94
95 /*
96 * Constructors
97 */
98 ClientHandshaker(SSLSocketImpl socket, SSLContextImpl context,
99 ProtocolList enabledProtocols,
100 ProtocolVersion activeProtocolVersion,
101 boolean isInitialHandshake, boolean secureRenegotiation,
102 byte[] clientVerifyData, byte[] serverVerifyData) {
103
104 super(socket, context, enabledProtocols, true, true,
105 activeProtocolVersion, isInitialHandshake, secureRenegotiation,
106 clientVerifyData, serverVerifyData);
107 }
108
109 ClientHandshaker(SSLEngineImpl engine, SSLContextImpl context,
110 ProtocolList enabledProtocols,
111 ProtocolVersion activeProtocolVersion,
112 boolean isInitialHandshake, boolean secureRenegotiation,
113 byte[] clientVerifyData, byte[] serverVerifyData) {
114
115 super(engine, context, enabledProtocols, true, true,
116 activeProtocolVersion, isInitialHandshake, secureRenegotiation,
117 clientVerifyData, serverVerifyData);
118 }
119
120 /*
121 * This routine handles all the client side handshake messages, one at
122 * a time. Given the message type (and in some cases the pending cipher
123 * spec) it parses the type-specific message. Then it calls a function
124 * that handles that specific message.
125 *
126 * It updates the state machine (need to verify it) as each message
127 * is processed, and writes responses as needed using the connection
128 * in the constructor.
129 */
130 void processMessage(byte type, int messageLen) throws IOException {
131 if (state > type
132 && (type != HandshakeMessage.ht_hello_request
133 && state != HandshakeMessage.ht_client_hello)) {
134 throw new SSLProtocolException(
135 "Handshake message sequence violation, " + type);
136 }
137
138 switch (type) {
139 case HandshakeMessage.ht_hello_request:
140 this.serverHelloRequest(new HelloRequest(input));
141 break;
142
143 case HandshakeMessage.ht_server_hello:
144 this.serverHello(new ServerHello(input, messageLen));
145 break;
146
147 case HandshakeMessage.ht_certificate:
148 if (keyExchange == K_DH_ANON || keyExchange == K_ECDH_ANON
149 || keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
150 fatalSE(Alerts.alert_unexpected_message,
151 "unexpected server cert chain");
152 // NOTREACHED
153 }
154 this.serverCertificate(new CertificateMsg(input));
155 serverKey =
156 session.getPeerCertificates()[0].getPublicKey();
157 break;
158
159 case HandshakeMessage.ht_server_key_exchange:
160 serverKeyExchangeReceived = true;
161 switch (keyExchange) {
162 case K_RSA_EXPORT:
163 /**
164 * The server key exchange message is sent by the server only
165 * when the server certificate message does not contain the
166 * proper amount of data to allow the client to exchange a
167 * premaster secret, such as when RSA_EXPORT is used and the
168 * public key in the server certificate is longer than 512 bits.
169 */
170 if (serverKey == null) {
171 throw new SSLProtocolException
172 ("Server did not send certificate message");
173 }
174
175 if (!(serverKey instanceof RSAPublicKey)) {
176 throw new SSLProtocolException("Protocol violation:" +
177 " the certificate type must be appropriate for the" +
178 " selected cipher suite's key exchange algorithm");
179 }
180
181 if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
182 throw new SSLProtocolException("Protocol violation:" +
183 " server sent a server key exchange message for" +
184 " key exchange " + keyExchange +
185 " when the public key in the server certificate" +
186 " is less than or equal to 512 bits in length");
187 }
188
189 try {
190 this.serverKeyExchange(new RSA_ServerKeyExchange(input));
191 } catch (GeneralSecurityException e) {
192 throwSSLException("Server key", e);
193 }
194 break;
195 case K_DH_ANON:
196 this.serverKeyExchange(new DH_ServerKeyExchange(
197 input, protocolVersion));
198 break;
199 case K_DHE_DSS:
200 case K_DHE_RSA:
201 try {
202 this.serverKeyExchange(new DH_ServerKeyExchange(
203 input, serverKey,
204 clnt_random.random_bytes, svr_random.random_bytes,
205 messageLen,
206 localSupportedSignAlgs, protocolVersion));
207 } catch (GeneralSecurityException e) {
208 throwSSLException("Server key", e);
209 }
210 break;
211 case K_ECDHE_ECDSA:
212 case K_ECDHE_RSA:
213 case K_ECDH_ANON:
214 try {
215 this.serverKeyExchange(new ECDH_ServerKeyExchange
216 (input, serverKey, clnt_random.random_bytes,
217 svr_random.random_bytes,
218 localSupportedSignAlgs, protocolVersion));
219 } catch (GeneralSecurityException e) {
220 throwSSLException("Server key", e);
221 }
222 break;
223 case K_RSA:
224 case K_DH_RSA:
225 case K_DH_DSS:
226 case K_ECDH_ECDSA:
227 case K_ECDH_RSA:
228 throw new SSLProtocolException(
229 "Protocol violation: server sent a server key exchange"
230 + "message for key exchange " + keyExchange);
231 case K_KRB5:
232 case K_KRB5_EXPORT:
233 throw new SSLProtocolException(
234 "unexpected receipt of server key exchange algorithm");
235 default:
236 throw new SSLProtocolException(
237 "unsupported key exchange algorithm = "
238 + keyExchange);
239 }
240 break;
241
242 case HandshakeMessage.ht_certificate_request:
243 // save for later, it's handled by serverHelloDone
244 if ((keyExchange == K_DH_ANON) || (keyExchange == K_ECDH_ANON)) {
245 throw new SSLHandshakeException(
246 "Client authentication requested for "+
247 "anonymous cipher suite.");
248 } else if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
249 throw new SSLHandshakeException(
250 "Client certificate requested for "+
251 "kerberos cipher suite.");
252 }
253 certRequest = new CertificateRequest(input, protocolVersion);
254 if (debug != null && Debug.isOn("handshake")) {
255 certRequest.print(System.out);
256 }
257
258 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
259 Collection<SignatureAndHashAlgorithm> peerSignAlgs =
260 certRequest.getSignAlgorithms();
261 if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
262 throw new SSLHandshakeException(
263 "No peer supported signature algorithms");
264 }
265
266 Collection<SignatureAndHashAlgorithm> supportedPeerSignAlgs =
267 SignatureAndHashAlgorithm.getSupportedAlgorithms(
268 peerSignAlgs);
269 if (supportedPeerSignAlgs.isEmpty()) {
270 throw new SSLHandshakeException(
271 "No supported signature and hash algorithm in common");
272 }
273
274 setPeerSupportedSignAlgs(supportedPeerSignAlgs);
275 session.setPeerSupportedSignatureAlgorithms(
276 supportedPeerSignAlgs);
277 }
278
279 break;
280
281 case HandshakeMessage.ht_server_hello_done:
282 this.serverHelloDone(new ServerHelloDone(input));
283 break;
284
285 case HandshakeMessage.ht_finished:
286 this.serverFinished(
287 new Finished(protocolVersion, input, cipherSuite));
288 break;
289
290 default:
291 throw new SSLProtocolException(
292 "Illegal client handshake msg, " + type);
293 }
294
295 //
296 // Move state machine forward if the message handling
297 // code didn't already do so
298 //
299 if (state < type) {
300 state = type;
301 }
302 }
303
304 /*
305 * Used by the server to kickstart negotiations -- this requests a
306 * "client hello" to renegotiate current cipher specs (e.g. maybe lots
307 * of data has been encrypted with the same keys, or the server needs
308 * the client to present a certificate).
309 */
310 private void serverHelloRequest(HelloRequest mesg) throws IOException {
311 if (debug != null && Debug.isOn("handshake")) {
312 mesg.print(System.out);
313 }
314
315 //
316 // Could be (e.g. at connection setup) that we already
317 // sent the "client hello" but the server's not seen it.
318 //
319 if (state < HandshakeMessage.ht_client_hello) {
320 if (!secureRenegotiation && !allowUnsafeRenegotiation) {
321 // renegotiation is not allowed.
322 if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
323 // response with a no_renegotiation warning,
324 warningSE(Alerts.alert_no_renegotiation);
325
326 // invalidate the handshake so that the caller can
327 // dispose this object.
328 invalidated = true;
329
330 // If there is still unread block in the handshake
331 // input stream, it would be truncated with the disposal
332 // and the next handshake message will become incomplete.
333 //
334 // However, according to SSL/TLS specifications, no more
335 // handshake message should immediately follow ClientHello
336 // or HelloRequest. So just let it be.
337 } else {
338 // For SSLv3, send the handshake_failure fatal error.
339 // Note that SSLv3 does not define a no_renegotiation
340 // alert like TLSv1. However we cannot ignore the message
341 // simply, otherwise the other side was waiting for a
342 // response that would never come.
343 fatalSE(Alerts.alert_handshake_failure,
344 "Renegotiation is not allowed");
345 }
346 } else {
347 if (!secureRenegotiation) {
348 if (debug != null && Debug.isOn("handshake")) {
349 System.out.println(
350 "Warning: continue with insecure renegotiation");
351 }
352 }
353 kickstart();
354 }
355 }
356 }
357
358
359 /*
360 * Server chooses session parameters given options created by the
361 * client -- basically, cipher options, session id, and someday a
362 * set of compression options.
363 *
364 * There are two branches of the state machine, decided by the
365 * details of this message. One is the "fast" handshake, where we
366 * can resume the pre-existing session we asked resume. The other
367 * is a more expensive "full" handshake, with key exchange and
368 * probably authentication getting done.
369 */
370 private void serverHello(ServerHello mesg) throws IOException {
371 serverKeyExchangeReceived = false;
372 if (debug != null && Debug.isOn("handshake")) {
373 mesg.print(System.out);
374 }
375
376 // check if the server selected protocol version is OK for us
377 ProtocolVersion mesgVersion = mesg.protocolVersion;
378 if (!isNegotiable(mesgVersion)) {
379 throw new SSLHandshakeException(
380 "Server chose " + mesgVersion +
381 ", but that protocol version is not enabled or not supported " +
382 "by the client.");
383 }
384
385 handshakeHash.protocolDetermined(mesgVersion);
386
387 // Set protocolVersion and propagate to SSLSocket and the
388 // Handshake streams
389 setVersion(mesgVersion);
390
391 // check the "renegotiation_info" extension
392 RenegotiationInfoExtension serverHelloRI = (RenegotiationInfoExtension)
393 mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
394 if (serverHelloRI != null) {
395 if (isInitialHandshake) {
396 // verify the length of the "renegotiated_connection" field
397 if (!serverHelloRI.isEmpty()) {
398 // abort the handshake with a fatal handshake_failure alert
399 fatalSE(Alerts.alert_handshake_failure,
400 "The renegotiation_info field is not empty");
401 }
402
403 secureRenegotiation = true;
404 } else {
405 // For a legacy renegotiation, the client MUST verify that
406 // it does not contain the "renegotiation_info" extension.
407 if (!secureRenegotiation) {
408 fatalSE(Alerts.alert_handshake_failure,
409 "Unexpected renegotiation indication extension");
410 }
411
412 // verify the client_verify_data and server_verify_data values
413 byte[] verifyData =
414 new byte[clientVerifyData.length + serverVerifyData.length];
415 System.arraycopy(clientVerifyData, 0, verifyData,
416 0, clientVerifyData.length);
417 System.arraycopy(serverVerifyData, 0, verifyData,
418 clientVerifyData.length, serverVerifyData.length);
419 if (!Arrays.equals(verifyData,
420 serverHelloRI.getRenegotiatedConnection())) {
421 fatalSE(Alerts.alert_handshake_failure,
422 "Incorrect verify data in ServerHello " +
423 "renegotiation_info message");
424 }
425 }
426 } else {
427 // no renegotiation indication extension
428 if (isInitialHandshake) {
429 if (!allowLegacyHelloMessages) {
430 // abort the handshake with a fatal handshake_failure alert
431 fatalSE(Alerts.alert_handshake_failure,
432 "Failed to negotiate the use of secure renegotiation");
433 }
434
435 secureRenegotiation = false;
436 if (debug != null && Debug.isOn("handshake")) {
437 System.out.println("Warning: No renegotiation " +
438 "indication extension in ServerHello");
439 }
440 } else {
441 // For a secure renegotiation, the client must abort the
442 // handshake if no "renegotiation_info" extension is present.
443 if (secureRenegotiation) {
444 fatalSE(Alerts.alert_handshake_failure,
445 "No renegotiation indication extension");
446 }
447
448 // we have already allowed unsafe renegotation before request
449 // the renegotiation.
450 }
451 }
452
453 //
454 // Save server nonce, we always use it to compute connection
455 // keys and it's also used to create the master secret if we're
456 // creating a new session (i.e. in the full handshake).
457 //
458 svr_random = mesg.svr_random;
459
460 if (isNegotiable(mesg.cipherSuite) == false) {
461 fatalSE(Alerts.alert_illegal_parameter,
462 "Server selected improper ciphersuite " + mesg.cipherSuite);
463 }
464
465 setCipherSuite(mesg.cipherSuite);
466 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
467 handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
468 }
469
470 if (mesg.compression_method != 0) {
471 fatalSE(Alerts.alert_illegal_parameter,
472 "compression type not supported, "
473 + mesg.compression_method);
474 // NOTREACHED
475 }
476
477 // so far so good, let's look at the session
478 if (session != null) {
479 // we tried to resume, let's see what the server decided
480 if (session.getSessionId().equals(mesg.sessionId)) {
481 // server resumed the session, let's make sure everything
482 // checks out
483
484 // Verify that the session ciphers are unchanged.
485 CipherSuite sessionSuite = session.getSuite();
486 if (cipherSuite != sessionSuite) {
487 throw new SSLProtocolException
488 ("Server returned wrong cipher suite for session");
489 }
490
491 // verify protocol version match
492 ProtocolVersion sessionVersion = session.getProtocolVersion();
493 if (protocolVersion != sessionVersion) {
494 throw new SSLProtocolException
495 ("Server resumed session with wrong protocol version");
496 }
497
498 // validate subject identity
499 if (sessionSuite.keyExchange == K_KRB5 ||
500 sessionSuite.keyExchange == K_KRB5_EXPORT) {
501 Principal localPrincipal = session.getLocalPrincipal();
502
503 Subject subject = null;
504 try {
505 subject = AccessController.doPrivileged(
506 new PrivilegedExceptionAction<Subject>() {
507 public Subject run() throws Exception {
508 return Krb5Helper.getClientSubject(getAccSE());
509 }});
510 } catch (PrivilegedActionException e) {
511 subject = null;
512 if (debug != null && Debug.isOn("session")) {
513 System.out.println("Attempt to obtain" +
514 " subject failed!");
515 }
516 }
517
518 if (subject != null) {
519 // Eliminate dependency on KerberosPrincipal
520 Set<Principal> principals =
521 subject.getPrincipals(Principal.class);
522 if (!principals.contains(localPrincipal)) {
523 throw new SSLProtocolException("Server resumed" +
524 " session with wrong subject identity");
525 } else {
526 if (debug != null && Debug.isOn("session"))
527 System.out.println("Subject identity is same");
528 }
529 } else {
530 if (debug != null && Debug.isOn("session"))
531 System.out.println("Kerberos credentials are not" +
532 " present in the current Subject; check if " +
533 " javax.security.auth.useSubjectAsCreds" +
534 " system property has been set to false");
535 throw new SSLProtocolException
536 ("Server resumed session with no subject");
537 }
538 }
539
540 // looks fine; resume it, and update the state machine.
541 resumingSession = true;
542 state = HandshakeMessage.ht_finished - 1;
543 calculateConnectionKeys(session.getMasterSecret());
544 if (debug != null && Debug.isOn("session")) {
545 System.out.println("%% Server resumed " + session);
546 }
547 } else {
548 // we wanted to resume, but the server refused
549 session = null;
550 if (!enableNewSession) {
551 throw new SSLException
552 ("New session creation is disabled");
553 }
554 }
555 }
556
557 if (resumingSession && session != null) {
558 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
559 handshakeHash.setCertificateVerifyAlg(null);
560 }
561
562 setHandshakeSessionSE(session);
563 return;
564 }
565
566 // check extensions
567 for (HelloExtension ext : mesg.extensions.list()) {
568 ExtensionType type = ext.type;
569 if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
570 && (type != ExtensionType.EXT_EC_POINT_FORMATS)
571 && (type != ExtensionType.EXT_SERVER_NAME)
572 && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
573 fatalSE(Alerts.alert_unsupported_extension,
574 "Server sent an unsupported extension: " + type);
575 }
576 }
577
578 // Create a new session, we need to do the full handshake
579 session = new SSLSessionImpl(protocolVersion, cipherSuite,
580 getLocalSupportedSignAlgs(),
581 mesg.sessionId, getHostSE(), getPortSE());
582 setHandshakeSessionSE(session);
583 if (debug != null && Debug.isOn("handshake")) {
584 System.out.println("** " + cipherSuite);
585 }
586 }
587
588 /*
589 * Server's own key was either a signing-only key, or was too
590 * large for export rules ... this message holds an ephemeral
591 * RSA key to use for key exchange.
592 */
593 private void serverKeyExchange(RSA_ServerKeyExchange mesg)
594 throws IOException, GeneralSecurityException {
595 if (debug != null && Debug.isOn("handshake")) {
596 mesg.print(System.out);
597 }
598 if (!mesg.verify(serverKey, clnt_random, svr_random)) {
599 fatalSE(Alerts.alert_handshake_failure,
600 "server key exchange invalid");
601 // NOTREACHED
602 }
603 ephemeralServerKey = mesg.getPublicKey();
604 }
605
606
607 /*
608 * Diffie-Hellman key exchange. We save the server public key and
609 * our own D-H algorithm object so we can defer key calculations
610 * until after we've sent the client key exchange message (which
611 * gives client and server some useful parallelism).
612 */
613 private void serverKeyExchange(DH_ServerKeyExchange mesg)
614 throws IOException {
615 if (debug != null && Debug.isOn("handshake")) {
616 mesg.print(System.out);
617 }
618 dh = new DHCrypt(mesg.getModulus(), mesg.getBase(),
619 sslContext.getSecureRandom());
620 serverDH = mesg.getServerPublicKey();
621 }
622
623 private void serverKeyExchange(ECDH_ServerKeyExchange mesg)
624 throws IOException {
625 if (debug != null && Debug.isOn("handshake")) {
626 mesg.print(System.out);
627 }
628 ECPublicKey key = mesg.getPublicKey();
629 ecdh = new ECDHCrypt(key.getParams(), sslContext.getSecureRandom());
630 ephemeralServerKey = key;
631 }
632
633 /*
634 * The server's "Hello Done" message is the client's sign that
635 * it's time to do all the hard work.
636 */
637 private void serverHelloDone(ServerHelloDone mesg) throws IOException {
638 if (debug != null && Debug.isOn("handshake")) {
639 mesg.print(System.out);
640 }
641 /*
642 * Always make sure the input has been digested before we
643 * start emitting data, to ensure the hashes are correctly
644 * computed for the Finished and CertificateVerify messages
645 * which we send (here).
646 */
647 input.digestNow();
648
649 /*
650 * FIRST ... if requested, send an appropriate Certificate chain
651 * to authenticate the client, and remember the associated private
652 * key to sign the CertificateVerify message.
653 */
654 PrivateKey signingKey = null;
655
656 if (certRequest != null) {
657 X509ExtendedKeyManager km = sslContext.getX509KeyManager();
658
659 ArrayList<String> keytypesTmp = new ArrayList<>(4);
660
661 for (int i = 0; i < certRequest.types.length; i++) {
662 String typeName;
663
664 switch (certRequest.types[i]) {
665 case CertificateRequest.cct_rsa_sign:
666 typeName = "RSA";
667 break;
668
669 case CertificateRequest.cct_dss_sign:
670 typeName = "DSA";
671 break;
672
673 case CertificateRequest.cct_ecdsa_sign:
674 // ignore if we do not have EC crypto available
675 typeName = JsseJce.isEcAvailable() ? "EC" : null;
676 break;
677
678 // Fixed DH/ECDH client authentication not supported
679 case CertificateRequest.cct_rsa_fixed_dh:
680 case CertificateRequest.cct_dss_fixed_dh:
681 case CertificateRequest.cct_rsa_fixed_ecdh:
682 case CertificateRequest.cct_ecdsa_fixed_ecdh:
683 // Any other values (currently not used in TLS)
684 case CertificateRequest.cct_rsa_ephemeral_dh:
685 case CertificateRequest.cct_dss_ephemeral_dh:
686 default:
687 typeName = null;
688 break;
689 }
690
691 if ((typeName != null) && (!keytypesTmp.contains(typeName))) {
692 keytypesTmp.add(typeName);
693 }
694 }
695
696 String alias = null;
697 int keytypesTmpSize = keytypesTmp.size();
698 if (keytypesTmpSize != 0) {
699 String keytypes[] =
700 keytypesTmp.toArray(new String[keytypesTmpSize]);
701
702 if (conn != null) {
703 alias = km.chooseClientAlias(keytypes,
704 certRequest.getAuthorities(), conn);
705 } else {
706 alias = km.chooseEngineClientAlias(keytypes,
707 certRequest.getAuthorities(), engine);
708 }
709 }
710
711 CertificateMsg m1 = null;
712 if (alias != null) {
713 X509Certificate[] certs = km.getCertificateChain(alias);
714 if ((certs != null) && (certs.length != 0)) {
715 PublicKey publicKey = certs[0].getPublicKey();
716 // for EC, make sure we use a supported named curve
717 if (publicKey instanceof ECPublicKey) {
718 ECParameterSpec params =
719 ((ECPublicKey)publicKey).getParams();
720 int index =
721 SupportedEllipticCurvesExtension.getCurveIndex(
722 params);
723 if (!SupportedEllipticCurvesExtension.isSupported(
724 index)) {
725 publicKey = null;
726 }
727 }
728 if (publicKey != null) {
729 m1 = new CertificateMsg(certs);
730 signingKey = km.getPrivateKey(alias);
731 session.setLocalPrivateKey(signingKey);
732 session.setLocalCertificates(certs);
733 }
734 }
735 }
736 if (m1 == null) {
737 //
738 // No appropriate cert was found ... report this to the
739 // server. For SSLv3, send the no_certificate alert;
740 // TLS uses an empty cert chain instead.
741 //
742 if (protocolVersion.v >= ProtocolVersion.TLS10.v) {
743 m1 = new CertificateMsg(new X509Certificate [0]);
744 } else {
745 warningSE(Alerts.alert_no_certificate);
746 }
747 }
748
749 //
750 // At last ... send any client certificate chain.
751 //
752 if (m1 != null) {
753 if (debug != null && Debug.isOn("handshake")) {
754 m1.print(System.out);
755 }
756 m1.write(output);
757 }
758 }
759
760 /*
761 * SECOND ... send the client key exchange message. The
762 * procedure used is a function of the cipher suite selected;
763 * one is always needed.
764 */
765 HandshakeMessage m2;
766
767 switch (keyExchange) {
768
769 case K_RSA:
770 case K_RSA_EXPORT:
771 if (serverKey == null) {
772 throw new SSLProtocolException
773 ("Server did not send certificate message");
774 }
775
776 if (!(serverKey instanceof RSAPublicKey)) {
777 throw new SSLProtocolException
778 ("Server certificate does not include an RSA key");
779 }
780
781 /*
782 * For RSA key exchange, we randomly generate a new
783 * pre-master secret and encrypt it with the server's
784 * public key. Then we save that pre-master secret
785 * so that we can calculate the keying data later;
786 * it's a performance speedup not to do that until
787 * the client's waiting for the server response, but
788 * more of a speedup for the D-H case.
789 *
790 * If the RSA_EXPORT scheme is active, when the public
791 * key in the server certificate is less than or equal
792 * to 512 bits in length, use the cert's public key,
793 * otherwise, the ephemeral one.
794 */
795 PublicKey key;
796 if (keyExchange == K_RSA) {
797 key = serverKey;
798 } else { // K_RSA_EXPORT
799 if (JsseJce.getRSAKeyLength(serverKey) <= 512) {
800 // extraneous ephemeralServerKey check done
801 // above in processMessage()
802 key = serverKey;
803 } else {
804 if (ephemeralServerKey == null) {
805 throw new SSLProtocolException("Server did not send" +
806 " a RSA_EXPORT Server Key Exchange message");
807 }
808 key = ephemeralServerKey;
809 }
810 }
811
812 m2 = new RSAClientKeyExchange(protocolVersion, maxProtocolVersion,
813 sslContext.getSecureRandom(), key);
814 break;
815 case K_DH_RSA:
816 case K_DH_DSS:
817 /*
818 * For DH Key exchange, we only need to make sure the server
819 * knows our public key, so we calculate the same pre-master
820 * secret.
821 *
822 * For certs that had DH keys in them, we send an empty
823 * handshake message (no key) ... we flag this case by
824 * passing a null "dhPublic" value.
825 *
826 * Otherwise we send ephemeral DH keys, unsigned.
827 */
828 // if (useDH_RSA || useDH_DSS)
829 m2 = new DHClientKeyExchange();
830 break;
831 case K_DHE_RSA:
832 case K_DHE_DSS:
833 case K_DH_ANON:
834 if (dh == null) {
835 throw new SSLProtocolException
836 ("Server did not send a DH Server Key Exchange message");
837 }
838 m2 = new DHClientKeyExchange(dh.getPublicKey());
839 break;
840 case K_ECDHE_RSA:
841 case K_ECDHE_ECDSA:
842 case K_ECDH_ANON:
843 if (ecdh == null) {
844 throw new SSLProtocolException
845 ("Server did not send a ECDH Server Key Exchange message");
846 }
847 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
848 break;
849 case K_ECDH_RSA:
850 case K_ECDH_ECDSA:
851 if (serverKey == null) {
852 throw new SSLProtocolException
853 ("Server did not send certificate message");
854 }
855 if (serverKey instanceof ECPublicKey == false) {
856 throw new SSLProtocolException
857 ("Server certificate does not include an EC key");
858 }
859 ECParameterSpec params = ((ECPublicKey)serverKey).getParams();
860 ecdh = new ECDHCrypt(params, sslContext.getSecureRandom());
861 m2 = new ECDHClientKeyExchange(ecdh.getPublicKey());
862 break;
863 case K_KRB5:
864 case K_KRB5_EXPORT:
865 String hostname = getHostSE();
866 if (hostname == null) {
867 throw new IOException("Hostname is required" +
868 " to use Kerberos cipher suites");
869 }
870 KerberosClientKeyExchange kerberosMsg =
871 new KerberosClientKeyExchange(
872 hostname, isLoopbackSE(), getAccSE(), protocolVersion,
873 sslContext.getSecureRandom());
874 // Record the principals involved in exchange
875 session.setPeerPrincipal(kerberosMsg.getPeerPrincipal());
876 session.setLocalPrincipal(kerberosMsg.getLocalPrincipal());
877 m2 = kerberosMsg;
878 break;
879 default:
880 // somethings very wrong
881 throw new RuntimeException
882 ("Unsupported key exchange: " + keyExchange);
883 }
884 if (debug != null && Debug.isOn("handshake")) {
885 m2.print(System.out);
886 }
887 m2.write(output);
888
889
890 /*
891 * THIRD, send a "change_cipher_spec" record followed by the
892 * "Finished" message. We flush the messages we've queued up, to
893 * get concurrency between client and server. The concurrency is
894 * useful as we calculate the master secret, which is needed both
895 * to compute the "Finished" message, and to compute the keys used
896 * to protect all records following the change_cipher_spec.
897 */
898
899 output.doHashes();
900 output.flush();
901
902 /*
903 * We deferred calculating the master secret and this connection's
904 * keying data; we do it now. Deferring this calculation is good
905 * from a performance point of view, since it lets us do it during
906 * some time that network delays and the server's own calculations
907 * would otherwise cause to be "dead" in the critical path.
908 */
909 SecretKey preMasterSecret;
910 switch (keyExchange) {
911 case K_RSA:
912 case K_RSA_EXPORT:
913 preMasterSecret = ((RSAClientKeyExchange)m2).preMaster;
914 break;
915 case K_KRB5:
916 case K_KRB5_EXPORT:
917 byte[] secretBytes =
918 ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
919 preMasterSecret = new SecretKeySpec(secretBytes,
920 "TlsPremasterSecret");
921 break;
922 case K_DHE_RSA:
923 case K_DHE_DSS:
924 case K_DH_ANON:
925 preMasterSecret = dh.getAgreedSecret(serverDH);
926 break;
927 case K_ECDHE_RSA:
928 case K_ECDHE_ECDSA:
929 case K_ECDH_ANON:
930 preMasterSecret = ecdh.getAgreedSecret(ephemeralServerKey);
931 break;
932 case K_ECDH_RSA:
933 case K_ECDH_ECDSA:
934 preMasterSecret = ecdh.getAgreedSecret(serverKey);
935 break;
936 default:
937 throw new IOException("Internal error: unknown key exchange "
938 + keyExchange);
939 }
940
941 calculateKeys(preMasterSecret, null);
942
943 /*
944 * FOURTH, if we sent a Certificate, we need to send a signed
945 * CertificateVerify (unless the key in the client's certificate
946 * was a Diffie-Hellman key).).
947 *
948 * This uses a hash of the previous handshake messages ... either
949 * a nonfinal one (if the particular implementation supports it)
950 * or else using the third element in the arrays of hashes being
951 * computed.
952 */
953 if (signingKey != null) {
954 CertificateVerify m3;
955 try {
956 SignatureAndHashAlgorithm preferableSignatureAlgorithm = null;
957 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
958 preferableSignatureAlgorithm =
959 SignatureAndHashAlgorithm.getPreferableAlgorithm(
960 peerSupportedSignAlgs, signingKey.getAlgorithm());
961
962 if (preferableSignatureAlgorithm == null) {
963 throw new SSLHandshakeException(
964 "No supported signature algorithm");
965 }
966
967 String hashAlg =
968 SignatureAndHashAlgorithm.getHashAlgorithmName(
969 preferableSignatureAlgorithm);
970 if (hashAlg == null || hashAlg.length() == 0) {
971 throw new SSLHandshakeException(
972 "No supported hash algorithm");
973 }
974
975 handshakeHash.setCertificateVerifyAlg(hashAlg);
976 }
977
978 m3 = new CertificateVerify(protocolVersion, handshakeHash,
979 signingKey, session.getMasterSecret(),
980 sslContext.getSecureRandom(),
981 preferableSignatureAlgorithm);
982 } catch (GeneralSecurityException e) {
983 fatalSE(Alerts.alert_handshake_failure,
984 "Error signing certificate verify", e);
985 // NOTREACHED, make compiler happy
986 m3 = null;
987 }
988 if (debug != null && Debug.isOn("handshake")) {
989 m3.print(System.out);
990 }
991 m3.write(output);
992 output.doHashes();
993 } else {
994 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
995 handshakeHash.setCertificateVerifyAlg(null);
996 }
997 }
998
999 /*
1000 * OK, that's that!
1001 */
1002 sendChangeCipherAndFinish(false);
1003 }
1004
1005
1006 /*
1007 * "Finished" is the last handshake message sent. If we got this
1008 * far, the MAC has been validated post-decryption. We validate
1009 * the two hashes here as an additional sanity check, protecting
1010 * the handshake against various active attacks.
1011 */
1012 private void serverFinished(Finished mesg) throws IOException {
1013 if (debug != null && Debug.isOn("handshake")) {
1014 mesg.print(System.out);
1015 }
1016
1017 boolean verified = mesg.verify(handshakeHash, Finished.SERVER,
1018 session.getMasterSecret());
1019
1020 if (!verified) {
1021 fatalSE(Alerts.alert_illegal_parameter,
1022 "server 'finished' message doesn't verify");
1023 // NOTREACHED
1024 }
1025
1026 /*
1027 * save server verify data for secure renegotiation
1028 */
1029 if (secureRenegotiation) {
1030 serverVerifyData = mesg.getVerifyData();
1031 }
1032
1033 /*
1034 * OK, it verified. If we're doing the fast handshake, add that
1035 * "Finished" message to the hash of handshake messages, then send
1036 * our own change_cipher_spec and Finished message for the server
1037 * to verify in turn. These are the last handshake messages.
1038 *
1039 * In any case, update the session cache. We're done handshaking,
1040 * so there are no threats any more associated with partially
1041 * completed handshakes.
1042 */
1043 if (resumingSession) {
1044 input.digestNow();
1045 sendChangeCipherAndFinish(true);
1046 }
1047 session.setLastAccessedTime(System.currentTimeMillis());
1048
1049 if (!resumingSession) {
1050 if (session.isRejoinable()) {
1051 ((SSLSessionContextImpl) sslContext
1052 .engineGetClientSessionContext())
1053 .put(session);
1054 if (debug != null && Debug.isOn("session")) {
1055 System.out.println("%% Cached client session: " + session);
1056 }
1057 } else if (debug != null && Debug.isOn("session")) {
1058 System.out.println(
1059 "%% Didn't cache non-resumable client session: "
1060 + session);
1061 }
1062 }
1063 }
1064
1065
1066 /*
1067 * Send my change-cipher-spec and Finished message ... done as the
1068 * last handshake act in either the short or long sequences. In
1069 * the short one, we've already seen the server's Finished; in the
1070 * long one, we wait for it now.
1071 */
1072 private void sendChangeCipherAndFinish(boolean finishedTag)
1073 throws IOException {
1074 Finished mesg = new Finished(protocolVersion, handshakeHash,
1075 Finished.CLIENT, session.getMasterSecret(), cipherSuite);
1076
1077 /*
1078 * Send the change_cipher_spec message, then the Finished message
1079 * which we just calculated (and protected using the keys we just
1080 * calculated). Server responds with its Finished message, except
1081 * in the "fast handshake" (resume session) case.
1082 */
1083 sendChangeCipherSpec(mesg, finishedTag);
1084
1085 /*
1086 * save client verify data for secure renegotiation
1087 */
1088 if (secureRenegotiation) {
1089 clientVerifyData = mesg.getVerifyData();
1090 }
1091
1092 /*
1093 * Update state machine so server MUST send 'finished' next.
1094 * (In "long" handshake case; in short case, we're responding
1095 * to its message.)
1096 */
1097 state = HandshakeMessage.ht_finished - 1;
1098 }
1099
1100
1101 /*
1102 * Returns a ClientHello message to kickstart renegotiations
1103 */
1104 HandshakeMessage getKickstartMessage() throws SSLException {
1105 // session ID of the ClientHello message
1106 SessionId sessionId = SSLSessionImpl.nullSession.getSessionId();
1107
1108 // a list of cipher suites sent by the client
1109 CipherSuiteList cipherSuites = getActiveCipherSuites();
1110
1111 // set the max protocol version this client is supporting.
1112 maxProtocolVersion = protocolVersion;
1113
1114 //
1115 // Try to resume an existing session. This might be mandatory,
1116 // given certain API options.
1117 //
1118 session = ((SSLSessionContextImpl)sslContext
1119 .engineGetClientSessionContext())
1120 .get(getHostSE(), getPortSE());
1121 if (debug != null && Debug.isOn("session")) {
1122 if (session != null) {
1123 System.out.println("%% Client cached "
1124 + session
1125 + (session.isRejoinable() ? "" : " (not rejoinable)"));
1126 } else {
1127 System.out.println("%% No cached client session");
1128 }
1129 }
1130 if ((session != null) && (session.isRejoinable() == false)) {
1131 session = null;
1132 }
1133
1134 if (session != null) {
1135 CipherSuite sessionSuite = session.getSuite();
1136 ProtocolVersion sessionVersion = session.getProtocolVersion();
1137 if (isNegotiable(sessionSuite) == false) {
1138 if (debug != null && Debug.isOn("session")) {
1139 System.out.println("%% can't resume, unavailable cipher");
1140 }
1141 session = null;
1142 }
1143
1144 if ((session != null) && !isNegotiable(sessionVersion)) {
1145 if (debug != null && Debug.isOn("session")) {
1146 System.out.println("%% can't resume, protocol disabled");
1147 }
1148 session = null;
1149 }
1150
1151 if (session != null) {
1152 if (debug != null) {
1153 if (Debug.isOn("handshake") || Debug.isOn("session")) {
1154 System.out.println("%% Try resuming " + session
1155 + " from port " + getLocalPortSE());
1156 }
1157 }
1158
1159 sessionId = session.getSessionId();
1160 maxProtocolVersion = sessionVersion;
1161
1162 // Update SSL version number in underlying SSL socket and
1163 // handshake output stream, so that the output records (at the
1164 // record layer) have the correct version
1165 setVersion(sessionVersion);
1166 }
1167
1168 /*
1169 * Force use of the previous session ciphersuite, and
1170 * add the SCSV if enabled.
1171 */
1172 if (!enableNewSession) {
1173 if (session == null) {
1174 throw new SSLHandshakeException(
1175 "Can't reuse existing SSL client session");
1176 }
1177
1178 Collection<CipherSuite> cipherList = new ArrayList<>(2);
1179 cipherList.add(sessionSuite);
1180 if (!secureRenegotiation &&
1181 cipherSuites.contains(CipherSuite.C_SCSV)) {
1182 cipherList.add(CipherSuite.C_SCSV);
1183 } // otherwise, renegotiation_info extension will be used
1184
1185 cipherSuites = new CipherSuiteList(cipherList);
1186 }
1187 }
1188
1189 if (session == null && !enableNewSession) {
1190 throw new SSLHandshakeException("No existing session to resume");
1191 }
1192
1193 // exclude SCSV for secure renegotiation
1194 if (secureRenegotiation && cipherSuites.contains(CipherSuite.C_SCSV)) {
1195 Collection<CipherSuite> cipherList =
1196 new ArrayList<>(cipherSuites.size() - 1);
1197 for (CipherSuite suite : cipherSuites.collection()) {
1198 if (suite != CipherSuite.C_SCSV) {
1199 cipherList.add(suite);
1200 }
1201 }
1202
1203 cipherSuites = new CipherSuiteList(cipherList);
1204 }
1205
1206 // make sure there is a negotiable cipher suite.
1207 boolean negotiable = false;
1208 for (CipherSuite suite : cipherSuites.collection()) {
1209 if (isNegotiable(suite)) {
1210 negotiable = true;
1211 break;
1212 }
1213 }
1214
1215 if (!negotiable) {
1216 throw new SSLHandshakeException("No negotiable cipher suite");
1217 }
1218
1219 // Not a TLS1.2+ handshake
1220 // For SSLv2Hello, HandshakeHash.reset() will be called, so we
1221 // cannot call HandshakeHash.protocolDetermined() here. As it does
1222 // not follow the spec that HandshakeHash.reset() can be only be
1223 // called before protocolDetermined.
1224 // if (maxProtocolVersion.v < ProtocolVersion.TLS12.v) {
1225 // handshakeHash.protocolDetermined(maxProtocolVersion);
1226 // }
1227
1228 // create the ClientHello message
1229 ClientHello clientHelloMessage = new ClientHello(
1230 sslContext.getSecureRandom(), maxProtocolVersion,
1231 sessionId, cipherSuites);
1232
1233 // add signature_algorithm extension
1234 if (maxProtocolVersion.v >= ProtocolVersion.TLS12.v) {
1235 // we will always send the signature_algorithm extension
1236 Collection<SignatureAndHashAlgorithm> localSignAlgs =
1237 getLocalSupportedSignAlgs();
1238 if (localSignAlgs.isEmpty()) {
1239 throw new SSLHandshakeException(
1240 "No supported signature algorithm");
1241 }
1242
1243 clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
1244 }
1245
1246 // add server_name extension
1247 if (enableSNIExtension) {
1248 // We cannot use the hostname resolved from name services. For
1249 // virtual hosting, multiple hostnames may be bound to the same IP
1250 // address, so the hostname resolved from name services is not
1251 // reliable.
1252 String hostname = getRawHostnameSE();
1253
1254 // we only allow FQDN
1255 if (hostname != null && hostname.indexOf('.') > 0 &&
1256 !IPAddressUtil.isIPv4LiteralAddress(hostname) &&
1257 !IPAddressUtil.isIPv6LiteralAddress(hostname)) {
1258 clientHelloMessage.addServerNameIndicationExtension(hostname);
1259 }
1260 }
1261
1262 // reset the client random cookie
1263 clnt_random = clientHelloMessage.clnt_random;
1264
1265 /*
1266 * need to set the renegotiation_info extension for:
1267 * 1: secure renegotiation
1268 * 2: initial handshake and no SCSV in the ClientHello
1269 * 3: insecure renegotiation and no SCSV in the ClientHello
1270 */
1271 if (secureRenegotiation ||
1272 !cipherSuites.contains(CipherSuite.C_SCSV)) {
1273 clientHelloMessage.addRenegotiationInfoExtension(clientVerifyData);
1274 }
1275
1276 return clientHelloMessage;
1277 }
1278
1279 /*
1280 * Fault detected during handshake.
1281 */
1282 void handshakeAlert(byte description) throws SSLProtocolException {
1283 String message = Alerts.alertDescription(description);
1284
1285 if (debug != null && Debug.isOn("handshake")) {
1286 System.out.println("SSL - handshake alert: " + message);
1287 }
1288 throw new SSLProtocolException("handshake alert: " + message);
1289 }
1290
1291 /*
1292 * Unless we are using an anonymous ciphersuite, the server always
1293 * sends a certificate message (for the CipherSuites we currently
1294 * support). The trust manager verifies the chain for us.
1295 */
1296 private void serverCertificate(CertificateMsg mesg) throws IOException {
1297 if (debug != null && Debug.isOn("handshake")) {
1298 mesg.print(System.out);
1299 }
1300 X509Certificate[] peerCerts = mesg.getCertificateChain();
1301 if (peerCerts.length == 0) {
1302 fatalSE(Alerts.alert_bad_certificate,
1303 "empty certificate chain");
1304 }
1305 // ask the trust manager to verify the chain
1306 X509TrustManager tm = sslContext.getX509TrustManager();
1307 try {
1308 // find out the key exchange algorithm used
1309 // use "RSA" for non-ephemeral "RSA_EXPORT"
1310 String keyExchangeString;
1311 if (keyExchange == K_RSA_EXPORT && !serverKeyExchangeReceived) {
1312 keyExchangeString = K_RSA.name;
1313 } else {
1314 keyExchangeString = keyExchange.name;
1315 }
1316
1317 if (tm instanceof X509ExtendedTrustManager) {
1318 if (conn != null) {
1319 ((X509ExtendedTrustManager)tm).checkServerTrusted(
1320 peerCerts.clone(),
1321 keyExchangeString,
1322 conn);
1323 } else {
1324 ((X509ExtendedTrustManager)tm).checkServerTrusted(
1325 peerCerts.clone(),
1326 keyExchangeString,
1327 engine);
1328 }
1329 } else {
1330 // Unlikely to happen, because we have wrapped the old
1331 // X509TrustManager with the new X509ExtendedTrustManager.
1332 throw new CertificateException(
1333 "Improper X509TrustManager implementation");
1334 }
1335 } catch (CertificateException e) {
1336 // This will throw an exception, so include the original error.
1337 fatalSE(Alerts.alert_certificate_unknown, e);
1338 }
1339 session.setPeerCertificates(peerCerts);
1340 }
1341}