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