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"})
SSLHandshake(byte id, String name)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"})
SSLHandshake(byte id, String name, Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers, Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers)366     SSLHandshake(byte id, String name,
367         Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
368         Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers) {
369 
370         this(id, name, handshakeConsumers, handshakeProducers,
371                 (Map.Entry<HandshakeAbsence, ProtocolVersion[]>[])(
372                         new Map.Entry[0]));
373     }
374 
SSLHandshake(byte id, String name, Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers, Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers, Map.Entry<HandshakeAbsence, ProtocolVersion[]>[] handshakeAbsence)375     SSLHandshake(byte id, String name,
376         Map.Entry<SSLConsumer, ProtocolVersion[]>[] handshakeConsumers,
377         Map.Entry<HandshakeProducer, ProtocolVersion[]>[] handshakeProducers,
378         Map.Entry<HandshakeAbsence, ProtocolVersion[]>[] handshakeAbsence) {
379 
380         this.id = id;
381         this.name = name;
382         this.handshakeConsumers = handshakeConsumers;
383         this.handshakeProducers = handshakeProducers;
384         this.handshakeAbsences = handshakeAbsence;
385     }
386 
387     @Override
consume(ConnectionContext context, ByteBuffer message)388     public void consume(ConnectionContext context,
389             ByteBuffer message) throws IOException {
390         SSLConsumer hc = getHandshakeConsumer(context);
391         if (hc != null) {
392             hc.consume(context, message);
393         } else {
394             throw new UnsupportedOperationException(
395                     "Unsupported handshake consumer: " + this.name);
396         }
397     }
398 
getHandshakeConsumer(ConnectionContext context)399     private SSLConsumer getHandshakeConsumer(ConnectionContext context) {
400         if (handshakeConsumers.length == 0) {
401             return null;
402         }
403 
404         // The consuming happens in handshake context only.
405         HandshakeContext hc = (HandshakeContext)context;
406         ProtocolVersion protocolVersion;
407         if ((hc.negotiatedProtocol == null) ||
408                 (hc.negotiatedProtocol == ProtocolVersion.NONE)) {
409             if (hc.conContext.isNegotiated &&
410                     hc.conContext.protocolVersion != ProtocolVersion.NONE) {
411                 protocolVersion = hc.conContext.protocolVersion;
412             } else {
413                 protocolVersion = hc.maximumActiveProtocol;
414             }
415         } else {
416             protocolVersion = hc.negotiatedProtocol;
417         }
418 
419         for (Map.Entry<SSLConsumer,
420                 ProtocolVersion[]> phe : handshakeConsumers) {
421             for (ProtocolVersion pv : phe.getValue()) {
422                 if (protocolVersion == pv) {
423                     return phe.getKey();
424                 }
425             }
426         }
427 
428         return null;
429     }
430 
431     @Override
produce(ConnectionContext context, HandshakeMessage message)432     public byte[] produce(ConnectionContext context,
433             HandshakeMessage message) throws IOException {
434         HandshakeProducer hp = getHandshakeProducer(context);
435         if (hp != null) {
436             return hp.produce(context, message);
437         } else {
438             throw new UnsupportedOperationException(
439                     "Unsupported handshake producer: " + this.name);
440         }
441     }
442 
getHandshakeProducer( ConnectionContext context)443     private HandshakeProducer getHandshakeProducer(
444             ConnectionContext context) {
445         if (handshakeConsumers.length == 0) {
446             return null;
447         }
448 
449         // The consuming happens in handshake context only.
450         HandshakeContext hc = (HandshakeContext)context;
451         ProtocolVersion protocolVersion;
452         if ((hc.negotiatedProtocol == null) ||
453                 (hc.negotiatedProtocol == ProtocolVersion.NONE)) {
454             if (hc.conContext.isNegotiated &&
455                     hc.conContext.protocolVersion != ProtocolVersion.NONE) {
456                 protocolVersion = hc.conContext.protocolVersion;
457             } else {
458                 protocolVersion = hc.maximumActiveProtocol;
459             }
460         } else {
461             protocolVersion = hc.negotiatedProtocol;
462         }
463 
464         for (Map.Entry<HandshakeProducer,
465                 ProtocolVersion[]> phe : handshakeProducers) {
466             for (ProtocolVersion pv : phe.getValue()) {
467                 if (protocolVersion == pv) {
468                     return phe.getKey();
469                 }
470             }
471         }
472 
473         return null;
474     }
475 
476     @Override
toString()477     public String toString() {
478         return name;
479     }
480 
nameOf(byte id)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 
isKnown(byte id)496     static boolean isKnown(byte id) {
497         for (SSLHandshake hs : SSLHandshake.values()) {
498             if (hs.id == id && id != NOT_APPLICABLE.id) {
499                 return true;
500             }
501         }
502 
503         return false;
504     }
505 
kickstart(HandshakeContext context)506     static final void kickstart(HandshakeContext context) throws IOException {
507         if (context instanceof ClientHandshakeContext) {
508             // For initial handshaking, including session resumption,
509             // ClientHello message is used as the kickstart message.
510             //
511             // (D)TLS 1.2 and older protocols support renegotiation on existing
512             // connections.  A ClientHello messages is used to kickstart the
513             // renegotiation.
514             //
515             // (D)TLS 1.3 forbids renegotiation.  The post-handshake KeyUpdate
516             // message is used to update the sending cryptographic keys.
517             if (context.conContext.isNegotiated &&
518                     context.conContext.protocolVersion.useTLS13PlusSpec()) {
519                 // Use KeyUpdate message for renegotiation.
520                 KeyUpdate.kickstartProducer.produce(context);
521             } else {
522                 // Using ClientHello message for the initial handshaking
523                 // (including session resumption) or renegotiation.
524                 // SSLHandshake.CLIENT_HELLO.produce(context);
525                 ClientHello.kickstartProducer.produce(context);
526             }
527         } else {
528             // The server side can delivering kickstart message after the
529             // connection has established.
530             //
531             // (D)TLS 1.2 and older protocols use HelloRequest to begin a
532             // negotiation process anew.
533             //
534             // While (D)TLS 1.3 uses the post-handshake KeyUpdate message
535             // to update the sending cryptographic keys.
536             if (context.conContext.protocolVersion.useTLS13PlusSpec()) {
537                 // Use KeyUpdate message for renegotiation.
538                 KeyUpdate.kickstartProducer.produce(context);
539             } else {
540                 // SSLHandshake.HELLO_REQUEST.produce(context);
541                 HelloRequest.kickstartProducer.produce(context);
542             }
543         }
544     }
545 
546     /**
547      * A (transparent) specification of handshake message.
548      */
549     static abstract class HandshakeMessage {
550         final HandshakeContext      handshakeContext;
551 
HandshakeMessage(HandshakeContext handshakeContext)552         HandshakeMessage(HandshakeContext handshakeContext) {
553             this.handshakeContext = handshakeContext;
554         }
555 
handshakeType()556         abstract SSLHandshake handshakeType();
messageLength()557         abstract int messageLength();
send(HandshakeOutStream hos)558         abstract void send(HandshakeOutStream hos) throws IOException;
559 
write(HandshakeOutStream hos)560         void write(HandshakeOutStream hos) throws IOException {
561             int len = messageLength();
562             if (len >= Record.OVERFLOW_OF_INT24) {
563                 throw new SSLException("Handshake message is overflow"
564                         + ", type = " + handshakeType() + ", len = " + len);
565             }
566             hos.write(handshakeType().id);
567             hos.putInt24(len);
568             send(hos);
569             hos.complete();
570         }
571     }
572 }
573