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