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