1 /*
   2  * Copyright (c) 2006, 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.util.AbstractMap.SimpleImmutableEntry;
  31 import java.util.Map;
  32 import javax.net.ssl.SSLException;
  33 
  34 enum SSLHandshake implements SSLConsumer, HandshakeProducer {
  35     @SuppressWarnings({"unchecked", "rawtypes"})
  36     HELLO_REQUEST ((byte)0x00, "hello_request",
  37         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
  38             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
  39                 HelloRequest.handshakeConsumer,
  40                 ProtocolVersion.PROTOCOLS_TO_12
  41             )
  42         }),
  43         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
  44             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
  45                 HelloRequest.handshakeProducer,
  46                 ProtocolVersion.PROTOCOLS_TO_12
  47             )
  48         })),
  49 
  50     @SuppressWarnings({"unchecked", "rawtypes"})
  51     CLIENT_HELLO ((byte)0x01, "client_hello",
  52         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
  53             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
  54                 ClientHello.handshakeConsumer,
  55                 ProtocolVersion.PROTOCOLS_TO_13
  56             )
  57         }),
  58         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
  59             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
  60                 ClientHello.handshakeProducer,
  61                 ProtocolVersion.PROTOCOLS_TO_13
  62             )
  63         })),
  64 
  65     @SuppressWarnings({"unchecked", "rawtypes"})
  66     SERVER_HELLO ((byte)0x02, "server_hello",
  67         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
  68             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
  69                 ServerHello.handshakeConsumer,
  70                 ProtocolVersion.PROTOCOLS_TO_13
  71             )
  72         }),
  73         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
  74             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
  75                 ServerHello.t12HandshakeProducer,
  76                 ProtocolVersion.PROTOCOLS_TO_12
  77             ),
  78             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
  79                 ServerHello.t13HandshakeProducer,
  80                 ProtocolVersion.PROTOCOLS_OF_13
  81             )
  82         })),
  83 
  84     @SuppressWarnings({"unchecked", "rawtypes"})
  85     HELLO_RETRY_REQUEST ((byte)0x02, "hello_retry_request",
  86         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
  87             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
  88                 ServerHello.handshakeConsumer,      // Use ServerHello consumer
  89                 ProtocolVersion.PROTOCOLS_TO_13
  90             )
  91         }),
  92         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
  93             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
  94                 ServerHello.hrrHandshakeProducer,
  95                 ProtocolVersion.PROTOCOLS_OF_13
  96             )
  97         })),
  98 
  99     @SuppressWarnings({"unchecked", "rawtypes"})
 100     HELLO_VERIFY_REQUEST        ((byte)0x03, "hello_verify_request",
 101         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 102             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 103                 HelloVerifyRequest.handshakeConsumer,
 104                 ProtocolVersion.PROTOCOLS_TO_12
 105             )
 106         }),
 107         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 108             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 109                 HelloVerifyRequest.handshakeProducer,
 110                 ProtocolVersion.PROTOCOLS_TO_12
 111             )
 112         })),
 113 
 114     @SuppressWarnings({"unchecked", "rawtypes"})
 115     NEW_SESSION_TICKET          ((byte)0x04, "new_session_ticket",
 116         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 117             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 118                 NewSessionTicket.handshakeConsumer,
 119                 ProtocolVersion.PROTOCOLS_OF_13
 120         )
 121         }),
 122         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 123             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 124                 NewSessionTicket.handshakeProducer,
 125                 ProtocolVersion.PROTOCOLS_OF_13
 126         )
 127         })),
 128     END_OF_EARLY_DATA           ((byte)0x05, "end_of_early_data"),
 129 
 130     @SuppressWarnings({"unchecked", "rawtypes"})
 131     ENCRYPTED_EXTENSIONS        ((byte)0x08, "encrypted_extensions",
 132         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 133             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 134                 EncryptedExtensions.handshakeConsumer,
 135                 ProtocolVersion.PROTOCOLS_OF_13
 136             )
 137         }),
 138         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 139             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 140                 EncryptedExtensions.handshakeProducer,
 141                 ProtocolVersion.PROTOCOLS_OF_13
 142             )
 143         })),
 144 
 145     @SuppressWarnings({"unchecked", "rawtypes"})
 146     CERTIFICATE                 ((byte)0x0B, "certificate",
 147         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 148             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 149                 CertificateMessage.t12HandshakeConsumer,
 150                 ProtocolVersion.PROTOCOLS_TO_12
 151             ),
 152             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 153                 CertificateMessage.t13HandshakeConsumer,
 154                 ProtocolVersion.PROTOCOLS_OF_13
 155             )
 156         }),
 157         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 158             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 159                 CertificateMessage.t12HandshakeProducer,
 160                 ProtocolVersion.PROTOCOLS_TO_12
 161             ),
 162             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 163                 CertificateMessage.t13HandshakeProducer,
 164                 ProtocolVersion.PROTOCOLS_OF_13
 165             )
 166         })),
 167 
 168     @SuppressWarnings({"unchecked", "rawtypes"})
 169     SERVER_KEY_EXCHANGE         ((byte)0x0C, "server_key_exchange",
 170         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 171             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 172                 ServerKeyExchange.handshakeConsumer,
 173                 ProtocolVersion.PROTOCOLS_TO_12
 174             )
 175         }),
 176         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 177             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 178                 ServerKeyExchange.handshakeProducer,
 179                 ProtocolVersion.PROTOCOLS_TO_12
 180             )
 181         })),
 182 
 183     @SuppressWarnings({"unchecked", "rawtypes"})
 184     CERTIFICATE_REQUEST         ((byte)0x0D, "certificate_request",
 185         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 186             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 187                 CertificateRequest.t10HandshakeConsumer,
 188                 ProtocolVersion.PROTOCOLS_TO_11
 189             ),
 190             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 191                 CertificateRequest.t12HandshakeConsumer,
 192                 ProtocolVersion.PROTOCOLS_OF_12
 193             ),
 194             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 195                 CertificateRequest.t13HandshakeConsumer,
 196                 ProtocolVersion.PROTOCOLS_OF_13
 197             )
 198         }),
 199         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 200             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 201                 CertificateRequest.t10HandshakeProducer,
 202                 ProtocolVersion.PROTOCOLS_TO_11
 203             ),
 204             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 205                 CertificateRequest.t12HandshakeProducer,
 206                 ProtocolVersion.PROTOCOLS_OF_12
 207             ),
 208             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 209                 CertificateRequest.t13HandshakeProducer,
 210                 ProtocolVersion.PROTOCOLS_OF_13
 211             )
 212         })),
 213 
 214     @SuppressWarnings({"unchecked", "rawtypes"})
 215     SERVER_HELLO_DONE           ((byte)0x0E, "server_hello_done",
 216         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 217             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 218                 ServerHelloDone.handshakeConsumer,
 219                 ProtocolVersion.PROTOCOLS_TO_12
 220             )
 221         }),
 222         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 223             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 224                 ServerHelloDone.handshakeProducer,
 225                 ProtocolVersion.PROTOCOLS_TO_12
 226             )
 227         })),
 228 
 229     @SuppressWarnings({"unchecked", "rawtypes"})
 230     CERTIFICATE_VERIFY          ((byte)0x0F, "certificate_verify",
 231         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 232             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 233                 CertificateVerify.s30HandshakeConsumer,
 234                 ProtocolVersion.PROTOCOLS_OF_30
 235             ),
 236             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 237                 CertificateVerify.t10HandshakeConsumer,
 238                 ProtocolVersion.PROTOCOLS_10_11
 239             ),
 240             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 241                 CertificateVerify.t12HandshakeConsumer,
 242                 ProtocolVersion.PROTOCOLS_OF_12
 243             ),
 244             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 245                 CertificateVerify.t13HandshakeConsumer,
 246                 ProtocolVersion.PROTOCOLS_OF_13
 247             )
 248         }),
 249         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 250             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 251                 CertificateVerify.s30HandshakeProducer,
 252                 ProtocolVersion.PROTOCOLS_OF_30
 253             ),
 254             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 255                 CertificateVerify.t10HandshakeProducer,
 256                 ProtocolVersion.PROTOCOLS_10_11
 257             ),
 258             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 259                 CertificateVerify.t12HandshakeProducer,
 260                 ProtocolVersion.PROTOCOLS_OF_12
 261             ),
 262             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 263                 CertificateVerify.t13HandshakeProducer,
 264                 ProtocolVersion.PROTOCOLS_OF_13
 265             )
 266         })),
 267 
 268     @SuppressWarnings({"unchecked", "rawtypes"})
 269     CLIENT_KEY_EXCHANGE         ((byte)0x10, "client_key_exchange",
 270         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 271             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 272                 ClientKeyExchange.handshakeConsumer,
 273                 ProtocolVersion.PROTOCOLS_TO_12
 274             )
 275         }),
 276         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 277             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 278                 ClientKeyExchange.handshakeProducer,
 279                 ProtocolVersion.PROTOCOLS_TO_12
 280             )
 281         })),
 282 
 283     @SuppressWarnings({"unchecked", "rawtypes"})
 284     FINISHED                    ((byte)0x14, "finished",
 285         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 286             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 287                 Finished.t12HandshakeConsumer,
 288                 ProtocolVersion.PROTOCOLS_TO_12
 289             ),
 290             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 291                 Finished.t13HandshakeConsumer,
 292                 ProtocolVersion.PROTOCOLS_OF_13
 293             )
 294         }),
 295         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 296             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 297                 Finished.t12HandshakeProducer,
 298                 ProtocolVersion.PROTOCOLS_TO_12
 299             ),
 300             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 301                 Finished.t13HandshakeProducer,
 302                 ProtocolVersion.PROTOCOLS_OF_13
 303             )
 304         })),
 305 
 306     CERTIFICATE_URL             ((byte)0x15, "certificate_url"),
 307 
 308     @SuppressWarnings({"unchecked", "rawtypes"})
 309     CERTIFICATE_STATUS          ((byte)0x16, "certificate_status",
 310         (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 311             new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 312                 CertificateStatus.handshakeConsumer,
 313                 ProtocolVersion.PROTOCOLS_TO_12
 314             )
 315         }),
 316         (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 317             new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 318                 CertificateStatus.handshakeProducer,
 319                 ProtocolVersion.PROTOCOLS_TO_12
 320             )
 321         }),
 322         (Map.Entry<HandshakeAbsence, ProtocolVersion[]>[])(new Map.Entry[] {
 323             new SimpleImmutableEntry<HandshakeAbsence, ProtocolVersion[]>(
 324                 CertificateStatus.handshakeAbsence,
 325                 ProtocolVersion.PROTOCOLS_TO_12
 326             )
 327         })),
 328 
 329     SUPPLEMENTAL_DATA           ((byte)0x17, "supplemental_data"),
 330 
 331     @SuppressWarnings({"unchecked", "rawtypes"})
 332     KEY_UPDATE                  ((byte)0x18, "key_update",
 333             (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(new Map.Entry[] {
 334                     new SimpleImmutableEntry<SSLConsumer, ProtocolVersion[]>(
 335                             KeyUpdate.handshakeConsumer,
 336                             ProtocolVersion.PROTOCOLS_OF_13
 337                     )
 338             }),
 339             (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(new Map.Entry[] {
 340                     new SimpleImmutableEntry<HandshakeProducer, ProtocolVersion[]>(
 341                             KeyUpdate.handshakeProducer,
 342                             ProtocolVersion.PROTOCOLS_OF_13
 343                     )
 344             })),
 345     MESSAGE_HASH                ((byte)0xFE, "message_hash"),
 346     NOT_APPLICABLE              ((byte)0xFF, "not_applicable");
 347 
 348     final byte id;
 349     final String name;
 350     final Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers;
 351     final Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers;
 352     final Map.Entry<HandshakeAbsence, ProtocolVersion[]>[] handshakeAbsences;
 353 
 354     @SuppressWarnings({"unchecked", "rawtypes"})
 355     SSLHandshake(byte id, String name) {
 356         this(id, name,
 357                 (Map.Entry<SSLConsumer, ProtocolVersion[]>[])(
 358                         new Map.Entry[0]),
 359                 (Map.Entry<HandshakeProducer, ProtocolVersion[]>[])(
 360                         new Map.Entry[0]),
 361                 (Map.Entry<HandshakeAbsence, ProtocolVersion[]>[])(
 362                         new Map.Entry[0]));
 363     }
 364 
 365     @SuppressWarnings({"unchecked", "rawtypes"})
 366     SSLHandshake(byte id, String name,
 367         Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
 368         Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers) {
 369         this(id, name, handshakeConsumers, handshakeProducers,
 370                 (Map.Entry<HandshakeAbsence, ProtocolVersion[]>[])(
 371                         new Map.Entry[0]));
 372     }
 373 
 374     SSLHandshake(byte id, String name,
 375         Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
 376         Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers,
 377         Map.Entry<HandshakeAbsence, ProtocolVersion[]>[] handshakeAbsence) {
 378         this.id = id;
 379         this.name = name;
 380         this.handshakeConsumers = handshakeConsumers;
 381         this.handshakeProducers = handshakeProducers;
 382         this.handshakeAbsences = handshakeAbsence;
 383     }
 384 
 385     @Override
 386     public void consume(ConnectionContext context,
 387             ByteBuffer message) throws IOException {
 388         SSLConsumer hc = getHandshakeConsumer(context);
 389         if (hc != null) {
 390             hc.consume(context, message);
 391         } else {
 392             throw new UnsupportedOperationException(
 393                     "Unsupported handshake consumer: " + this.name);
 394         }
 395     }
 396 
 397     private SSLConsumer getHandshakeConsumer(ConnectionContext context) {
 398         if (handshakeConsumers.length == 0) {
 399             return null;
 400         }
 401 
 402         // The comsuming happens in handshake context only.
 403         HandshakeContext hc = (HandshakeContext)context;
 404         ProtocolVersion protocolVersion;
 405         if ((hc.negotiatedProtocol == null) ||
 406                 (hc.negotiatedProtocol == ProtocolVersion.NONE)) {
 407             protocolVersion = hc.maximumActiveProtocol;
 408         } else {
 409             protocolVersion = hc.negotiatedProtocol;
 410         }
 411 
 412         for (Map.Entry<SSLConsumer,
 413                 ProtocolVersion[]> phe : handshakeConsumers) {
 414             for (ProtocolVersion pv : phe.getValue()) {
 415                 if (protocolVersion == pv) {
 416                     return phe.getKey();
 417                 }
 418             }
 419         }
 420 
 421         return null;
 422     }
 423 
 424     @Override
 425     public byte[] produce(ConnectionContext context,
 426             HandshakeMessage message) throws IOException {
 427         HandshakeProducer hp = getHandshakeProducer(context);
 428         if (hp != null) {
 429             return hp.produce(context, message);
 430         } else {
 431             throw new UnsupportedOperationException(
 432                     "Unsupported handshake producer: " + this.name);
 433         }
 434     }
 435 
 436     private HandshakeProducer getHandshakeProducer(
 437             ConnectionContext context) {
 438         if (handshakeConsumers.length == 0) {
 439             return null;
 440         }
 441 
 442         // The comsuming happens in handshake context only.
 443         HandshakeContext hc = (HandshakeContext)context;
 444         ProtocolVersion protocolVersion;
 445         if ((hc.negotiatedProtocol == null) ||
 446                 (hc.negotiatedProtocol == ProtocolVersion.NONE)) {
 447             protocolVersion = hc.maximumActiveProtocol;
 448         } else {
 449             protocolVersion = hc.negotiatedProtocol;
 450         }
 451 
 452         for (Map.Entry<HandshakeProducer,
 453                 ProtocolVersion[]> phe : handshakeProducers) {
 454             for (ProtocolVersion pv : phe.getValue()) {
 455                 if (protocolVersion == pv) {
 456                     return phe.getKey();
 457                 }
 458             }
 459         }
 460 
 461         return null;
 462     }
 463 
 464     @Override
 465     public String toString() {
 466         return name;
 467     }
 468 
 469     /*
 470     static SSLHandshake valueOf(byte id) {
 471         for (SSLHandshake hs : SSLHandshake.values()) {
 472             if (hs.id == id) {
 473                 return hs;
 474             }
 475         }
 476 
 477         return null;
 478     }
 479     */
 480 
 481     static String nameOf(byte id) {
 482         // If two handshake message share the same handshake type, returns
 483         // the first handshake message name.
 484         //
 485         // It is not a big issue at present as only ServerHello and
 486         // HellRetryRequest share a handshake type.
 487         for (SSLHandshake hs : SSLHandshake.values()) {
 488             if (hs.id == id) {
 489                 return hs.name;
 490             }
 491         }
 492 
 493         return "UNKNOWN-HANDSHAKE-MESSAGE(" + id + ")";
 494     }
 495 
 496     static final void kickstart(HandshakeContext context) throws IOException {
 497         if (context instanceof ClientHandshakeContext) {
 498             // For initial handshaking, including session resumption,
 499             // ClientHello message is used as the kickstart message.
 500             //
 501             // (D)TLS 1.2 and older protocols support renegotiation on existing
 502             // connections.  A ClientHello messages is used to kickstart the
 503             // renegotiation.
 504             //
 505             // (D)TLS 1.3 forbids renegotiation.  The post-handshake KeyUpdate
 506             // message is used to update the sending cryptographic keys.
 507             if (context.conContext.isNegotiated &&
 508                     context.conContext.protocolVersion.useTLS13PlusSpec()) {
 509                 // Use KeyUpdate message for renegotiation.
 510                 KeyUpdate.kickstartProducer.produce(context);
 511             } else {
 512                 // Using ClientHello message for the initial handshaking
 513                 // (including session resumption) or renegotiation.
 514                 // SSLHandshake.CLIENT_HELLO.produce(context);
 515                 ClientHello.kickstartProducer.produce(context);
 516             }
 517         } else {
 518             // The server side can delivering kickstart message after the
 519             // connection has established.
 520             //
 521             // (D)TLS 1.2 and older protocols use HelloRequest to begin a
 522             // negotiation process anew.
 523             //
 524             // While (D)TLS 1.3 uses the post-handshake KeyUpdate message
 525             // to update the sending cryptographic keys.
 526             if (context.conContext.protocolVersion.useTLS13PlusSpec()) {
 527                 // Use KeyUpdate message for renegotiation.
 528                 KeyUpdate.kickstartProducer.produce(context);
 529             } else {
 530                 // SSLHandshake.HELLO_REQUEST.produce(context);
 531                 HelloRequest.kickstartProducer.produce(context);
 532             }
 533         }
 534     }
 535 
 536     /**
 537      * A (transparent) specification of handshake message.
 538      */
 539     static abstract class HandshakeMessage {
 540         final HandshakeContext      handshakeContext;
 541 
 542         HandshakeMessage(HandshakeContext handshakeContext) {
 543             this.handshakeContext = handshakeContext;
 544         }
 545 
 546         abstract SSLHandshake handshakeType();
 547         abstract int messageLength();
 548         abstract void send(HandshakeOutStream hos) throws IOException;
 549 
 550         void write(HandshakeOutStream hos) throws IOException {
 551             int len = messageLength();
 552             if (len >= Record.OVERFLOW_OF_INT24) {
 553                 throw new SSLException("Handshake message is overflow"
 554                         + ", type = " + handshakeType() + ", len = " + len);
 555             }
 556             hos.write(handshakeType().id);
 557             hos.putInt24(len);
 558             send(hos);
 559             hos.complete();
 560         }
 561     }
 562 }