1 /* 2 * Copyright (c) 2015, 2019, 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.IOException; 29 import java.nio.ByteBuffer; 30 import java.security.SecureRandom; 31 import java.security.cert.X509Certificate; 32 import java.text.MessageFormat; 33 import java.util.Arrays; 34 import java.util.Collections; 35 import java.util.LinkedList; 36 import java.util.List; 37 import java.util.Locale; 38 import java.util.Objects; 39 import javax.net.ssl.SSLException; 40 import javax.net.ssl.SSLHandshakeException; 41 import javax.net.ssl.SSLPeerUnverifiedException; 42 import javax.net.ssl.SSLProtocolException; 43 import static sun.security.ssl.ClientAuthType.CLIENT_AUTH_REQUIRED; 44 import sun.security.ssl.SSLHandshake.HandshakeMessage; 45 import sun.security.ssl.SupportedVersionsExtension.CHSupportedVersionsSpec; 46 47 /** 48 * Pack of the ClientHello handshake message. 49 */ 50 final class ClientHello { 51 static final SSLProducer kickstartProducer = 52 new ClientHelloKickstartProducer(); 53 static final SSLConsumer handshakeConsumer = 54 new ClientHelloConsumer(); 55 static final HandshakeProducer handshakeProducer = 56 new ClientHelloProducer(); 57 58 private static final HandshakeConsumer t12HandshakeConsumer = 59 new T12ClientHelloConsumer(); 60 private static final HandshakeConsumer t13HandshakeConsumer = 61 new T13ClientHelloConsumer(); 62 private static final HandshakeConsumer d12HandshakeConsumer = 63 new D12ClientHelloConsumer(); 64 private static final HandshakeConsumer d13HandshakeConsumer = 65 new D13ClientHelloConsumer(); 66 67 /** 68 * The ClientHello handshake message. 69 * 70 * See RFC 5264/4346/2246/6347 for the specifications. 71 */ 72 static final class ClientHelloMessage extends HandshakeMessage { 73 private final boolean isDTLS; 74 75 final int clientVersion; 76 final RandomCookie clientRandom; 77 final SessionId sessionId; 78 private byte[] cookie; // DTLS only 79 final int[] cipherSuiteIds; 80 final List<CipherSuite> cipherSuites; // known cipher suites only 81 final byte[] compressionMethod; 82 final SSLExtensions extensions; 83 84 private static final byte[] NULL_COMPRESSION = new byte[] {0}; 85 86 ClientHelloMessage(HandshakeContext handshakeContext, 87 int clientVersion, SessionId sessionId, 88 List<CipherSuite> cipherSuites, SecureRandom generator) { 89 super(handshakeContext); 90 this.isDTLS = handshakeContext.sslContext.isDTLS(); 91 92 this.clientVersion = clientVersion; 93 this.clientRandom = new RandomCookie(generator); 94 this.sessionId = sessionId; 95 if (isDTLS) { 96 this.cookie = new byte[0]; 97 } else { 98 this.cookie = null; 99 } 100 101 this.cipherSuites = cipherSuites; 102 this.cipherSuiteIds = getCipherSuiteIds(cipherSuites); 103 this.extensions = new SSLExtensions(this); 104 105 // Don't support compression. 106 this.compressionMethod = NULL_COMPRESSION; 107 } 108 109 /* Read up to the binders in the PSK extension. After this method 110 * returns, the ByteBuffer position will be at end of the message 111 * fragment that should be hashed to produce the PSK binder values. 112 * The client of this method can use this position to determine the 113 * message fragment and produce the binder values. 114 */ 115 static void readPartial(TransportContext tc, 116 ByteBuffer m) throws IOException { 117 boolean isDTLS = tc.sslContext.isDTLS(); 118 119 // version 120 Record.getInt16(m); 121 122 new RandomCookie(m); 123 124 // session ID 125 Record.getBytes8(m); 126 127 // DTLS cookie 128 if (isDTLS) { 129 Record.getBytes8(m); 130 } 131 132 // cipher suite IDs 133 Record.getBytes16(m); 134 // compression method 135 Record.getBytes8(m); 136 // read extensions, if present 137 if (m.remaining() >= 2) { 138 int remaining = Record.getInt16(m); 139 while (remaining > 0) { 140 int id = Record.getInt16(m); 141 int extLen = Record.getInt16(m); 142 remaining -= extLen + 4; 143 144 if (id == SSLExtension.CH_PRE_SHARED_KEY.id) { 145 // ensure pre_shared_key is the last extension 146 if (remaining > 0) { 147 throw tc.fatal(Alert.ILLEGAL_PARAMETER, 148 "pre_shared_key extension is not last"); 149 } 150 // read only up to the IDs 151 Record.getBytes16(m); 152 return; 153 } else { 154 m.position(m.position() + extLen); 155 156 } 157 } 158 } // Otherwise, ignore the remaining bytes. 159 } 160 161 ClientHelloMessage(HandshakeContext handshakeContext, ByteBuffer m, 162 SSLExtension[] supportedExtensions) throws IOException { 163 super(handshakeContext); 164 this.isDTLS = handshakeContext.sslContext.isDTLS(); 165 166 this.clientVersion = ((m.get() & 0xFF) << 8) | (m.get() & 0xFF); 167 this.clientRandom = new RandomCookie(m); 168 this.sessionId = new SessionId(Record.getBytes8(m)); 169 try { 170 sessionId.checkLength(clientVersion); 171 } catch (SSLProtocolException ex) { 172 throw handshakeContext.conContext.fatal( 173 Alert.ILLEGAL_PARAMETER, ex); 174 } 175 if (isDTLS) { 176 this.cookie = Record.getBytes8(m); 177 } else { 178 this.cookie = null; 179 } 180 181 byte[] encodedIds = Record.getBytes16(m); 182 if (encodedIds.length == 0 || (encodedIds.length & 0x01) != 0) { 183 throw handshakeContext.conContext.fatal( 184 Alert.ILLEGAL_PARAMETER, 185 "Invalid ClientHello message"); 186 } 187 188 this.cipherSuiteIds = new int[encodedIds.length >> 1]; 189 for (int i = 0, j = 0; i < encodedIds.length; i++, j++) { 190 cipherSuiteIds[j] = 191 ((encodedIds[i++] & 0xFF) << 8) | (encodedIds[i] & 0xFF); 192 } 193 this.cipherSuites = getCipherSuites(cipherSuiteIds); 194 195 this.compressionMethod = Record.getBytes8(m); 196 // In TLS 1.3, use of certain extensions is mandatory. 197 if (m.hasRemaining()) { 198 this.extensions = 199 new SSLExtensions(this, m, supportedExtensions); 200 } else { 201 this.extensions = new SSLExtensions(this); 202 } 203 } 204 205 void setHelloCookie(byte[] cookie) { 206 this.cookie = cookie; 207 } 208 209 // DTLS 1.0/1.2, for cookie generation. 210 byte[] getHelloCookieBytes() { 211 HandshakeOutStream hos = new HandshakeOutStream(null); 212 try { 213 // copied from send() method 214 hos.putInt8((byte)((clientVersion >>> 8) & 0xFF)); 215 hos.putInt8((byte)(clientVersion & 0xFF)); 216 hos.write(clientRandom.randomBytes, 0, 32); 217 hos.putBytes8(sessionId.getId()); 218 // ignore cookie 219 hos.putBytes16(getEncodedCipherSuites()); 220 hos.putBytes8(compressionMethod); 221 extensions.send(hos); // In TLS 1.3, use of certain 222 // extensions is mandatory. 223 } catch (IOException ioe) { 224 // unlikely 225 } 226 227 return hos.toByteArray(); 228 } 229 230 // (D)TLS 1.3, for cookie generation. 231 byte[] getHeaderBytes() { 232 HandshakeOutStream hos = new HandshakeOutStream(null); 233 try { 234 // copied from send() method 235 hos.putInt8((byte)((clientVersion >>> 8) & 0xFF)); 236 hos.putInt8((byte)(clientVersion & 0xFF)); 237 hos.write(clientRandom.randomBytes, 0, 32); 238 hos.putBytes8(sessionId.getId()); 239 hos.putBytes16(getEncodedCipherSuites()); 240 hos.putBytes8(compressionMethod); 241 } catch (IOException ioe) { 242 // unlikely 243 } 244 245 return hos.toByteArray(); 246 } 247 248 private static int[] getCipherSuiteIds( 249 List<CipherSuite> cipherSuites) { 250 if (cipherSuites != null) { 251 int[] ids = new int[cipherSuites.size()]; 252 int i = 0; 253 for (CipherSuite cipherSuite : cipherSuites) { 254 ids[i++] = cipherSuite.id; 255 } 256 257 return ids; 258 } 259 260 return new int[0]; 261 } 262 263 private static List<CipherSuite> getCipherSuites(int[] ids) { 264 List<CipherSuite> cipherSuites = new LinkedList<>(); 265 for (int id : ids) { 266 CipherSuite cipherSuite = CipherSuite.valueOf(id); 267 if (cipherSuite != null) { 268 cipherSuites.add(cipherSuite); 269 } 270 } 271 272 return Collections.unmodifiableList(cipherSuites); 273 } 274 275 private List<String> getCipherSuiteNames() { 276 List<String> names = new LinkedList<>(); 277 for (int id : cipherSuiteIds) { 278 names.add(CipherSuite.nameOf(id) + 279 "(" + Utilities.byte16HexString(id) + ")"); } 280 281 return names; 282 } 283 284 private byte[] getEncodedCipherSuites() { 285 byte[] encoded = new byte[cipherSuiteIds.length << 1]; 286 int i = 0; 287 for (int id : cipherSuiteIds) { 288 encoded[i++] = (byte)(id >> 8); 289 encoded[i++] = (byte)id; 290 } 291 return encoded; 292 } 293 294 @Override 295 public SSLHandshake handshakeType() { 296 return SSLHandshake.CLIENT_HELLO; 297 } 298 299 @Override 300 public int messageLength() { 301 /* 302 * Add fixed size parts of each field... 303 * version + random + session + cipher + compress 304 */ 305 return (2 + 32 + 1 + 2 + 1 306 + sessionId.length() /* ... + variable parts */ 307 + (isDTLS ? (1 + cookie.length) : 0) 308 + (cipherSuiteIds.length * 2) 309 + compressionMethod.length) 310 + extensions.length(); // In TLS 1.3, use of certain 311 // extensions is mandatory. 312 } 313 314 @Override 315 public void send(HandshakeOutStream hos) throws IOException { 316 sendCore(hos); 317 extensions.send(hos); // In TLS 1.3, use of certain 318 // extensions is mandatory. 319 } 320 321 void sendCore(HandshakeOutStream hos) throws IOException { 322 hos.putInt8((byte) (clientVersion >>> 8)); 323 hos.putInt8((byte) clientVersion); 324 hos.write(clientRandom.randomBytes, 0, 32); 325 hos.putBytes8(sessionId.getId()); 326 if (isDTLS) { 327 hos.putBytes8(cookie); 328 } 329 hos.putBytes16(getEncodedCipherSuites()); 330 hos.putBytes8(compressionMethod); 331 } 332 333 @Override 334 public String toString() { 335 if (isDTLS) { 336 MessageFormat messageFormat = new MessageFormat( 337 "\"ClientHello\": '{'\n" + 338 " \"client version\" : \"{0}\",\n" + 339 " \"random\" : \"{1}\",\n" + 340 " \"session id\" : \"{2}\",\n" + 341 " \"cookie\" : \"{3}\",\n" + 342 " \"cipher suites\" : \"{4}\",\n" + 343 " \"compression methods\" : \"{5}\",\n" + 344 " \"extensions\" : [\n" + 345 "{6}\n" + 346 " ]\n" + 347 "'}'", 348 Locale.ENGLISH); 349 Object[] messageFields = { 350 ProtocolVersion.nameOf(clientVersion), 351 Utilities.toHexString(clientRandom.randomBytes), 352 sessionId.toString(), 353 Utilities.toHexString(cookie), 354 getCipherSuiteNames().toString(), 355 Utilities.toHexString(compressionMethod), 356 Utilities.indent(Utilities.indent(extensions.toString())) 357 }; 358 359 return messageFormat.format(messageFields); 360 } else { 361 MessageFormat messageFormat = new MessageFormat( 362 "\"ClientHello\": '{'\n" + 363 " \"client version\" : \"{0}\",\n" + 364 " \"random\" : \"{1}\",\n" + 365 " \"session id\" : \"{2}\",\n" + 366 " \"cipher suites\" : \"{3}\",\n" + 367 " \"compression methods\" : \"{4}\",\n" + 368 " \"extensions\" : [\n" + 369 "{5}\n" + 370 " ]\n" + 371 "'}'", 372 Locale.ENGLISH); 373 Object[] messageFields = { 374 ProtocolVersion.nameOf(clientVersion), 375 Utilities.toHexString(clientRandom.randomBytes), 376 sessionId.toString(), 377 getCipherSuiteNames().toString(), 378 Utilities.toHexString(compressionMethod), 379 Utilities.indent(Utilities.indent(extensions.toString())) 380 }; 381 382 return messageFormat.format(messageFields); 383 } 384 } 385 } 386 387 /** 388 * The "ClientHello" handshake message kick start producer. 389 */ 390 private static final 391 class ClientHelloKickstartProducer implements SSLProducer { 392 // Prevent instantiation of this class. 393 private ClientHelloKickstartProducer() { 394 // blank 395 } 396 397 // Produce kickstart handshake message. 398 @Override 399 public byte[] produce(ConnectionContext context) throws IOException { 400 // The producing happens in client side only. 401 ClientHandshakeContext chc = (ClientHandshakeContext)context; 402 403 // clean up this producer 404 chc.handshakeProducers.remove(SSLHandshake.CLIENT_HELLO.id); 405 406 // the max protocol version this client is supporting. 407 ProtocolVersion maxProtocolVersion = chc.maximumActiveProtocol; 408 409 // session ID of the ClientHello message 410 SessionId sessionId = SSLSessionImpl.nullSession.getSessionId(); 411 412 // a list of cipher suites sent by the client 413 List<CipherSuite> cipherSuites = chc.activeCipherSuites; 414 415 // 416 // Try to resume an existing session. 417 // 418 SSLSessionContextImpl ssci = (SSLSessionContextImpl) 419 chc.sslContext.engineGetClientSessionContext(); 420 SSLSessionImpl session = ssci.get( 421 chc.conContext.transport.getPeerHost(), 422 chc.conContext.transport.getPeerPort()); 423 if (session != null) { 424 // If unsafe server certificate change is not allowed, reserve 425 // current server certificates if the previous handshake is a 426 // session-resumption abbreviated initial handshake. 427 if (!ClientHandshakeContext.allowUnsafeServerCertChange && 428 session.isSessionResumption()) { 429 try { 430 // If existing, peer certificate chain cannot be null. 431 chc.reservedServerCerts = 432 (X509Certificate[])session.getPeerCertificates(); 433 } catch (SSLPeerUnverifiedException puve) { 434 // Maybe not certificate-based, ignore the exception. 435 } 436 } 437 438 if (!session.isRejoinable()) { 439 session = null; 440 if (SSLLogger.isOn && 441 SSLLogger.isOn("ssl,handshake,verbose")) { 442 SSLLogger.finest( 443 "Can't resume, the session is not rejoinable"); 444 } 445 } 446 } 447 448 CipherSuite sessionSuite = null; 449 if (session != null) { 450 sessionSuite = session.getSuite(); 451 if (!chc.isNegotiable(sessionSuite)) { 452 session = null; 453 if (SSLLogger.isOn && 454 SSLLogger.isOn("ssl,handshake,verbose")) { 455 SSLLogger.finest( 456 "Can't resume, unavailable session cipher suite"); 457 } 458 } 459 } 460 461 ProtocolVersion sessionVersion = null; 462 if (session != null) { 463 sessionVersion = session.getProtocolVersion(); 464 if (!chc.isNegotiable(sessionVersion)) { 465 session = null; 466 if (SSLLogger.isOn && 467 SSLLogger.isOn("ssl,handshake,verbose")) { 468 SSLLogger.finest( 469 "Can't resume, unavailable protocol version"); 470 } 471 } 472 } 473 474 if (session != null && 475 !sessionVersion.useTLS13PlusSpec() && 476 SSLConfiguration.useExtendedMasterSecret) { 477 478 boolean isEmsAvailable = chc.sslConfig.isAvailable( 479 SSLExtension.CH_EXTENDED_MASTER_SECRET, sessionVersion); 480 if (isEmsAvailable && !session.useExtendedMasterSecret && 481 !SSLConfiguration.allowLegacyResumption) { 482 // perform full handshake instead 483 // 484 // The client SHOULD NOT offer an abbreviated handshake 485 // to resume a session that does not use an extended 486 // master secret. Instead, it SHOULD offer a full 487 // handshake. 488 session = null; 489 } 490 491 if ((session != null) && 492 !ClientHandshakeContext.allowUnsafeServerCertChange) { 493 // It is fine to move on with abbreviate handshake if 494 // endpoint identification is enabled. 495 String identityAlg = chc.sslConfig.identificationProtocol; 496 if (identityAlg == null || identityAlg.isEmpty()) { 497 if (isEmsAvailable) { 498 if (!session.useExtendedMasterSecret) { 499 // perform full handshake instead 500 session = null; 501 } // Otherwise, use extended master secret. 502 } else { 503 // The extended master secret extension does not 504 // apply to SSL 3.0. Perform a full handshake 505 // instead. 506 // 507 // Note that the useExtendedMasterSecret is 508 // extended to protect SSL 3.0 connections, 509 // by discarding abbreviate handshake. 510 session = null; 511 } 512 } 513 } 514 } 515 516 // ensure that the endpoint identification algorithm matches the 517 // one in the session 518 String identityAlg = chc.sslConfig.identificationProtocol; 519 if (session != null && identityAlg != null) { 520 String sessionIdentityAlg = 521 session.getIdentificationProtocol(); 522 if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { 523 if (SSLLogger.isOn && 524 SSLLogger.isOn("ssl,handshake,verbose")) { 525 SSLLogger.finest("Can't resume, endpoint id" + 526 " algorithm does not match, requested: " + 527 identityAlg + ", cached: " + sessionIdentityAlg); 528 } 529 session = null; 530 } 531 } 532 533 if (session != null) { 534 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake,verbose")) { 535 SSLLogger.finest("Try resuming session", session); 536 } 537 538 // only set session id if session is 1.2 or earlier 539 if (!session.getProtocolVersion().useTLS13PlusSpec()) { 540 sessionId = session.getSessionId(); 541 } 542 if (!maxProtocolVersion.equals(sessionVersion)) { 543 maxProtocolVersion = sessionVersion; 544 545 // Update protocol version number in underlying socket and 546 // handshake output stream, so that the output records 547 // (at the record layer) have the correct version 548 chc.setVersion(sessionVersion); 549 } 550 551 // If no new session is allowed, force use of the previous 552 // session ciphersuite, and add the renegotiation SCSV if 553 // necessary. 554 if (!chc.sslConfig.enableSessionCreation) { 555 if (!chc.conContext.isNegotiated && 556 !sessionVersion.useTLS13PlusSpec() && 557 cipherSuites.contains( 558 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 559 cipherSuites = Arrays.asList(sessionSuite, 560 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV); 561 } else { // otherwise, use renegotiation_info extension 562 cipherSuites = Arrays.asList(sessionSuite); 563 } 564 565 if (SSLLogger.isOn && 566 SSLLogger.isOn("ssl,handshake,verbose")) { 567 SSLLogger.finest( 568 "No new session is allowed, so try to resume " + 569 "the session cipher suite only", sessionSuite); 570 } 571 } 572 573 chc.isResumption = true; 574 chc.resumingSession = session; 575 } 576 577 if (session == null) { 578 if (!chc.sslConfig.enableSessionCreation) { 579 throw new SSLHandshakeException( 580 "No new session is allowed and " + 581 "no existing session can be resumed"); 582 } 583 584 if (maxProtocolVersion.useTLS13PlusSpec() && 585 SSLConfiguration.useCompatibilityMode) { 586 // In compatibility mode, the TLS 1.3 legacy_session_id 587 // field MUST be non-empty, so a client not offering a 588 // pre-TLS 1.3 session MUST generate a new 32-byte value. 589 sessionId = 590 new SessionId(true, chc.sslContext.getSecureRandom()); 591 } 592 } 593 594 ProtocolVersion minimumVersion = ProtocolVersion.NONE; 595 for (ProtocolVersion pv : chc.activeProtocols) { 596 if (minimumVersion == ProtocolVersion.NONE || 597 pv.compare(minimumVersion) < 0) { 598 minimumVersion = pv; 599 } 600 } 601 602 // exclude SCSV for secure renegotiation 603 if (!minimumVersion.useTLS13PlusSpec()) { 604 if (chc.conContext.secureRenegotiation && 605 cipherSuites.contains( 606 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV)) { 607 // The cipherSuites may be unmodifiable 608 cipherSuites = new LinkedList<>(cipherSuites); 609 cipherSuites.remove( 610 CipherSuite.TLS_EMPTY_RENEGOTIATION_INFO_SCSV); 611 } 612 } 613 614 // make sure there is a negotiable cipher suite. 615 boolean negotiable = false; 616 for (CipherSuite suite : cipherSuites) { 617 if (chc.isNegotiable(suite)) { 618 negotiable = true; 619 break; 620 } 621 } 622 if (!negotiable) { 623 throw new SSLHandshakeException("No negotiable cipher suite"); 624 } 625 626 // Create the handshake message. 627 ProtocolVersion clientHelloVersion = maxProtocolVersion; 628 if (clientHelloVersion.useTLS13PlusSpec()) { 629 // In (D)TLS 1.3, the client indicates its version preferences 630 // in the "supported_versions" extension and the client_version 631 // (legacy_version) field MUST be set to (D)TLS 1.2. 632 if (clientHelloVersion.isDTLS) { 633 clientHelloVersion = ProtocolVersion.DTLS12; 634 } else { 635 clientHelloVersion = ProtocolVersion.TLS12; 636 } 637 } 638 639 ClientHelloMessage chm = new ClientHelloMessage(chc, 640 clientHelloVersion.id, sessionId, cipherSuites, 641 chc.sslContext.getSecureRandom()); 642 643 // cache the client random number for further using 644 chc.clientHelloRandom = chm.clientRandom; 645 chc.clientHelloVersion = clientHelloVersion.id; 646 647 // Produce extensions for ClientHello handshake message. 648 SSLExtension[] extTypes = chc.sslConfig.getEnabledExtensions( 649 SSLHandshake.CLIENT_HELLO, chc.activeProtocols); 650 chm.extensions.produce(chc, extTypes); 651 652 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 653 SSLLogger.fine("Produced ClientHello handshake message", chm); 654 } 655 656 // Output the handshake message. 657 chm.write(chc.handshakeOutput); 658 chc.handshakeOutput.flush(); 659 660 // Reserve the initial ClientHello message for the follow on 661 // cookie exchange if needed. 662 chc.initialClientHelloMsg = chm; 663 664 // What's the expected response? 665 chc.handshakeConsumers.put( 666 SSLHandshake.SERVER_HELLO.id, SSLHandshake.SERVER_HELLO); 667 if (chc.sslContext.isDTLS() && 668 !minimumVersion.useTLS13PlusSpec()) { 669 chc.handshakeConsumers.put( 670 SSLHandshake.HELLO_VERIFY_REQUEST.id, 671 SSLHandshake.HELLO_VERIFY_REQUEST); 672 } 673 674 // The handshake message has been delivered. 675 return null; 676 } 677 } 678 679 private static final 680 class ClientHelloProducer implements HandshakeProducer { 681 // Prevent instantiation of this class. 682 private ClientHelloProducer() { 683 // blank 684 } 685 686 // Response to one of the following handshake message: 687 // HelloRequest (SSL 3.0/TLS 1.0/1.1/1.2) 688 // ServerHello(HelloRetryRequest) (TLS 1.3) 689 // HelloVerifyRequest (DTLS 1.0/1.2) 690 @Override 691 public byte[] produce(ConnectionContext context, 692 HandshakeMessage message) throws IOException { 693 // The producing happens in client side only. 694 ClientHandshakeContext chc = (ClientHandshakeContext)context; 695 696 SSLHandshake ht = message.handshakeType(); 697 if (ht == null) { 698 throw new UnsupportedOperationException("Not supported yet."); 699 } 700 701 switch (ht) { 702 case HELLO_REQUEST: 703 // SSL 3.0/TLS 1.0/1.1/1.2 704 try { 705 chc.kickstart(); 706 } catch (IOException ioe) { 707 throw chc.conContext.fatal( 708 Alert.HANDSHAKE_FAILURE, ioe); 709 } 710 711 // The handshake message has been delivered. 712 return null; 713 case HELLO_VERIFY_REQUEST: 714 // DTLS 1.0/1.2 715 // 716 // The HelloVerifyRequest consumer should have updated the 717 // ClientHello handshake message with cookie. 718 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 719 SSLLogger.fine( 720 "Produced ClientHello(cookie) handshake message", 721 chc.initialClientHelloMsg); 722 } 723 724 // Output the handshake message. 725 chc.initialClientHelloMsg.write(chc.handshakeOutput); 726 chc.handshakeOutput.flush(); 727 728 // What's the expected response? 729 chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id, 730 SSLHandshake.SERVER_HELLO); 731 732 ProtocolVersion minimumVersion = ProtocolVersion.NONE; 733 for (ProtocolVersion pv : chc.activeProtocols) { 734 if (minimumVersion == ProtocolVersion.NONE || 735 pv.compare(minimumVersion) < 0) { 736 minimumVersion = pv; 737 } 738 } 739 if (chc.sslContext.isDTLS() && 740 !minimumVersion.useTLS13PlusSpec()) { 741 chc.handshakeConsumers.put( 742 SSLHandshake.HELLO_VERIFY_REQUEST.id, 743 SSLHandshake.HELLO_VERIFY_REQUEST); 744 } 745 746 // The handshake message has been delivered. 747 return null; 748 case HELLO_RETRY_REQUEST: 749 // TLS 1.3 750 // The HelloRetryRequest consumer should have updated the 751 // ClientHello handshake message with cookie. 752 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 753 SSLLogger.fine( 754 "Produced ClientHello(HRR) handshake message", 755 chc.initialClientHelloMsg); 756 } 757 758 // Output the handshake message. 759 chc.initialClientHelloMsg.write(chc.handshakeOutput); 760 chc.handshakeOutput.flush(); 761 762 // What's the expected response? 763 chc.conContext.consumers.putIfAbsent( 764 ContentType.CHANGE_CIPHER_SPEC.id, 765 ChangeCipherSpec.t13Consumer); 766 chc.handshakeConsumers.put(SSLHandshake.SERVER_HELLO.id, 767 SSLHandshake.SERVER_HELLO); 768 769 // The handshake message has been delivered. 770 return null; 771 default: 772 throw new UnsupportedOperationException( 773 "Not supported yet."); 774 } 775 } 776 } 777 778 /** 779 * The "ClientHello" handshake message consumer. 780 */ 781 private static final class ClientHelloConsumer implements SSLConsumer { 782 // Prevent instantiation of this class. 783 private ClientHelloConsumer() { 784 // blank 785 } 786 787 @Override 788 public void consume(ConnectionContext context, 789 ByteBuffer message) throws IOException { 790 // The consuming happens in server side only. 791 ServerHandshakeContext shc = (ServerHandshakeContext)context; 792 793 // clean up this consumer 794 shc.handshakeConsumers.remove(SSLHandshake.CLIENT_HELLO.id); 795 if (!shc.handshakeConsumers.isEmpty()) { 796 throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, 797 "No more handshake message allowed " + 798 "in a ClientHello flight"); 799 } 800 801 // Get enabled extension types in ClientHello handshake message. 802 SSLExtension[] enabledExtensions = 803 shc.sslConfig.getEnabledExtensions( 804 SSLHandshake.CLIENT_HELLO); 805 806 ClientHelloMessage chm = 807 new ClientHelloMessage(shc, message, enabledExtensions); 808 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 809 SSLLogger.fine("Consuming ClientHello handshake message", chm); 810 } 811 812 shc.clientHelloVersion = chm.clientVersion; 813 onClientHello(shc, chm); 814 } 815 816 private void onClientHello(ServerHandshakeContext context, 817 ClientHelloMessage clientHello) throws IOException { 818 // Negotiate protocol version. 819 // 820 // Check and launch SupportedVersions. 821 SSLExtension[] extTypes = new SSLExtension[] { 822 SSLExtension.CH_SUPPORTED_VERSIONS 823 }; 824 clientHello.extensions.consumeOnLoad(context, extTypes); 825 826 ProtocolVersion negotiatedProtocol; 827 CHSupportedVersionsSpec svs = 828 (CHSupportedVersionsSpec)context.handshakeExtensions.get( 829 SSLExtension.CH_SUPPORTED_VERSIONS); 830 if (svs != null) { 831 negotiatedProtocol = 832 negotiateProtocol(context, svs.requestedProtocols); 833 } else { 834 negotiatedProtocol = 835 negotiateProtocol(context, clientHello.clientVersion); 836 } 837 context.negotiatedProtocol = negotiatedProtocol; 838 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { 839 SSLLogger.fine( 840 "Negotiated protocol version: " + negotiatedProtocol.name); 841 } 842 843 // Consume the handshake message for the specific protocol version. 844 if (negotiatedProtocol.isDTLS) { 845 if (negotiatedProtocol.useTLS13PlusSpec()) { 846 d13HandshakeConsumer.consume(context, clientHello); 847 } else { 848 d12HandshakeConsumer.consume(context, clientHello); 849 } 850 } else { 851 if (negotiatedProtocol.useTLS13PlusSpec()) { 852 t13HandshakeConsumer.consume(context, clientHello); 853 } else { 854 t12HandshakeConsumer.consume(context, clientHello); 855 } 856 } 857 } 858 859 // Select a protocol version according to the 860 // ClientHello.client_version. 861 private ProtocolVersion negotiateProtocol( 862 ServerHandshakeContext context, 863 int clientHelloVersion) throws SSLException { 864 865 // Per TLS 1.3 specification, server MUST negotiate TLS 1.2 or prior 866 // even if ClientHello.client_version is 0x0304 or later. 867 int chv = clientHelloVersion; 868 if (context.sslContext.isDTLS()) { 869 if (chv < ProtocolVersion.DTLS12.id) { 870 chv = ProtocolVersion.DTLS12.id; 871 } 872 } else { 873 if (chv > ProtocolVersion.TLS12.id) { 874 chv = ProtocolVersion.TLS12.id; 875 } 876 } 877 878 // Select a protocol version from the activated protocols. 879 ProtocolVersion pv = ProtocolVersion.selectedFrom( 880 context.activeProtocols, chv); 881 if (pv == null || pv == ProtocolVersion.NONE || 882 pv == ProtocolVersion.SSL20Hello) { 883 throw context.conContext.fatal(Alert.PROTOCOL_VERSION, 884 "Client requested protocol " + 885 ProtocolVersion.nameOf(clientHelloVersion) + 886 " is not enabled or supported in server context"); 887 } 888 889 return pv; 890 } 891 892 // Select a protocol version according to the 893 // supported_versions extension. 894 private ProtocolVersion negotiateProtocol( 895 ServerHandshakeContext context, 896 int[] clientSupportedVersions) throws SSLException { 897 898 // The client supported protocol versions are present in client 899 // preference order. This implementation chooses to use the server 900 // preference of protocol versions instead. 901 for (ProtocolVersion spv : context.activeProtocols) { 902 if (spv == ProtocolVersion.SSL20Hello) { 903 continue; 904 } 905 for (int cpv : clientSupportedVersions) { 906 if (cpv == ProtocolVersion.SSL20Hello.id) { 907 continue; 908 } 909 if (spv.id == cpv) { 910 return spv; 911 } 912 } 913 } 914 915 // No protocol version can be negotiated. 916 throw context.conContext.fatal(Alert.PROTOCOL_VERSION, 917 "The client supported protocol versions " + Arrays.toString( 918 ProtocolVersion.toStringArray(clientSupportedVersions)) + 919 " are not accepted by server preferences " + 920 context.activeProtocols); 921 } 922 } 923 924 /** 925 * The "ClientHello" handshake message consumer for TLS 1.2 and 926 * prior SSL/TLS protocol versions. 927 */ 928 private static final 929 class T12ClientHelloConsumer implements HandshakeConsumer { 930 // Prevent instantiation of this class. 931 private T12ClientHelloConsumer() { 932 // blank 933 } 934 935 @Override 936 public void consume(ConnectionContext context, 937 HandshakeMessage message) throws IOException { 938 // The consuming happens in server side only. 939 ServerHandshakeContext shc = (ServerHandshakeContext)context; 940 ClientHelloMessage clientHello = (ClientHelloMessage)message; 941 942 // 943 // validate 944 // 945 946 // Reject client initiated renegotiation? 947 // 948 // If server side should reject client-initiated renegotiation, 949 // send an Alert.HANDSHAKE_FAILURE fatal alert, not a 950 // no_renegotiation warning alert (no_renegotiation must be a 951 // warning: RFC 2246). no_renegotiation might seem more 952 // natural at first, but warnings are not appropriate because 953 // the sending party does not know how the receiving party 954 // will behave. This state must be treated as a fatal server 955 // condition. 956 // 957 // This will not have any impact on server initiated renegotiation. 958 if (shc.conContext.isNegotiated) { 959 if (!shc.conContext.secureRenegotiation && 960 !HandshakeContext.allowUnsafeRenegotiation) { 961 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 962 "Unsafe renegotiation is not allowed"); 963 } 964 965 if (ServerHandshakeContext.rejectClientInitiatedRenego && 966 !shc.kickstartMessageDelivered) { 967 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 968 "Client initiated renegotiation is not allowed"); 969 } 970 } 971 972 // Is it an abbreviated handshake? 973 if (clientHello.sessionId.length() != 0) { 974 SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext 975 .engineGetServerSessionContext()) 976 .get(clientHello.sessionId.getId()); 977 978 boolean resumingSession = 979 (previous != null) && previous.isRejoinable(); 980 if (!resumingSession) { 981 if (SSLLogger.isOn && 982 SSLLogger.isOn("ssl,handshake,verbose")) { 983 SSLLogger.finest( 984 "Can't resume, " + 985 "the existing session is not rejoinable"); 986 } 987 } 988 // Validate the negotiated protocol version. 989 if (resumingSession) { 990 ProtocolVersion sessionProtocol = 991 previous.getProtocolVersion(); 992 if (sessionProtocol != shc.negotiatedProtocol) { 993 resumingSession = false; 994 if (SSLLogger.isOn && 995 SSLLogger.isOn("ssl,handshake,verbose")) { 996 SSLLogger.finest( 997 "Can't resume, not the same protocol version"); 998 } 999 } 1000 } 1001 1002 // Validate the required client authentication. 1003 if (resumingSession && 1004 (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) { 1005 try { 1006 previous.getPeerPrincipal(); 1007 } catch (SSLPeerUnverifiedException e) { 1008 resumingSession = false; 1009 if (SSLLogger.isOn && 1010 SSLLogger.isOn("ssl,handshake,verbose")) { 1011 SSLLogger.finest( 1012 "Can't resume, " + 1013 "client authentication is required"); 1014 } 1015 } 1016 } 1017 1018 // Validate that the cached cipher suite. 1019 if (resumingSession) { 1020 CipherSuite suite = previous.getSuite(); 1021 if ((!shc.isNegotiable(suite)) || 1022 (!clientHello.cipherSuites.contains(suite))) { 1023 resumingSession = false; 1024 if (SSLLogger.isOn && 1025 SSLLogger.isOn("ssl,handshake,verbose")) { 1026 SSLLogger.finest( 1027 "Can't resume, " + 1028 "the session cipher suite is absent"); 1029 } 1030 } 1031 } 1032 1033 // ensure that the endpoint identification algorithm matches the 1034 // one in the session 1035 String identityAlg = shc.sslConfig.identificationProtocol; 1036 if (resumingSession && identityAlg != null) { 1037 String sessionIdentityAlg = 1038 previous.getIdentificationProtocol(); 1039 if (!identityAlg.equalsIgnoreCase(sessionIdentityAlg)) { 1040 if (SSLLogger.isOn && 1041 SSLLogger.isOn("ssl,handshake,verbose")) { 1042 SSLLogger.finest("Can't resume, endpoint id" + 1043 " algorithm does not match, requested: " + 1044 identityAlg + ", cached: " + sessionIdentityAlg); 1045 } 1046 resumingSession = false; 1047 } 1048 } 1049 1050 // So far so good. Note that the handshake extensions may reset 1051 // the resuming options later. 1052 shc.isResumption = resumingSession; 1053 shc.resumingSession = resumingSession ? previous : null; 1054 } 1055 1056 // cache the client random number for further using 1057 shc.clientHelloRandom = clientHello.clientRandom; 1058 1059 // Check and launch ClientHello extensions. 1060 SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions( 1061 SSLHandshake.CLIENT_HELLO); 1062 clientHello.extensions.consumeOnLoad(shc, extTypes); 1063 1064 // 1065 // update 1066 // 1067 if (!shc.conContext.isNegotiated) { 1068 shc.conContext.protocolVersion = shc.negotiatedProtocol; 1069 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol); 1070 } 1071 1072 // update the responders 1073 // 1074 // Only need to ServerHello, which may add more responders later. 1075 // Note that ServerHello and HelloRetryRequest share the same 1076 // handshake type/id. The ServerHello producer may be replaced 1077 // by HelloRetryRequest producer if needed. 1078 shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id, 1079 SSLHandshake.SERVER_HELLO); 1080 1081 // 1082 // produce 1083 // 1084 SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] { 1085 SSLHandshake.SERVER_HELLO, 1086 1087 // full handshake messages 1088 SSLHandshake.CERTIFICATE, 1089 SSLHandshake.CERTIFICATE_STATUS, 1090 SSLHandshake.SERVER_KEY_EXCHANGE, 1091 SSLHandshake.CERTIFICATE_REQUEST, 1092 SSLHandshake.SERVER_HELLO_DONE, 1093 1094 // abbreviated handshake messages 1095 SSLHandshake.FINISHED 1096 }; 1097 1098 for (SSLHandshake hs : probableHandshakeMessages) { 1099 HandshakeProducer handshakeProducer = 1100 shc.handshakeProducers.remove(hs.id); 1101 if (handshakeProducer != null) { 1102 handshakeProducer.produce(context, clientHello); 1103 } 1104 } 1105 } 1106 } 1107 1108 /** 1109 * The "ClientHello" handshake message consumer for TLS 1.3. 1110 */ 1111 private static final 1112 class T13ClientHelloConsumer implements HandshakeConsumer { 1113 // Prevent instantiation of this class. 1114 private T13ClientHelloConsumer() { 1115 // blank 1116 } 1117 1118 @Override 1119 public void consume(ConnectionContext context, 1120 HandshakeMessage message) throws IOException { 1121 // The consuming happens in server side only. 1122 ServerHandshakeContext shc = (ServerHandshakeContext)context; 1123 ClientHelloMessage clientHello = (ClientHelloMessage)message; 1124 1125 // [RFC 8446] TLS 1.3 forbids renegotiation. If a server has 1126 // negotiated TLS 1.3 and receives a ClientHello at any other 1127 // time, it MUST terminate the connection with an 1128 // "unexpected_message" alert. 1129 if (shc.conContext.isNegotiated) { 1130 throw shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, 1131 "Received unexpected renegotiation handshake message"); 1132 } 1133 1134 // The client may send a dummy change_cipher_spec record 1135 // immediately after the first ClientHello. 1136 shc.conContext.consumers.putIfAbsent( 1137 ContentType.CHANGE_CIPHER_SPEC.id, 1138 ChangeCipherSpec.t13Consumer); 1139 1140 // Is it a resumption? 1141 // 1142 // Check and launch the "psk_key_exchange_modes" and 1143 // "pre_shared_key" extensions first, which will reset the 1144 // resuming session, no matter the extensions present or not. 1145 shc.isResumption = true; 1146 SSLExtension[] extTypes = new SSLExtension[] { 1147 SSLExtension.PSK_KEY_EXCHANGE_MODES, 1148 SSLExtension.CH_PRE_SHARED_KEY 1149 }; 1150 clientHello.extensions.consumeOnLoad(shc, extTypes); 1151 1152 // Check and launch ClientHello extensions other than 1153 // "psk_key_exchange_modes", "pre_shared_key", "protocol_version" 1154 // and "key_share" extensions. 1155 // 1156 // These extensions may discard session resumption, or ask for 1157 // hello retry. 1158 extTypes = shc.sslConfig.getExclusiveExtensions( 1159 SSLHandshake.CLIENT_HELLO, 1160 Arrays.asList( 1161 SSLExtension.PSK_KEY_EXCHANGE_MODES, 1162 SSLExtension.CH_PRE_SHARED_KEY, 1163 SSLExtension.CH_SUPPORTED_VERSIONS)); 1164 clientHello.extensions.consumeOnLoad(shc, extTypes); 1165 1166 if (!shc.handshakeProducers.isEmpty()) { 1167 // Should be HelloRetryRequest producer. 1168 goHelloRetryRequest(shc, clientHello); 1169 } else { 1170 goServerHello(shc, clientHello); 1171 } 1172 } 1173 1174 private void goHelloRetryRequest(ServerHandshakeContext shc, 1175 ClientHelloMessage clientHello) throws IOException { 1176 HandshakeProducer handshakeProducer = 1177 shc.handshakeProducers.remove( 1178 SSLHandshake.HELLO_RETRY_REQUEST.id); 1179 if (handshakeProducer != null) { 1180 handshakeProducer.produce(shc, clientHello); 1181 } else { 1182 // unlikely 1183 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 1184 "No HelloRetryRequest producer: " + shc.handshakeProducers); 1185 } 1186 1187 if (!shc.handshakeProducers.isEmpty()) { 1188 // unlikely, but please double check. 1189 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 1190 "unknown handshake producers: " + shc.handshakeProducers); 1191 } 1192 } 1193 1194 private void goServerHello(ServerHandshakeContext shc, 1195 ClientHelloMessage clientHello) throws IOException { 1196 // 1197 // validate 1198 // 1199 shc.clientHelloRandom = clientHello.clientRandom; 1200 1201 // 1202 // update 1203 // 1204 if (!shc.conContext.isNegotiated) { 1205 shc.conContext.protocolVersion = shc.negotiatedProtocol; 1206 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol); 1207 } 1208 1209 // update the responders 1210 // 1211 // Only ServerHello/HelloRetryRequest producer, which adds 1212 // more responders later. 1213 shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id, 1214 SSLHandshake.SERVER_HELLO); 1215 1216 SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] { 1217 SSLHandshake.SERVER_HELLO, 1218 1219 // full handshake messages 1220 SSLHandshake.ENCRYPTED_EXTENSIONS, 1221 SSLHandshake.CERTIFICATE_REQUEST, 1222 SSLHandshake.CERTIFICATE, 1223 SSLHandshake.CERTIFICATE_VERIFY, 1224 SSLHandshake.FINISHED 1225 }; 1226 1227 // 1228 // produce 1229 // 1230 for (SSLHandshake hs : probableHandshakeMessages) { 1231 HandshakeProducer handshakeProducer = 1232 shc.handshakeProducers.remove(hs.id); 1233 if (handshakeProducer != null) { 1234 handshakeProducer.produce(shc, clientHello); 1235 } 1236 } 1237 } 1238 } 1239 1240 /** 1241 * The "ClientHello" handshake message consumer for DTLS 1.2 and 1242 * previous DTLS protocol versions. 1243 */ 1244 private static final 1245 class D12ClientHelloConsumer implements HandshakeConsumer { 1246 // Prevent instantiation of this class. 1247 private D12ClientHelloConsumer() { 1248 // blank 1249 } 1250 1251 @Override 1252 public void consume(ConnectionContext context, 1253 HandshakeMessage message) throws IOException { 1254 // The consuming happens in server side only. 1255 ServerHandshakeContext shc = (ServerHandshakeContext)context; 1256 ClientHelloMessage clientHello = (ClientHelloMessage)message; 1257 1258 // 1259 // validate 1260 // 1261 1262 // Reject client initiated renegotiation? 1263 // 1264 // If server side should reject client-initiated renegotiation, 1265 // send an Alert.HANDSHAKE_FAILURE fatal alert, not a 1266 // no_renegotiation warning alert (no_renegotiation must be a 1267 // warning: RFC 2246). no_renegotiation might seem more 1268 // natural at first, but warnings are not appropriate because 1269 // the sending party does not know how the receiving party 1270 // will behave. This state must be treated as a fatal server 1271 // condition. 1272 // 1273 // This will not have any impact on server initiated renegotiation. 1274 if (shc.conContext.isNegotiated) { 1275 if (!shc.conContext.secureRenegotiation && 1276 !HandshakeContext.allowUnsafeRenegotiation) { 1277 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 1278 "Unsafe renegotiation is not allowed"); 1279 } 1280 1281 if (ServerHandshakeContext.rejectClientInitiatedRenego && 1282 !shc.kickstartMessageDelivered) { 1283 throw shc.conContext.fatal(Alert.HANDSHAKE_FAILURE, 1284 "Client initiated renegotiation is not allowed"); 1285 } 1286 } 1287 1288 // Is it an abbreviated handshake? 1289 if (clientHello.sessionId.length() != 0) { 1290 SSLSessionImpl previous = ((SSLSessionContextImpl)shc.sslContext 1291 .engineGetServerSessionContext()) 1292 .get(clientHello.sessionId.getId()); 1293 1294 boolean resumingSession = 1295 (previous != null) && previous.isRejoinable(); 1296 if (!resumingSession) { 1297 if (SSLLogger.isOn && 1298 SSLLogger.isOn("ssl,handshake,verbose")) { 1299 SSLLogger.finest( 1300 "Can't resume, " + 1301 "the existing session is not rejoinable"); 1302 } 1303 } 1304 // Validate the negotiated protocol version. 1305 if (resumingSession) { 1306 ProtocolVersion sessionProtocol = 1307 previous.getProtocolVersion(); 1308 if (sessionProtocol != shc.negotiatedProtocol) { 1309 resumingSession = false; 1310 if (SSLLogger.isOn && 1311 SSLLogger.isOn("ssl,handshake,verbose")) { 1312 SSLLogger.finest( 1313 "Can't resume, not the same protocol version"); 1314 } 1315 } 1316 } 1317 1318 // Validate the required client authentication. 1319 if (resumingSession && 1320 (shc.sslConfig.clientAuthType == CLIENT_AUTH_REQUIRED)) { 1321 1322 try { 1323 previous.getPeerPrincipal(); 1324 } catch (SSLPeerUnverifiedException e) { 1325 resumingSession = false; 1326 if (SSLLogger.isOn && 1327 SSLLogger.isOn("ssl,handshake,verbose")) { 1328 SSLLogger.finest( 1329 "Can't resume, " + 1330 "client authentication is required"); 1331 } 1332 } 1333 } 1334 1335 // Validate that the cached cipher suite. 1336 if (resumingSession) { 1337 CipherSuite suite = previous.getSuite(); 1338 if ((!shc.isNegotiable(suite)) || 1339 (!clientHello.cipherSuites.contains(suite))) { 1340 resumingSession = false; 1341 if (SSLLogger.isOn && 1342 SSLLogger.isOn("ssl,handshake,verbose")) { 1343 SSLLogger.finest( 1344 "Can't resume, " + 1345 "the session cipher suite is absent"); 1346 } 1347 } 1348 } 1349 1350 // So far so good. Note that the handshake extensions may reset 1351 // the resuming options later. 1352 shc.isResumption = resumingSession; 1353 shc.resumingSession = resumingSession ? previous : null; 1354 } 1355 1356 HelloCookieManager hcm = 1357 shc.sslContext.getHelloCookieManager(ProtocolVersion.DTLS10); 1358 if (!shc.isResumption && 1359 !hcm.isCookieValid(shc, clientHello, clientHello.cookie)) { 1360 // 1361 // Perform cookie exchange for DTLS handshaking if no cookie 1362 // or the cookie is invalid in the ClientHello message. 1363 // 1364 // update the responders 1365 shc.handshakeProducers.put( 1366 SSLHandshake.HELLO_VERIFY_REQUEST.id, 1367 SSLHandshake.HELLO_VERIFY_REQUEST); 1368 1369 // 1370 // produce response handshake message 1371 // 1372 SSLHandshake.HELLO_VERIFY_REQUEST.produce(context, clientHello); 1373 1374 return; 1375 } 1376 1377 // cache the client random number for further using 1378 shc.clientHelloRandom = clientHello.clientRandom; 1379 1380 // Check and launch ClientHello extensions. 1381 SSLExtension[] extTypes = shc.sslConfig.getEnabledExtensions( 1382 SSLHandshake.CLIENT_HELLO); 1383 clientHello.extensions.consumeOnLoad(shc, extTypes); 1384 1385 // 1386 // update 1387 // 1388 if (!shc.conContext.isNegotiated) { 1389 shc.conContext.protocolVersion = shc.negotiatedProtocol; 1390 shc.conContext.outputRecord.setVersion(shc.negotiatedProtocol); 1391 } 1392 1393 // update the responders 1394 // 1395 // Only need to ServerHello, which may add more responders later. 1396 shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id, 1397 SSLHandshake.SERVER_HELLO); 1398 1399 // 1400 // produce 1401 // 1402 SSLHandshake[] probableHandshakeMessages = new SSLHandshake[] { 1403 SSLHandshake.SERVER_HELLO, 1404 1405 // full handshake messages 1406 SSLHandshake.CERTIFICATE, 1407 SSLHandshake.CERTIFICATE_STATUS, 1408 SSLHandshake.SERVER_KEY_EXCHANGE, 1409 SSLHandshake.CERTIFICATE_REQUEST, 1410 SSLHandshake.SERVER_HELLO_DONE, 1411 1412 // abbreviated handshake messages 1413 SSLHandshake.FINISHED 1414 }; 1415 1416 for (SSLHandshake hs : probableHandshakeMessages) { 1417 HandshakeProducer handshakeProducer = 1418 shc.handshakeProducers.remove(hs.id); 1419 if (handshakeProducer != null) { 1420 handshakeProducer.produce(context, clientHello); 1421 } 1422 } 1423 } 1424 } 1425 1426 /** 1427 * The "ClientHello" handshake message consumer for DTLS 1.3. 1428 */ 1429 private static final 1430 class D13ClientHelloConsumer implements HandshakeConsumer { 1431 // Prevent instantiation of this class. 1432 private D13ClientHelloConsumer() { 1433 // blank 1434 } 1435 1436 @Override 1437 public void consume(ConnectionContext context, 1438 HandshakeMessage message) throws IOException { 1439 throw new UnsupportedOperationException("Not supported yet."); 1440 } 1441 } 1442 }