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

Unified · Split

java/pkg/sun/security/ssl/ServerHandshaker.java+1678−0
@@ -0,0 +1,1678 @@
1/*
2 * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27package sun.security.ssl;
28
29import java.io.*;
30import java.util.*;
31import java.security.*;
32import java.security.cert.*;
33import java.security.interfaces.*;
34import java.security.spec.ECParameterSpec;
35
36import javax.crypto.SecretKey;
37import javax.crypto.spec.SecretKeySpec;
38
39import javax.net.ssl.*;
40
41import javax.security.auth.Subject;
42
43import sun.security.ssl.HandshakeMessage.*;
44import sun.security.ssl.CipherSuite.*;
45import sun.security.ssl.SignatureAndHashAlgorithm.*;
46import static sun.security.ssl.CipherSuite.*;
47import static sun.security.ssl.CipherSuite.KeyExchange.*;
48
49/**
50 * ServerHandshaker does the protocol handshaking from the point
51 * of view of a server. It is driven asychronously by handshake messages
52 * as delivered by the parent Handshaker class, and also uses
53 * common functionality (e.g. key generation) that is provided there.
54 *
55 * @author David Brownell
56 */
57final class ServerHandshaker extends Handshaker {
58
59 // is the server going to require the client to authenticate?
60 private byte doClientAuth;
61
62 // our authentication info
63 private X509Certificate[] certs;
64 private PrivateKey privateKey;
65
66 private SecretKey[] kerberosKeys;
67
68 // flag to check for clientCertificateVerify message
69 private boolean needClientVerify = false;
70
71 /*
72 * For exportable ciphersuites using non-exportable key sizes, we use
73 * ephemeral RSA keys. We could also do anonymous RSA in the same way
74 * but there are no such ciphersuites currently defined.
75 */
76 private PrivateKey tempPrivateKey;
77 private PublicKey tempPublicKey;
78
79 /*
80 * For anonymous and ephemeral Diffie-Hellman key exchange, we use
81 * ephemeral Diffie-Hellman keys.
82 */
83 private DHCrypt dh;
84
85 // Helper for ECDH based key exchanges
86 private ECDHCrypt ecdh;
87
88 // version request by the client in its ClientHello
89 // we remember it for the RSA premaster secret version check
90 private ProtocolVersion clientRequestedVersion;
91
92 private SupportedEllipticCurvesExtension supportedCurves;
93
94 // the preferable signature algorithm used by ServerKeyExchange message
95 SignatureAndHashAlgorithm preferableSignatureAlgorithm;
96
97 /*
98 * Constructor ... use the keys found in the auth context.
99 */
100 ServerHandshaker(SSLSocketImpl socket, SSLContextImpl context,
101 ProtocolList enabledProtocols, byte clientAuth,
102 ProtocolVersion activeProtocolVersion, boolean isInitialHandshake,
103 boolean secureRenegotiation,
104 byte[] clientVerifyData, byte[] serverVerifyData) {
105
106 super(socket, context, enabledProtocols,
107 (clientAuth != SSLEngineImpl.clauth_none), false,
108 activeProtocolVersion, isInitialHandshake, secureRenegotiation,
109 clientVerifyData, serverVerifyData);
110 doClientAuth = clientAuth;
111 }
112
113 /*
114 * Constructor ... use the keys found in the auth context.
115 */
116 ServerHandshaker(SSLEngineImpl engine, SSLContextImpl context,
117 ProtocolList enabledProtocols, byte clientAuth,
118 ProtocolVersion activeProtocolVersion,
119 boolean isInitialHandshake, boolean secureRenegotiation,
120 byte[] clientVerifyData, byte[] serverVerifyData) {
121
122 super(engine, context, enabledProtocols,
123 (clientAuth != SSLEngineImpl.clauth_none), false,
124 activeProtocolVersion, isInitialHandshake, secureRenegotiation,
125 clientVerifyData, serverVerifyData);
126 doClientAuth = clientAuth;
127 }
128
129 /*
130 * As long as handshaking has not started, we can change
131 * whether client authentication is required. Otherwise,
132 * we will need to wait for the next handshake.
133 */
134 void setClientAuth(byte clientAuth) {
135 doClientAuth = clientAuth;
136 }
137
138 /*
139 * This routine handles all the server side handshake messages, one at
140 * a time. Given the message type (and in some cases the pending cipher
141 * spec) it parses the type-specific message. Then it calls a function
142 * that handles that specific message.
143 *
144 * It updates the state machine as each message is processed, and writes
145 * responses as needed using the connection in the constructor.
146 */
147 void processMessage(byte type, int message_len)
148 throws IOException {
149 //
150 // In SSLv3 and TLS, messages follow strictly increasing
151 // numerical order _except_ for one annoying special case.
152 //
153 if ((state > type)
154 && (state != HandshakeMessage.ht_client_key_exchange
155 && type != HandshakeMessage.ht_certificate_verify)) {
156 throw new SSLProtocolException(
157 "Handshake message sequence violation, state = " + state
158 + ", type = " + type);
159 }
160
161 switch (type) {
162 case HandshakeMessage.ht_client_hello:
163 ClientHello ch = new ClientHello(input, message_len);
164 /*
165 * send it off for processing.
166 */
167 this.clientHello(ch);
168 break;
169
170 case HandshakeMessage.ht_certificate:
171 if (doClientAuth == SSLEngineImpl.clauth_none) {
172 fatalSE(Alerts.alert_unexpected_message,
173 "client sent unsolicited cert chain");
174 // NOTREACHED
175 }
176 this.clientCertificate(new CertificateMsg(input));
177 break;
178
179 case HandshakeMessage.ht_client_key_exchange:
180 SecretKey preMasterSecret;
181 switch (keyExchange) {
182 case K_RSA:
183 case K_RSA_EXPORT:
184 /*
185 * The client's pre-master secret is decrypted using
186 * either the server's normal private RSA key, or the
187 * temporary one used for non-export or signing-only
188 * certificates/keys.
189 */
190 RSAClientKeyExchange pms = new RSAClientKeyExchange(
191 protocolVersion, clientRequestedVersion,
192 sslContext.getSecureRandom(), input,
193 message_len, privateKey);
194 preMasterSecret = this.clientKeyExchange(pms);
195 break;
196 case K_KRB5:
197 case K_KRB5_EXPORT:
198 preMasterSecret = this.clientKeyExchange(
199 new KerberosClientKeyExchange(protocolVersion,
200 clientRequestedVersion,
201 sslContext.getSecureRandom(),
202 input,
203 kerberosKeys));
204 break;
205 case K_DHE_RSA:
206 case K_DHE_DSS:
207 case K_DH_ANON:
208 /*
209 * The pre-master secret is derived using the normal
210 * Diffie-Hellman calculation. Note that the main
211 * protocol difference in these five flavors is in how
212 * the ServerKeyExchange message was constructed!
213 */
214 preMasterSecret = this.clientKeyExchange(
215 new DHClientKeyExchange(input));
216 break;
217 case K_ECDH_RSA:
218 case K_ECDH_ECDSA:
219 case K_ECDHE_RSA:
220 case K_ECDHE_ECDSA:
221 case K_ECDH_ANON:
222 preMasterSecret = this.clientKeyExchange
223 (new ECDHClientKeyExchange(input));
224 break;
225 default:
226 throw new SSLProtocolException
227 ("Unrecognized key exchange: " + keyExchange);
228 }
229
230 //
231 // All keys are calculated from the premaster secret
232 // and the exchanged nonces in the same way.
233 //
234 calculateKeys(preMasterSecret, clientRequestedVersion);
235 break;
236
237 case HandshakeMessage.ht_certificate_verify:
238 this.clientCertificateVerify(new CertificateVerify(input,
239 localSupportedSignAlgs, protocolVersion));
240 break;
241
242 case HandshakeMessage.ht_finished:
243 this.clientFinished(
244 new Finished(protocolVersion, input, cipherSuite));
245 break;
246
247 default:
248 throw new SSLProtocolException(
249 "Illegal server handshake msg, " + type);
250 }
251
252 //
253 // Move the state machine forward except for that annoying
254 // special case. This means that clients could send extra
255 // cert verify messages; not a problem so long as all of
256 // them actually check out.
257 //
258 if (state < type && type != HandshakeMessage.ht_certificate_verify) {
259 state = type;
260 }
261 }
262
263
264 /*
265 * ClientHello presents the server with a bunch of options, to which the
266 * server replies with a ServerHello listing the ones which this session
267 * will use. If needed, it also writes its Certificate plus in some cases
268 * a ServerKeyExchange message. It may also write a CertificateRequest,
269 * to elicit a client certificate.
270 *
271 * All these messages are terminated by a ServerHelloDone message. In
272 * most cases, all this can be sent in a single Record.
273 */
274 private void clientHello(ClientHello mesg) throws IOException {
275 if (debug != null && Debug.isOn("handshake")) {
276 mesg.print(System.out);
277 }
278
279 // Does the message include security renegotiation indication?
280 boolean renegotiationIndicated = false;
281
282 // check the TLS_EMPTY_RENEGOTIATION_INFO_SCSV
283 CipherSuiteList cipherSuites = mesg.getCipherSuites();
284 if (cipherSuites.contains(CipherSuite.C_SCSV)) {
285 renegotiationIndicated = true;
286 if (isInitialHandshake) {
287 secureRenegotiation = true;
288 } else {
289 // abort the handshake with a fatal handshake_failure alert
290 if (secureRenegotiation) {
291 fatalSE(Alerts.alert_handshake_failure,
292 "The SCSV is present in a secure renegotiation");
293 } else {
294 fatalSE(Alerts.alert_handshake_failure,
295 "The SCSV is present in a insecure renegotiation");
296 }
297 }
298 }
299
300 // check the "renegotiation_info" extension
301 RenegotiationInfoExtension clientHelloRI = (RenegotiationInfoExtension)
302 mesg.extensions.get(ExtensionType.EXT_RENEGOTIATION_INFO);
303 if (clientHelloRI != null) {
304 renegotiationIndicated = true;
305 if (isInitialHandshake) {
306 // verify the length of the "renegotiated_connection" field
307 if (!clientHelloRI.isEmpty()) {
308 // abort the handshake with a fatal handshake_failure alert
309 fatalSE(Alerts.alert_handshake_failure,
310 "The renegotiation_info field is not empty");
311 }
312
313 secureRenegotiation = true;
314 } else {
315 if (!secureRenegotiation) {
316 // unexpected RI extension for insecure renegotiation,
317 // abort the handshake with a fatal handshake_failure alert
318 fatalSE(Alerts.alert_handshake_failure,
319 "The renegotiation_info is present in a insecure " +
320 "renegotiation");
321 }
322
323 // verify the client_verify_data value
324 if (!Arrays.equals(clientVerifyData,
325 clientHelloRI.getRenegotiatedConnection())) {
326 fatalSE(Alerts.alert_handshake_failure,
327 "Incorrect verify data in ClientHello " +
328 "renegotiation_info message");
329 }
330 }
331 } else if (!isInitialHandshake && secureRenegotiation) {
332 // if the connection's "secure_renegotiation" flag is set to TRUE
333 // and the "renegotiation_info" extension is not present, abort
334 // the handshake.
335 fatalSE(Alerts.alert_handshake_failure,
336 "Inconsistent secure renegotiation indication");
337 }
338
339 // if there is no security renegotiation indication or the previous
340 // handshake is insecure.
341 if (!renegotiationIndicated || !secureRenegotiation) {
342 if (isInitialHandshake) {
343 if (!allowLegacyHelloMessages) {
344 // abort the handshake with a fatal handshake_failure alert
345 fatalSE(Alerts.alert_handshake_failure,
346 "Failed to negotiate the use of secure renegotiation");
347 }
348
349 // continue with legacy ClientHello
350 if (debug != null && Debug.isOn("handshake")) {
351 System.out.println("Warning: No renegotiation " +
352 "indication in ClientHello, allow legacy ClientHello");
353 }
354 } else if (!allowUnsafeRenegotiation) {
355 // abort the handshake
356 if (activeProtocolVersion.v >= ProtocolVersion.TLS10.v) {
357 // response with a no_renegotiation warning,
358 warningSE(Alerts.alert_no_renegotiation);
359
360 // invalidate the handshake so that the caller can
361 // dispose this object.
362 invalidated = true;
363
364 // If there is still unread block in the handshake
365 // input stream, it would be truncated with the disposal
366 // and the next handshake message will become incomplete.
367 //
368 // However, according to SSL/TLS specifications, no more
369 // handshake message could immediately follow ClientHello
370 // or HelloRequest. But in case of any improper messages,
371 // we'd better check to ensure there is no remaining bytes
372 // in the handshake input stream.
373 if (input.available() > 0) {
374 fatalSE(Alerts.alert_unexpected_message,
375 "ClientHello followed by an unexpected " +
376 "handshake message");
377 }
378
379 return;
380 } else {
381 // For SSLv3, send the handshake_failure fatal error.
382 // Note that SSLv3 does not define a no_renegotiation
383 // alert like TLSv1. However we cannot ignore the message
384 // simply, otherwise the other side was waiting for a
385 // response that would never come.
386 fatalSE(Alerts.alert_handshake_failure,
387 "Renegotiation is not allowed");
388 }
389 } else { // !isInitialHandshake && allowUnsafeRenegotiation
390 // continue with unsafe renegotiation.
391 if (debug != null && Debug.isOn("handshake")) {
392 System.out.println(
393 "Warning: continue with insecure renegotiation");
394 }
395 }
396 }
397
398 /*
399 * Always make sure this entire record has been digested before we
400 * start emitting output, to ensure correct digesting order.
401 */
402 input.digestNow();
403
404 /*
405 * FIRST, construct the ServerHello using the options and priorities
406 * from the ClientHello. Update the (pending) cipher spec as we do
407 * so, and save the client's version to protect against rollback
408 * attacks.
409 *
410 * There are a bunch of minor tasks here, and one major one: deciding
411 * if the short or the full handshake sequence will be used.
412 */
413 ServerHello m1 = new ServerHello();
414
415 clientRequestedVersion = mesg.protocolVersion;
416
417 // select a proper protocol version.
418 ProtocolVersion selectedVersion =
419 selectProtocolVersion(clientRequestedVersion);
420 if (selectedVersion == null ||
421 selectedVersion.v == ProtocolVersion.SSL20Hello.v) {
422 fatalSE(Alerts.alert_handshake_failure,
423 "Client requested protocol " + clientRequestedVersion +
424 " not enabled or not supported");
425 }
426
427 handshakeHash.protocolDetermined(selectedVersion);
428 setVersion(selectedVersion);
429
430 m1.protocolVersion = protocolVersion;
431
432 //
433 // random ... save client and server values for later use
434 // in computing the master secret (from pre-master secret)
435 // and thence the other crypto keys.
436 //
437 // NOTE: this use of three inputs to generating _each_ set
438 // of ciphers slows things down, but it does increase the
439 // security since each connection in the session can hold
440 // its own authenticated (and strong) keys. One could make
441 // creation of a session a rare thing...
442 //
443 clnt_random = mesg.clnt_random;
444 svr_random = new RandomCookie(sslContext.getSecureRandom());
445 m1.svr_random = svr_random;
446
447 session = null; // forget about the current session
448 //
449 // Here we go down either of two paths: (a) the fast one, where
450 // the client's asked to rejoin an existing session, and the server
451 // permits this; (b) the other one, where a new session is created.
452 //
453 if (mesg.sessionId.length() != 0) {
454 // client is trying to resume a session, let's see...
455
456 SSLSessionImpl previous = ((SSLSessionContextImpl)sslContext
457 .engineGetServerSessionContext())
458 .get(mesg.sessionId.getId());
459 //
460 // Check if we can use the fast path, resuming a session. We
461 // can do so iff we have a valid record for that session, and
462 // the cipher suite for that session was on the list which the
463 // client requested, and if we're not forgetting any needed
464 // authentication on the part of the client.
465 //
466 if (previous != null) {
467 resumingSession = previous.isRejoinable();
468
469 if (resumingSession) {
470 ProtocolVersion oldVersion = previous.getProtocolVersion();
471 // cannot resume session with different version
472 if (oldVersion != protocolVersion) {
473 resumingSession = false;
474 }
475 }
476
477 if (resumingSession &&
478 (doClientAuth == SSLEngineImpl.clauth_required)) {
479 try {
480 previous.getPeerPrincipal();
481 } catch (SSLPeerUnverifiedException e) {
482 resumingSession = false;
483 }
484 }
485
486 // validate subject identity
487 if (resumingSession) {
488 CipherSuite suite = previous.getSuite();
489 if (suite.keyExchange == K_KRB5 ||
490 suite.keyExchange == K_KRB5_EXPORT) {
491 Principal localPrincipal = previous.getLocalPrincipal();
492
493 Subject subject = null;
494 try {
495 subject = AccessController.doPrivileged(
496 new PrivilegedExceptionAction<Subject>() {
497 public Subject run() throws Exception {
498 return
499 Krb5Helper.getServerSubject(getAccSE());
500 }});
501 } catch (PrivilegedActionException e) {
502 subject = null;
503 if (debug != null && Debug.isOn("session")) {
504 System.out.println("Attempt to obtain" +
505 " subject failed!");
506 }
507 }
508
509 if (subject != null) {
510 // Eliminate dependency on KerberosPrincipal
511 Set<Principal> principals =
512 subject.getPrincipals(Principal.class);
513 if (!principals.contains(localPrincipal)) {
514 resumingSession = false;
515 if (debug != null && Debug.isOn("session")) {
516 System.out.println("Subject identity" +
517 " is not the same");
518 }
519 } else {
520 if (debug != null && Debug.isOn("session"))
521 System.out.println("Subject identity" +
522 " is same");
523 }
524 } else {
525 resumingSession = false;
526 if (debug != null && Debug.isOn("session"))
527 System.out.println("Kerberos credentials are" +
528 " not present in the current Subject;" +
529 " check if " +
530 " javax.security.auth.useSubjectAsCreds" +
531 " system property has been set to false");
532 }
533 }
534 }
535
536 if (resumingSession) {
537 CipherSuite suite = previous.getSuite();
538 // verify that the ciphersuite from the cached session
539 // is in the list of client requested ciphersuites and
540 // we have it enabled
541 if ((isNegotiable(suite) == false) ||
542 (mesg.getCipherSuites().contains(suite) == false)) {
543 resumingSession = false;
544 } else {
545 // everything looks ok, set the ciphersuite
546 // this should be done last when we are sure we
547 // will resume
548 setCipherSuite(suite);
549 }
550 }
551
552 if (resumingSession) {
553 session = previous;
554 if (debug != null &&
555 (Debug.isOn("handshake") || Debug.isOn("session"))) {
556 System.out.println("%% Resuming " + session);
557 }
558 }
559 }
560 } // else client did not try to resume
561
562 //
563 // If client hasn't specified a session we can resume, start a
564 // new one and choose its cipher suite and compression options.
565 // Unless new session creation is disabled for this connection!
566 //
567 if (session == null) {
568 if (!enableNewSession) {
569 throw new SSLException("Client did not resume a session");
570 }
571
572 supportedCurves = (SupportedEllipticCurvesExtension)
573 mesg.extensions.get(ExtensionType.EXT_ELLIPTIC_CURVES);
574
575 // We only need to handle the "signature_algorithm" extension
576 // for full handshakes and TLS 1.2 or later.
577 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
578 SignatureAlgorithmsExtension signAlgs =
579 (SignatureAlgorithmsExtension)mesg.extensions.get(
580 ExtensionType.EXT_SIGNATURE_ALGORITHMS);
581 if (signAlgs != null) {
582 Collection<SignatureAndHashAlgorithm> peerSignAlgs =
583 signAlgs.getSignAlgorithms();
584 if (peerSignAlgs == null || peerSignAlgs.isEmpty()) {
585 throw new SSLHandshakeException(
586 "No peer supported signature algorithms");
587 }
588
589 Collection<SignatureAndHashAlgorithm>
590 supportedPeerSignAlgs =
591 SignatureAndHashAlgorithm.getSupportedAlgorithms(
592 peerSignAlgs);
593 if (supportedPeerSignAlgs.isEmpty()) {
594 throw new SSLHandshakeException(
595 "No supported signature and hash algorithm " +
596 "in common");
597 }
598
599 setPeerSupportedSignAlgs(supportedPeerSignAlgs);
600 } // else, need to use peer implicit supported signature algs
601 }
602
603 session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
604 getLocalSupportedSignAlgs(),
605 sslContext.getSecureRandom(),
606 getHostAddressSE(), getPortSE());
607
608 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
609 if (peerSupportedSignAlgs != null) {
610 session.setPeerSupportedSignatureAlgorithms(
611 peerSupportedSignAlgs);
612 } // else, we will set the implicit peer supported signature
613 // algorithms in chooseCipherSuite()
614 }
615
616 // set the handshake session
617 setHandshakeSessionSE(session);
618
619 // choose cipher suite and corresponding private key
620 chooseCipherSuite(mesg);
621
622 session.setSuite(cipherSuite);
623 session.setLocalPrivateKey(privateKey);
624
625 // chooseCompression(mesg);
626 } else {
627 // set the handshake session
628 setHandshakeSessionSE(session);
629 }
630
631 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
632 if (resumingSession) {
633 handshakeHash.setCertificateVerifyAlg(null);
634 }
635 handshakeHash.setFinishedAlg(cipherSuite.prfAlg.getPRFHashAlg());
636 }
637
638 m1.cipherSuite = cipherSuite;
639 m1.sessionId = session.getSessionId();
640 m1.compression_method = session.getCompression();
641
642 if (secureRenegotiation) {
643 // For ServerHellos that are initial handshakes, then the
644 // "renegotiated_connection" field in "renegotiation_info"
645 // extension is of zero length.
646 //
647 // For ServerHellos that are renegotiating, this field contains
648 // the concatenation of client_verify_data and server_verify_data.
649 //
650 // Note that for initial handshakes, both the clientVerifyData
651 // variable and serverVerifyData variable are of zero length.
652 HelloExtension serverHelloRI = new RenegotiationInfoExtension(
653 clientVerifyData, serverVerifyData);
654 m1.extensions.add(serverHelloRI);
655 }
656
657 if (debug != null && Debug.isOn("handshake")) {
658 m1.print(System.out);
659 System.out.println("Cipher suite: " + session.getSuite());
660 }
661 m1.write(output);
662
663 //
664 // If we are resuming a session, we finish writing handshake
665 // messages right now and then finish.
666 //
667 if (resumingSession) {
668 calculateConnectionKeys(session.getMasterSecret());
669 sendChangeCipherAndFinish(false);
670 return;
671 }
672
673
674 /*
675 * SECOND, write the server Certificate(s) if we need to.
676 *
677 * NOTE: while an "anonymous RSA" mode is explicitly allowed by
678 * the protocol, we can't support it since all of the SSL flavors
679 * defined in the protocol spec are explicitly stated to require
680 * using RSA certificates.
681 */
682 if (keyExchange == K_KRB5 || keyExchange == K_KRB5_EXPORT) {
683 // Server certificates are omitted for Kerberos ciphers
684
685 } else if ((keyExchange != K_DH_ANON) && (keyExchange != K_ECDH_ANON)) {
686 if (certs == null) {
687 throw new RuntimeException("no certificates");
688 }
689
690 CertificateMsg m2 = new CertificateMsg(certs);
691
692 /*
693 * Set local certs in the SSLSession, output
694 * debug info, and then actually write to the client.
695 */
696 session.setLocalCertificates(certs);
697 if (debug != null && Debug.isOn("handshake")) {
698 m2.print(System.out);
699 }
700 m2.write(output);
701
702 // XXX has some side effects with OS TCP buffering,
703 // leave it out for now
704
705 // let client verify chain in the meantime...
706 // output.flush();
707 } else {
708 if (certs != null) {
709 throw new RuntimeException("anonymous keyexchange with certs");
710 }
711 }
712
713 /*
714 * THIRD, the ServerKeyExchange message ... iff it's needed.
715 *
716 * It's usually needed unless there's an encryption-capable
717 * RSA cert, or a D-H cert. The notable exception is that
718 * exportable ciphers used with big RSA keys need to downgrade
719 * to use short RSA keys, even when the key/cert encrypts OK.
720 */
721
722 ServerKeyExchange m3;
723 switch (keyExchange) {
724 case K_RSA:
725 case K_KRB5:
726 case K_KRB5_EXPORT:
727 // no server key exchange for RSA or KRB5 ciphersuites
728 m3 = null;
729 break;
730 case K_RSA_EXPORT:
731 if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
732 try {
733 m3 = new RSA_ServerKeyExchange(
734 tempPublicKey, privateKey,
735 clnt_random, svr_random,
736 sslContext.getSecureRandom());
737 privateKey = tempPrivateKey;
738 } catch (GeneralSecurityException e) {
739 throwSSLException
740 ("Error generating RSA server key exchange", e);
741 m3 = null; // make compiler happy
742 }
743 } else {
744 // RSA_EXPORT with short key, don't need ServerKeyExchange
745 m3 = null;
746 }
747 break;
748 case K_DHE_RSA:
749 case K_DHE_DSS:
750 try {
751 m3 = new DH_ServerKeyExchange(dh,
752 privateKey,
753 clnt_random.random_bytes,
754 svr_random.random_bytes,
755 sslContext.getSecureRandom(),
756 preferableSignatureAlgorithm,
757 protocolVersion);
758 } catch (GeneralSecurityException e) {
759 throwSSLException("Error generating DH server key exchange", e);
760 m3 = null; // make compiler happy
761 }
762 break;
763 case K_DH_ANON:
764 m3 = new DH_ServerKeyExchange(dh, protocolVersion);
765 break;
766 case K_ECDHE_RSA:
767 case K_ECDHE_ECDSA:
768 case K_ECDH_ANON:
769 try {
770 m3 = new ECDH_ServerKeyExchange(ecdh,
771 privateKey,
772 clnt_random.random_bytes,
773 svr_random.random_bytes,
774 sslContext.getSecureRandom(),
775 preferableSignatureAlgorithm,
776 protocolVersion);
777 } catch (GeneralSecurityException e) {
778 throwSSLException(
779 "Error generating ECDH server key exchange", e);
780 m3 = null; // make compiler happy
781 }
782 break;
783 case K_ECDH_RSA:
784 case K_ECDH_ECDSA:
785 // ServerKeyExchange not used for fixed ECDH
786 m3 = null;
787 break;
788 default:
789 throw new RuntimeException("internal error: " + keyExchange);
790 }
791 if (m3 != null) {
792 if (debug != null && Debug.isOn("handshake")) {
793 m3.print(System.out);
794 }
795 m3.write(output);
796 }
797
798 //
799 // FOURTH, the CertificateRequest message. The details of
800 // the message can be affected by the key exchange algorithm
801 // in use. For example, certs with fixed Diffie-Hellman keys
802 // are only useful with the DH_DSS and DH_RSA key exchange
803 // algorithms.
804 //
805 // Needed only if server requires client to authenticate self.
806 // Illegal for anonymous flavors, so we need to check that.
807 //
808 // CertificateRequest is omitted for Kerberos ciphers
809 if (doClientAuth != SSLEngineImpl.clauth_none &&
810 keyExchange != K_DH_ANON && keyExchange != K_ECDH_ANON &&
811 keyExchange != K_KRB5 && keyExchange != K_KRB5_EXPORT) {
812
813 CertificateRequest m4;
814 X509Certificate caCerts[];
815
816 Collection<SignatureAndHashAlgorithm> localSignAlgs = null;
817 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
818 // We currently use all local upported signature and hash
819 // algorithms. However, to minimize the computation cost
820 // of requested hash algorithms, we may use a restricted
821 // set of signature algorithms in the future.
822 localSignAlgs = getLocalSupportedSignAlgs();
823 if (localSignAlgs.isEmpty()) {
824 throw new SSLHandshakeException(
825 "No supported signature algorithm");
826 }
827
828 Set<String> localHashAlgs =
829 SignatureAndHashAlgorithm.getHashAlgorithmNames(
830 localSignAlgs);
831 if (localHashAlgs.isEmpty()) {
832 throw new SSLHandshakeException(
833 "No supported signature algorithm");
834 }
835 handshakeHash.restrictCertificateVerifyAlgs(localHashAlgs);
836 }
837
838 caCerts = sslContext.getX509TrustManager().getAcceptedIssuers();
839 m4 = new CertificateRequest(caCerts, keyExchange,
840 localSignAlgs, protocolVersion);
841
842 if (debug != null && Debug.isOn("handshake")) {
843 m4.print(System.out);
844 }
845 m4.write(output);
846 } else {
847 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
848 handshakeHash.setCertificateVerifyAlg(null);
849 }
850 }
851
852 /*
853 * FIFTH, say ServerHelloDone.
854 */
855 ServerHelloDone m5 = new ServerHelloDone();
856
857 if (debug != null && Debug.isOn("handshake")) {
858 m5.print(System.out);
859 }
860 m5.write(output);
861
862 /*
863 * Flush any buffered messages so the client will see them.
864 * Ideally, all the messages above go in a single network level
865 * message to the client. Without big Certificate chains, it's
866 * going to be the common case.
867 */
868 output.flush();
869 }
870
871 /*
872 * Choose cipher suite from among those supported by client. Sets
873 * the cipherSuite and keyExchange variables.
874 */
875 private void chooseCipherSuite(ClientHello mesg) throws IOException {
876 for (CipherSuite suite : mesg.getCipherSuites().collection()) {
877 if (isNegotiable(suite) == false) {
878 continue;
879 }
880
881 if (doClientAuth == SSLEngineImpl.clauth_required) {
882 if ((suite.keyExchange == K_DH_ANON) ||
883 (suite.keyExchange == K_ECDH_ANON)) {
884 continue;
885 }
886 }
887 if (trySetCipherSuite(suite) == false) {
888 continue;
889 }
890 return;
891 }
892 fatalSE(Alerts.alert_handshake_failure,
893 "no cipher suites in common");
894 }
895
896 /**
897 * Set the given CipherSuite, if possible. Return the result.
898 * The call succeeds if the CipherSuite is available and we have
899 * the necessary certificates to complete the handshake. We don't
900 * check if the CipherSuite is actually enabled.
901 *
902 * If successful, this method also generates ephemeral keys if
903 * required for this ciphersuite. This may take some time, so this
904 * method should only be called if you really want to use the
905 * CipherSuite.
906 *
907 * This method is called from chooseCipherSuite() in this class.
908 */
909 boolean trySetCipherSuite(CipherSuite suite) {
910 /*
911 * If we're resuming a session we know we can
912 * support this key exchange algorithm and in fact
913 * have already cached the result of it in
914 * the session state.
915 */
916 if (resumingSession) {
917 return true;
918 }
919
920 if (suite.isNegotiable() == false) {
921 return false;
922 }
923
924 // must not negotiate the obsoleted weak cipher suites.
925 if (protocolVersion.v >= suite.obsoleted) {
926 return false;
927 }
928
929 // must not negotiate unsupported cipher suites.
930 if (protocolVersion.v < suite.supported) {
931 return false;
932 }
933
934 KeyExchange keyExchange = suite.keyExchange;
935
936 // null out any existing references
937 privateKey = null;
938 certs = null;
939 dh = null;
940 tempPrivateKey = null;
941 tempPublicKey = null;
942
943 Collection<SignatureAndHashAlgorithm> supportedSignAlgs = null;
944 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
945 if (peerSupportedSignAlgs != null) {
946 supportedSignAlgs = peerSupportedSignAlgs;
947 } else {
948 SignatureAndHashAlgorithm algorithm = null;
949
950 // we may optimize the performance
951 switch (keyExchange) {
952 // If the negotiated key exchange algorithm is one of
953 // (RSA, DHE_RSA, DH_RSA, RSA_PSK, ECDH_RSA, ECDHE_RSA),
954 // behave as if client had sent the value {sha1,rsa}.
955 case K_RSA:
956 case K_DHE_RSA:
957 case K_DH_RSA:
958 // case K_RSA_PSK:
959 case K_ECDH_RSA:
960 case K_ECDHE_RSA:
961 algorithm = SignatureAndHashAlgorithm.valueOf(
962 HashAlgorithm.SHA1.value,
963 SignatureAlgorithm.RSA.value, 0);
964 break;
965 // If the negotiated key exchange algorithm is one of
966 // (DHE_DSS, DH_DSS), behave as if the client had
967 // sent the value {sha1,dsa}.
968 case K_DHE_DSS:
969 case K_DH_DSS:
970 algorithm = SignatureAndHashAlgorithm.valueOf(
971 HashAlgorithm.SHA1.value,
972 SignatureAlgorithm.DSA.value, 0);
973 break;
974 // If the negotiated key exchange algorithm is one of
975 // (ECDH_ECDSA, ECDHE_ECDSA), behave as if the client
976 // had sent value {sha1,ecdsa}.
977 case K_ECDH_ECDSA:
978 case K_ECDHE_ECDSA:
979 algorithm = SignatureAndHashAlgorithm.valueOf(
980 HashAlgorithm.SHA1.value,
981 SignatureAlgorithm.ECDSA.value, 0);
982 break;
983 default:
984 // no peer supported signature algorithms
985 }
986
987 if (algorithm == null) {
988 supportedSignAlgs =
989 Collections.<SignatureAndHashAlgorithm>emptySet();
990 } else {
991 supportedSignAlgs =
992 new ArrayList<SignatureAndHashAlgorithm>(1);
993 supportedSignAlgs.add(algorithm);
994 }
995
996 // Sets the peer supported signature algorithm to use in KM
997 // temporarily.
998 session.setPeerSupportedSignatureAlgorithms(supportedSignAlgs);
999 }
1000 }
1001
1002 switch (keyExchange) {
1003 case K_RSA:
1004 // need RSA certs for authentication
1005 if (setupPrivateKeyAndChain("RSA") == false) {
1006 return false;
1007 }
1008 break;
1009 case K_RSA_EXPORT:
1010 // need RSA certs for authentication
1011 if (setupPrivateKeyAndChain("RSA") == false) {
1012 return false;
1013 }
1014
1015 try {
1016 if (JsseJce.getRSAKeyLength(certs[0].getPublicKey()) > 512) {
1017 if (!setupEphemeralRSAKeys(suite.exportable)) {
1018 return false;
1019 }
1020 }
1021 } catch (RuntimeException e) {
1022 // could not determine keylength, ignore key
1023 return false;
1024 }
1025 break;
1026 case K_DHE_RSA:
1027 // get preferable peer signature algorithm for server key exchange
1028 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1029 preferableSignatureAlgorithm =
1030 SignatureAndHashAlgorithm.getPreferableAlgorithm(
1031 supportedSignAlgs, "RSA");
1032 if (preferableSignatureAlgorithm == null) {
1033 return false;
1034 }
1035 }
1036
1037 // need RSA certs for authentication
1038 if (setupPrivateKeyAndChain("RSA") == false) {
1039 return false;
1040 }
1041 setupEphemeralDHKeys(suite.exportable);
1042 break;
1043 case K_ECDHE_RSA:
1044 // get preferable peer signature algorithm for server key exchange
1045 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1046 preferableSignatureAlgorithm =
1047 SignatureAndHashAlgorithm.getPreferableAlgorithm(
1048 supportedSignAlgs, "RSA");
1049 if (preferableSignatureAlgorithm == null) {
1050 return false;
1051 }
1052 }
1053
1054 // need RSA certs for authentication
1055 if (setupPrivateKeyAndChain("RSA") == false) {
1056 return false;
1057 }
1058 if (setupEphemeralECDHKeys() == false) {
1059 return false;
1060 }
1061 break;
1062 case K_DHE_DSS:
1063 // get preferable peer signature algorithm for server key exchange
1064 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1065 preferableSignatureAlgorithm =
1066 SignatureAndHashAlgorithm.getPreferableAlgorithm(
1067 supportedSignAlgs, "DSA");
1068 if (preferableSignatureAlgorithm == null) {
1069 return false;
1070 }
1071 }
1072
1073 // need DSS certs for authentication
1074 if (setupPrivateKeyAndChain("DSA") == false) {
1075 return false;
1076 }
1077 setupEphemeralDHKeys(suite.exportable);
1078 break;
1079 case K_ECDHE_ECDSA:
1080 // get preferable peer signature algorithm for server key exchange
1081 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1082 preferableSignatureAlgorithm =
1083 SignatureAndHashAlgorithm.getPreferableAlgorithm(
1084 supportedSignAlgs, "ECDSA");
1085 if (preferableSignatureAlgorithm == null) {
1086 return false;
1087 }
1088 }
1089
1090 // need EC cert signed using EC
1091 if (setupPrivateKeyAndChain("EC_EC") == false) {
1092 return false;
1093 }
1094 if (setupEphemeralECDHKeys() == false) {
1095 return false;
1096 }
1097 break;
1098 case K_ECDH_RSA:
1099 // need EC cert signed using RSA
1100 if (setupPrivateKeyAndChain("EC_RSA") == false) {
1101 return false;
1102 }
1103 setupStaticECDHKeys();
1104 break;
1105 case K_ECDH_ECDSA:
1106 // need EC cert signed using EC
1107 if (setupPrivateKeyAndChain("EC_EC") == false) {
1108 return false;
1109 }
1110 setupStaticECDHKeys();
1111 break;
1112 case K_KRB5:
1113 case K_KRB5_EXPORT:
1114 // need Kerberos Key
1115 if (!setupKerberosKeys()) {
1116 return false;
1117 }
1118 break;
1119 case K_DH_ANON:
1120 // no certs needed for anonymous
1121 setupEphemeralDHKeys(suite.exportable);
1122 break;
1123 case K_ECDH_ANON:
1124 // no certs needed for anonymous
1125 if (setupEphemeralECDHKeys() == false) {
1126 return false;
1127 }
1128 break;
1129 default:
1130 // internal error, unknown key exchange
1131 throw new RuntimeException("Unrecognized cipherSuite: " + suite);
1132 }
1133 setCipherSuite(suite);
1134
1135 // set the peer implicit supported signature algorithms
1136 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1137 if (peerSupportedSignAlgs == null) {
1138 setPeerSupportedSignAlgs(supportedSignAlgs);
1139 // we had alreay update the session
1140 }
1141 }
1142 return true;
1143 }
1144
1145 /*
1146 * Get some "ephemeral" RSA keys for this context. This means
1147 * generating them if it's not already been done.
1148 *
1149 * Note that we currently do not implement any ciphersuites that use
1150 * strong ephemeral RSA. (We do not support the EXPORT1024 ciphersuites
1151 * and standard RSA ciphersuites prohibit ephemeral mode for some reason)
1152 * This means that export is always true and 512 bit keys are generated.
1153 */
1154 private boolean setupEphemeralRSAKeys(boolean export) {
1155 KeyPair kp = sslContext.getEphemeralKeyManager().
1156 getRSAKeyPair(export, sslContext.getSecureRandom());
1157 if (kp == null) {
1158 return false;
1159 } else {
1160 tempPublicKey = kp.getPublic();
1161 tempPrivateKey = kp.getPrivate();
1162 return true;
1163 }
1164 }
1165
1166 /*
1167 * Acquire some "ephemeral" Diffie-Hellman keys for this handshake.
1168 * We don't reuse these, for improved forward secrecy.
1169 */
1170 private void setupEphemeralDHKeys(boolean export) {
1171 /*
1172 * Diffie-Hellman keys ... we use 768 bit private keys due
1173 * to the "use twice as many key bits as bits you want secret"
1174 * rule of thumb, assuming we want the same size premaster
1175 * secret with Diffie-Hellman and RSA key exchanges. Except
1176 * that exportable ciphers max out at 512 bits modulus values.
1177 */
1178 dh = new DHCrypt((export ? 512 : 768), sslContext.getSecureRandom());
1179 }
1180
1181 // Setup the ephemeral ECDH parameters.
1182 // If we cannot continue because we do not support any of the curves that
1183 // the client requested, return false. Otherwise (all is well), return true.
1184 private boolean setupEphemeralECDHKeys() {
1185 int index = -1;
1186 if (supportedCurves != null) {
1187 // if the client sent the supported curves extension, pick the
1188 // first one that we support;
1189 for (int curveId : supportedCurves.curveIds()) {
1190 if (SupportedEllipticCurvesExtension.isSupported(curveId)) {
1191 index = curveId;
1192 break;
1193 }
1194 }
1195 if (index < 0) {
1196 // no match found, cannot use this ciphersuite
1197 return false;
1198 }
1199 } else {
1200 // pick our preference
1201 index = SupportedEllipticCurvesExtension.DEFAULT.curveIds()[0];
1202 }
1203 String oid = SupportedEllipticCurvesExtension.getCurveOid(index);
1204 ecdh = new ECDHCrypt(oid, sslContext.getSecureRandom());
1205 return true;
1206 }
1207
1208 private void setupStaticECDHKeys() {
1209 // don't need to check whether the curve is supported, already done
1210 // in setupPrivateKeyAndChain().
1211 ecdh = new ECDHCrypt(privateKey, certs[0].getPublicKey());
1212 }
1213
1214 /**
1215 * Retrieve the server key and certificate for the specified algorithm
1216 * from the KeyManager and set the instance variables.
1217 *
1218 * @return true if successful, false if not available or invalid
1219 */
1220 private boolean setupPrivateKeyAndChain(String algorithm) {
1221 X509ExtendedKeyManager km = sslContext.getX509KeyManager();
1222 String alias;
1223 if (conn != null) {
1224 alias = km.chooseServerAlias(algorithm, null, conn);
1225 } else {
1226 alias = km.chooseEngineServerAlias(algorithm, null, engine);
1227 }
1228 if (alias == null) {
1229 return false;
1230 }
1231 PrivateKey tempPrivateKey = km.getPrivateKey(alias);
1232 if (tempPrivateKey == null) {
1233 return false;
1234 }
1235 X509Certificate[] tempCerts = km.getCertificateChain(alias);
1236 if ((tempCerts == null) || (tempCerts.length == 0)) {
1237 return false;
1238 }
1239 String keyAlgorithm = algorithm.split("_")[0];
1240 PublicKey publicKey = tempCerts[0].getPublicKey();
1241 if ((tempPrivateKey.getAlgorithm().equals(keyAlgorithm) == false)
1242 || (publicKey.getAlgorithm().equals(keyAlgorithm) == false)) {
1243 return false;
1244 }
1245 // For ECC certs, check whether we support the EC domain parameters.
1246 // If the client sent a SupportedEllipticCurves ClientHello extension,
1247 // check against that too.
1248 if (keyAlgorithm.equals("EC")) {
1249 if (publicKey instanceof ECPublicKey == false) {
1250 return false;
1251 }
1252 ECParameterSpec params = ((ECPublicKey)publicKey).getParams();
1253 int index = SupportedEllipticCurvesExtension.getCurveIndex(params);
1254 if (SupportedEllipticCurvesExtension.isSupported(index) == false) {
1255 return false;
1256 }
1257 if ((supportedCurves != null) && !supportedCurves.contains(index)) {
1258 return false;
1259 }
1260 }
1261 this.privateKey = tempPrivateKey;
1262 this.certs = tempCerts;
1263 return true;
1264 }
1265
1266 /**
1267 * Retrieve the Kerberos key for the specified server principal
1268 * from the JAAS configuration file.
1269 *
1270 * @return true if successful, false if not available or invalid
1271 */
1272 private boolean setupKerberosKeys() {
1273 if (kerberosKeys != null) {
1274 return true;
1275 }
1276 try {
1277 final AccessControlContext acc = getAccSE();
1278 kerberosKeys = AccessController.doPrivileged(
1279 // Eliminate dependency on KerberosKey
1280 new PrivilegedExceptionAction<SecretKey[]>() {
1281 public SecretKey[] run() throws Exception {
1282 // get kerberos key for the default principal
1283 return Krb5Helper.getServerKeys(acc);
1284 }});
1285
1286 // check permission to access and use the secret key of the
1287 // Kerberized "host" service
1288 if (kerberosKeys != null && kerberosKeys.length > 0) {
1289 if (debug != null && Debug.isOn("handshake")) {
1290 for (SecretKey k: kerberosKeys) {
1291 System.out.println("Using Kerberos key: " +
1292 k);
1293 }
1294 }
1295
1296 String serverPrincipal =
1297 Krb5Helper.getServerPrincipalName(kerberosKeys[0]);
1298 SecurityManager sm = System.getSecurityManager();
1299 try {
1300 if (sm != null) {
1301 // Eliminate dependency on ServicePermission
1302 sm.checkPermission(Krb5Helper.getServicePermission(
1303 serverPrincipal, "accept"), acc);
1304 }
1305 } catch (SecurityException se) {
1306 kerberosKeys = null;
1307 // %%% destroy keys? or will that affect Subject?
1308 if (debug != null && Debug.isOn("handshake"))
1309 System.out.println("Permission to access Kerberos"
1310 + " secret key denied");
1311 return false;
1312 }
1313 }
1314 return (kerberosKeys != null);
1315 } catch (PrivilegedActionException e) {
1316 // Likely exception here is LoginExceptin
1317 if (debug != null && Debug.isOn("handshake")) {
1318 System.out.println("Attempt to obtain Kerberos key failed: "
1319 + e.toString());
1320 }
1321 return false;
1322 }
1323 }
1324
1325 /*
1326 * For Kerberos ciphers, the premaster secret is encrypted using
1327 * the session key. See RFC 2712.
1328 */
1329 private SecretKey clientKeyExchange(KerberosClientKeyExchange mesg)
1330 throws IOException {
1331
1332 if (debug != null && Debug.isOn("handshake")) {
1333 mesg.print(System.out);
1334 }
1335
1336 // Record the principals involved in exchange
1337 session.setPeerPrincipal(mesg.getPeerPrincipal());
1338 session.setLocalPrincipal(mesg.getLocalPrincipal());
1339
1340 byte[] b = mesg.getUnencryptedPreMasterSecret();
1341 return new SecretKeySpec(b, "TlsPremasterSecret");
1342 }
1343
1344 /*
1345 * Diffie Hellman key exchange is used when the server presented
1346 * D-H parameters in its certificate (signed using RSA or DSS/DSA),
1347 * or else the server presented no certificate but sent D-H params
1348 * in a ServerKeyExchange message. Use of D-H is specified by the
1349 * cipher suite chosen.
1350 *
1351 * The message optionally contains the client's D-H public key (if
1352 * it wasn't not sent in a client certificate). As always with D-H,
1353 * if a client and a server have each other's D-H public keys and
1354 * they use common algorithm parameters, they have a shared key
1355 * that's derived via the D-H calculation. That key becomes the
1356 * pre-master secret.
1357 */
1358 private SecretKey clientKeyExchange(DHClientKeyExchange mesg)
1359 throws IOException {
1360
1361 if (debug != null && Debug.isOn("handshake")) {
1362 mesg.print(System.out);
1363 }
1364 return dh.getAgreedSecret(mesg.getClientPublicKey());
1365 }
1366
1367 private SecretKey clientKeyExchange(ECDHClientKeyExchange mesg)
1368 throws IOException {
1369
1370 if (debug != null && Debug.isOn("handshake")) {
1371 mesg.print(System.out);
1372 }
1373 return ecdh.getAgreedSecret(mesg.getEncodedPoint());
1374 }
1375
1376 /*
1377 * Client wrote a message to verify the certificate it sent earlier.
1378 *
1379 * Note that this certificate isn't involved in key exchange. Client
1380 * authentication messages are included in the checksums used to
1381 * validate the handshake (e.g. Finished messages). Other than that,
1382 * the _exact_ identity of the client is less fundamental to protocol
1383 * security than its role in selecting keys via the pre-master secret.
1384 */
1385 private void clientCertificateVerify(CertificateVerify mesg)
1386 throws IOException {
1387
1388 if (debug != null && Debug.isOn("handshake")) {
1389 mesg.print(System.out);
1390 }
1391
1392 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1393 SignatureAndHashAlgorithm signAlg =
1394 mesg.getPreferableSignatureAlgorithm();
1395 if (signAlg == null) {
1396 throw new SSLHandshakeException(
1397 "Illegal CertificateVerify message");
1398 }
1399
1400 String hashAlg =
1401 SignatureAndHashAlgorithm.getHashAlgorithmName(signAlg);
1402 if (hashAlg == null || hashAlg.length() == 0) {
1403 throw new SSLHandshakeException(
1404 "No supported hash algorithm");
1405 }
1406
1407 handshakeHash.setCertificateVerifyAlg(hashAlg);
1408 }
1409
1410 try {
1411 PublicKey publicKey =
1412 session.getPeerCertificates()[0].getPublicKey();
1413
1414 boolean valid = mesg.verify(protocolVersion, handshakeHash,
1415 publicKey, session.getMasterSecret());
1416 if (valid == false) {
1417 fatalSE(Alerts.alert_bad_certificate,
1418 "certificate verify message signature error");
1419 }
1420 } catch (GeneralSecurityException e) {
1421 fatalSE(Alerts.alert_bad_certificate,
1422 "certificate verify format error", e);
1423 }
1424
1425 // reset the flag for clientCertificateVerify message
1426 needClientVerify = false;
1427 }
1428
1429
1430 /*
1431 * Client writes "finished" at the end of its handshake, after cipher
1432 * spec is changed. We verify it and then send ours.
1433 *
1434 * When we're resuming a session, we'll have already sent our own
1435 * Finished message so just the verification is needed.
1436 */
1437 private void clientFinished(Finished mesg) throws IOException {
1438 if (debug != null && Debug.isOn("handshake")) {
1439 mesg.print(System.out);
1440 }
1441
1442 /*
1443 * Verify if client did send the certificate when client
1444 * authentication was required, otherwise server should not proceed
1445 */
1446 if (doClientAuth == SSLEngineImpl.clauth_required) {
1447 // get X500Principal of the end-entity certificate for X509-based
1448 // ciphersuites, or Kerberos principal for Kerberos ciphersuites
1449 session.getPeerPrincipal();
1450 }
1451
1452 /*
1453 * Verify if client did send clientCertificateVerify message following
1454 * the client Certificate, otherwise server should not proceed
1455 */
1456 if (needClientVerify) {
1457 fatalSE(Alerts.alert_handshake_failure,
1458 "client did not send certificate verify message");
1459 }
1460
1461 /*
1462 * Verify the client's message with the "before" digest of messages,
1463 * and forget about continuing to use that digest.
1464 */
1465 boolean verified = mesg.verify(handshakeHash, Finished.CLIENT,
1466 session.getMasterSecret());
1467
1468 if (!verified) {
1469 fatalSE(Alerts.alert_handshake_failure,
1470 "client 'finished' message doesn't verify");
1471 // NOTREACHED
1472 }
1473
1474 /*
1475 * save client verify data for secure renegotiation
1476 */
1477 if (secureRenegotiation) {
1478 clientVerifyData = mesg.getVerifyData();
1479 }
1480
1481 /*
1482 * OK, it verified. If we're doing the full handshake, add that
1483 * "Finished" message to the hash of handshake messages, then send
1484 * the change_cipher_spec and Finished message.
1485 */
1486 if (!resumingSession) {
1487 input.digestNow();
1488 sendChangeCipherAndFinish(true);
1489 }
1490
1491 /*
1492 * Update the session cache only after the handshake completed, else
1493 * we're open to an attack against a partially completed handshake.
1494 */
1495 session.setLastAccessedTime(System.currentTimeMillis());
1496 if (!resumingSession && session.isRejoinable()) {
1497 ((SSLSessionContextImpl)sslContext.engineGetServerSessionContext())
1498 .put(session);
1499 if (debug != null && Debug.isOn("session")) {
1500 System.out.println(
1501 "%% Cached server session: " + session);
1502 }
1503 } else if (!resumingSession &&
1504 debug != null && Debug.isOn("session")) {
1505 System.out.println(
1506 "%% Didn't cache non-resumable server session: "
1507 + session);
1508 }
1509 }
1510
1511 /*
1512 * Compute finished message with the "server" digest (and then forget
1513 * about that digest, it can't be used again).
1514 */
1515 private void sendChangeCipherAndFinish(boolean finishedTag)
1516 throws IOException {
1517
1518 output.flush();
1519
1520 Finished mesg = new Finished(protocolVersion, handshakeHash,
1521 Finished.SERVER, session.getMasterSecret(), cipherSuite);
1522
1523 /*
1524 * Send the change_cipher_spec record; then our Finished handshake
1525 * message will be the last handshake message. Flush, and now we
1526 * are ready for application data!!
1527 */
1528 sendChangeCipherSpec(mesg, finishedTag);
1529
1530 /*
1531 * save server verify data for secure renegotiation
1532 */
1533 if (secureRenegotiation) {
1534 serverVerifyData = mesg.getVerifyData();
1535 }
1536
1537 /*
1538 * Update state machine so client MUST send 'finished' next
1539 * The update should only take place if it is not in the fast
1540 * handshake mode since the server has to wait for a finished
1541 * message from the client.
1542 */
1543 if (finishedTag) {
1544 state = HandshakeMessage.ht_finished;
1545 }
1546 }
1547
1548
1549 /*
1550 * Returns a HelloRequest message to kickstart renegotiations
1551 */
1552 HandshakeMessage getKickstartMessage() {
1553 return new HelloRequest();
1554 }
1555
1556
1557 /*
1558 * Fault detected during handshake.
1559 */
1560 void handshakeAlert(byte description) throws SSLProtocolException {
1561
1562 String message = Alerts.alertDescription(description);
1563
1564 if (debug != null && Debug.isOn("handshake")) {
1565 System.out.println("SSL -- handshake alert: "
1566 + message);
1567 }
1568
1569 /*
1570 * It's ok to get a no_certificate alert from a client of which
1571 * we *requested* authentication information.
1572 * However, if we *required* it, then this is not acceptable.
1573 *
1574 * Anyone calling getPeerCertificates() on the
1575 * session will get an SSLPeerUnverifiedException.
1576 */
1577 if ((description == Alerts.alert_no_certificate) &&
1578 (doClientAuth == SSLEngineImpl.clauth_requested)) {
1579 return;
1580 }
1581
1582 throw new SSLProtocolException("handshake alert: " + message);
1583 }
1584
1585 /*
1586 * RSA key exchange is normally used. The client encrypts a "pre-master
1587 * secret" with the server's public key, from the Certificate (or else
1588 * ServerKeyExchange) message that was sent to it by the server. That's
1589 * decrypted using the private key before we get here.
1590 */
1591 private SecretKey clientKeyExchange(RSAClientKeyExchange mesg)
1592 throws IOException {
1593
1594 if (debug != null && Debug.isOn("handshake")) {
1595 mesg.print(System.out);
1596 }
1597 return mesg.preMaster;
1598 }
1599
1600 /*
1601 * Verify the certificate sent by the client. We'll only get one if we
1602 * sent a CertificateRequest to request client authentication. If we
1603 * are in TLS mode, the client may send a message with no certificates
1604 * to indicate it does not have an appropriate chain. (In SSLv3 mode,
1605 * it would send a no certificate alert).
1606 */
1607 private void clientCertificate(CertificateMsg mesg) throws IOException {
1608 if (debug != null && Debug.isOn("handshake")) {
1609 mesg.print(System.out);
1610 }
1611
1612 X509Certificate[] peerCerts = mesg.getCertificateChain();
1613
1614 if (peerCerts.length == 0) {
1615 /*
1616 * If the client authentication is only *REQUESTED* (e.g.
1617 * not *REQUIRED*, this is an acceptable condition.)
1618 */
1619 if (doClientAuth == SSLEngineImpl.clauth_requested) {
1620 // Smart (aka stupid) to forecast that no CertificateVerify
1621 // message will be received.
1622 if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
1623 handshakeHash.setCertificateVerifyAlg(null);
1624 }
1625 return;
1626 } else {
1627 fatalSE(Alerts.alert_bad_certificate,
1628 "null cert chain");
1629 }
1630 }
1631
1632 // ask the trust manager to verify the chain
1633 X509TrustManager tm = sslContext.getX509TrustManager();
1634
1635 try {
1636 // find out the types of client authentication used
1637 PublicKey key = peerCerts[0].getPublicKey();
1638 String keyAlgorithm = key.getAlgorithm();
1639 String authType;
1640 if (keyAlgorithm.equals("RSA")) {
1641 authType = "RSA";
1642 } else if (keyAlgorithm.equals("DSA")) {
1643 authType = "DSA";
1644 } else if (keyAlgorithm.equals("EC")) {
1645 authType = "EC";
1646 } else {
1647 // unknown public key type
1648 authType = "UNKNOWN";
1649 }
1650
1651 if (tm instanceof X509ExtendedTrustManager) {
1652 if (conn != null) {
1653 ((X509ExtendedTrustManager)tm).checkClientTrusted(
1654 peerCerts.clone(),
1655 authType,
1656 conn);
1657 } else {
1658 ((X509ExtendedTrustManager)tm).checkClientTrusted(
1659 peerCerts.clone(),
1660 authType,
1661 engine);
1662 }
1663 } else {
1664 // Unlikely to happen, because we have wrapped the old
1665 // X509TrustManager with the new X509ExtendedTrustManager.
1666 throw new CertificateException(
1667 "Improper X509TrustManager implementation");
1668 }
1669 } catch (CertificateException e) {
1670 // This will throw an exception, so include the original error.
1671 fatalSE(Alerts.alert_certificate_unknown, e);
1672 }
1673 // set the flag for clientCertificateVerify message
1674 needClientVerify = true;
1675
1676 session.setPeerCertificates(peerCerts);
1677 }
1678}