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