1 /*
2  * Copyright (c) 2018, 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.BufferOverflowException;
30 import java.nio.BufferUnderflowException;
31 import java.nio.ByteBuffer;
32 import java.security.AlgorithmConstraints;
33 import java.security.CryptoPrimitive;
34 import java.util.AbstractMap.SimpleImmutableEntry;
35 import java.util.ArrayList;
36 import java.util.Collections;
37 import java.util.EnumMap;
38 import java.util.EnumSet;
39 import java.util.HashMap;
40 import java.util.LinkedHashMap;
41 import java.util.LinkedList;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Queue;
45 import javax.crypto.SecretKey;
46 import javax.net.ssl.SNIServerName;
47 import javax.net.ssl.SSLHandshakeException;
48 import javax.security.auth.x500.X500Principal;
49 import sun.security.ssl.NamedGroup.NamedGroupSpec;
50 import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
51 import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
52 
53 abstract class HandshakeContext implements ConnectionContext {
54     // System properties
55 
56     // By default, disable the unsafe legacy session renegotiation.
57     static final boolean allowUnsafeRenegotiation =
58             Utilities.getBooleanProperty(
59                     "sun.security.ssl.allowUnsafeRenegotiation", false);
60 
61     // For maximum interoperability and backward compatibility, RFC 5746
62     // allows server (or client) to accept ClientHello (or ServerHello)
63     // message without the secure renegotiation_info extension or SCSV.
64     //
65     // For maximum security, RFC 5746 also allows server (or client) to
66     // reject such message with a fatal "handshake_failure" alert.
67     //
68     // By default, allow such legacy hello messages.
69     static final boolean allowLegacyHelloMessages =
70             Utilities.getBooleanProperty(
71                     "sun.security.ssl.allowLegacyHelloMessages", true);
72 
73     // registered handshake message actors
74     LinkedHashMap<Byte, SSLConsumer>  handshakeConsumers;
75     final HashMap<Byte, HandshakeProducer>  handshakeProducers;
76 
77     // context
78     final SSLContextImpl                    sslContext;
79     final TransportContext                  conContext;
80     final SSLConfiguration                  sslConfig;
81 
82     // consolidated parameters
83     final List<ProtocolVersion>             activeProtocols;
84     final List<CipherSuite>                 activeCipherSuites;
85     final AlgorithmConstraints              algorithmConstraints;
86     final ProtocolVersion                   maximumActiveProtocol;
87 
88     // output stream
89     final HandshakeOutStream                handshakeOutput;
90 
91     // handshake transcript hash
92     final HandshakeHash                     handshakeHash;
93 
94     // negotiated security parameters
95     SSLSessionImpl                          handshakeSession;
96     boolean                                 handshakeFinished;
97     // boolean                                 isInvalidated;
98 
99     boolean                                 kickstartMessageDelivered;
100 
101     // Resumption
102     boolean                                 isResumption;
103     SSLSessionImpl                          resumingSession;
104 
105     final Queue<Map.Entry<Byte, ByteBuffer>> delegatedActions;
106     volatile boolean                        taskDelegated = false;
107     volatile Exception                      delegatedThrown = null;
108 
109     ProtocolVersion                         negotiatedProtocol;
110     CipherSuite                             negotiatedCipherSuite;
111     final List<SSLPossession>               handshakePossessions;
112     final List<SSLCredentials>              handshakeCredentials;
113     SSLKeyDerivation                        handshakeKeyDerivation;
114     SSLKeyExchange                          handshakeKeyExchange;
115     SecretKey                               baseReadSecret;
116     SecretKey                               baseWriteSecret;
117 
118     // protocol version being established
119     int                                     clientHelloVersion;
120     String                                  applicationProtocol;
121 
122     RandomCookie                            clientHelloRandom;
123     RandomCookie                            serverHelloRandom;
124     byte[]                                  certRequestContext;
125 
126     ////////////////////
127     // Extensions
128 
129     // the extensions used in the handshake
130     final Map<SSLExtension, SSLExtension.SSLExtensionSpec>
131                                             handshakeExtensions;
132 
133     // MaxFragmentLength
134     int                                     maxFragmentLength;
135 
136     // SignatureScheme
137     List<SignatureScheme>                   localSupportedSignAlgs;
138     List<SignatureScheme>                   peerRequestedSignatureSchemes;
139     List<SignatureScheme>                   peerRequestedCertSignSchemes;
140 
141     // Known authorities
142     X500Principal[]                         peerSupportedAuthorities = null;
143 
144     // SupportedGroups
145     List<NamedGroup>                        clientRequestedNamedGroups;
146 
147     // HelloRetryRequest
148     NamedGroup                              serverSelectedNamedGroup;
149 
150     // if server name indicator is negotiated
151     //
152     // May need a public API for the indication in the future.
153     List<SNIServerName>                     requestedServerNames;
154     SNIServerName                           negotiatedServerName;
155 
156     // OCSP Stapling info
157     boolean                                 staplingActive = false;
158 
HandshakeContext(SSLContextImpl sslContext, TransportContext conContext)159     protected HandshakeContext(SSLContextImpl sslContext,
160             TransportContext conContext) throws IOException {
161         this.sslContext = sslContext;
162         this.conContext = conContext;
163         this.sslConfig = (SSLConfiguration)conContext.sslConfig.clone();
164 
165         this.algorithmConstraints = new SSLAlgorithmConstraints(
166                 sslConfig.userSpecifiedAlgorithmConstraints);
167         this.activeProtocols = getActiveProtocols(sslConfig.enabledProtocols,
168                 sslConfig.enabledCipherSuites, algorithmConstraints);
169         if (activeProtocols.isEmpty()) {
170             throw new SSLHandshakeException(
171                 "No appropriate protocol (protocol is disabled or " +
172                 "cipher suites are inappropriate)");
173         }
174 
175         ProtocolVersion maximumVersion = ProtocolVersion.NONE;
176         for (ProtocolVersion pv : this.activeProtocols) {
177             if (maximumVersion == ProtocolVersion.NONE ||
178                     pv.compare(maximumVersion) > 0) {
179                 maximumVersion = pv;
180             }
181         }
182         this.maximumActiveProtocol = maximumVersion;
183         this.activeCipherSuites = getActiveCipherSuites(this.activeProtocols,
184                 sslConfig.enabledCipherSuites, algorithmConstraints);
185         if (activeCipherSuites.isEmpty()) {
186             throw new SSLHandshakeException("No appropriate cipher suite");
187         }
188 
189         this.handshakeConsumers = new LinkedHashMap<>();
190         this.handshakeProducers = new HashMap<>();
191         this.handshakeHash = conContext.inputRecord.handshakeHash;
192         this.handshakeOutput = new HandshakeOutStream(conContext.outputRecord);
193 
194         this.handshakeFinished = false;
195         this.kickstartMessageDelivered = false;
196 
197         this.delegatedActions = new LinkedList<>();
198         this.handshakeExtensions = new HashMap<>();
199         this.handshakePossessions = new LinkedList<>();
200         this.handshakeCredentials = new LinkedList<>();
201         this.requestedServerNames = null;
202         this.negotiatedServerName = null;
203         this.negotiatedCipherSuite = conContext.cipherSuite;
204         initialize();
205     }
206 
207     /**
208      * Constructor for PostHandshakeContext
209      */
HandshakeContext(TransportContext conContext)210     protected HandshakeContext(TransportContext conContext) {
211         this.sslContext = conContext.sslContext;
212         this.conContext = conContext;
213         this.sslConfig = conContext.sslConfig;
214 
215         this.negotiatedProtocol = conContext.protocolVersion;
216         this.negotiatedCipherSuite = conContext.cipherSuite;
217         this.handshakeOutput = new HandshakeOutStream(conContext.outputRecord);
218         this.delegatedActions = new LinkedList<>();
219 
220         this.handshakeConsumers = new LinkedHashMap<>();
221         this.handshakeProducers = null;
222         this.handshakeHash = null;
223         this.activeProtocols = null;
224         this.activeCipherSuites = null;
225         this.algorithmConstraints = null;
226         this.maximumActiveProtocol = null;
227         this.handshakeExtensions = Collections.emptyMap();  // Not in TLS13
228         this.handshakePossessions = null;
229         this.handshakeCredentials = null;
230     }
231 
232     // Initialize the non-final class variables.
initialize()233     private void initialize() {
234         ProtocolVersion inputHelloVersion;
235         ProtocolVersion outputHelloVersion;
236         if (conContext.isNegotiated) {
237             inputHelloVersion = conContext.protocolVersion;
238             outputHelloVersion = conContext.protocolVersion;
239         } else {
240             if (activeProtocols.contains(ProtocolVersion.SSL20Hello)) {
241                 inputHelloVersion = ProtocolVersion.SSL20Hello;
242 
243                 // Per TLS 1.3 protocol, implementation MUST NOT send an SSL
244                 // version 2.0 compatible CLIENT-HELLO.
245                 if (maximumActiveProtocol.useTLS13PlusSpec()) {
246                     outputHelloVersion = maximumActiveProtocol;
247                 } else {
248                     outputHelloVersion = ProtocolVersion.SSL20Hello;
249                 }
250             } else {
251                 inputHelloVersion = maximumActiveProtocol;
252                 outputHelloVersion = maximumActiveProtocol;
253             }
254         }
255 
256         conContext.inputRecord.setHelloVersion(inputHelloVersion);
257         conContext.outputRecord.setHelloVersion(outputHelloVersion);
258 
259         if (!conContext.isNegotiated) {
260             conContext.protocolVersion = maximumActiveProtocol;
261         }
262         conContext.outputRecord.setVersion(conContext.protocolVersion);
263     }
264 
getActiveProtocols( List<ProtocolVersion> enabledProtocols, List<CipherSuite> enabledCipherSuites, AlgorithmConstraints algorithmConstraints)265     private static List<ProtocolVersion> getActiveProtocols(
266             List<ProtocolVersion> enabledProtocols,
267             List<CipherSuite> enabledCipherSuites,
268             AlgorithmConstraints algorithmConstraints) {
269         boolean enabledSSL20Hello = false;
270         ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
271         for (ProtocolVersion protocol : enabledProtocols) {
272             if (!enabledSSL20Hello && protocol == ProtocolVersion.SSL20Hello) {
273                 enabledSSL20Hello = true;
274                 continue;
275             }
276 
277             if (!algorithmConstraints.permits(
278                     EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
279                     protocol.name, null)) {
280                 // Ignore disabled protocol.
281                 continue;
282             }
283 
284             boolean found = false;
285             Map<NamedGroupSpec, Boolean> cachedStatus =
286                     new EnumMap<>(NamedGroupSpec.class);
287             for (CipherSuite suite : enabledCipherSuites) {
288                 if (suite.isAvailable() && suite.supports(protocol)) {
289                     if (isActivatable(suite,
290                             algorithmConstraints, cachedStatus)) {
291                         protocols.add(protocol);
292                         found = true;
293                         break;
294                     }
295                 } else if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
296                     SSLLogger.fine(
297                         "Ignore unsupported cipher suite: " + suite +
298                              " for " + protocol);
299                 }
300             }
301 
302             if (!found && (SSLLogger.isOn) && SSLLogger.isOn("handshake")) {
303                 SSLLogger.fine(
304                     "No available cipher suite for " + protocol);
305             }
306         }
307 
308         if (!protocols.isEmpty()) {
309             if (enabledSSL20Hello) {
310                 protocols.add(ProtocolVersion.SSL20Hello);
311             }
312             Collections.sort(protocols);
313         }
314 
315         return Collections.unmodifiableList(protocols);
316     }
317 
getActiveCipherSuites( List<ProtocolVersion> enabledProtocols, List<CipherSuite> enabledCipherSuites, AlgorithmConstraints algorithmConstraints)318     private static List<CipherSuite> getActiveCipherSuites(
319             List<ProtocolVersion> enabledProtocols,
320             List<CipherSuite> enabledCipherSuites,
321             AlgorithmConstraints algorithmConstraints) {
322 
323         List<CipherSuite> suites = new LinkedList<>();
324         if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
325             Map<NamedGroupSpec, Boolean> cachedStatus =
326                     new EnumMap<>(NamedGroupSpec.class);
327             for (CipherSuite suite : enabledCipherSuites) {
328                 if (!suite.isAvailable()) {
329                     continue;
330                 }
331 
332                 boolean isSupported = false;
333                 for (ProtocolVersion protocol : enabledProtocols) {
334                     if (!suite.supports(protocol)) {
335                         continue;
336                     }
337                     if (isActivatable(suite,
338                             algorithmConstraints, cachedStatus)) {
339                         suites.add(suite);
340                         isSupported = true;
341                         break;
342                     }
343                 }
344 
345                 if (!isSupported &&
346                         SSLLogger.isOn && SSLLogger.isOn("verbose")) {
347                     SSLLogger.finest(
348                             "Ignore unsupported cipher suite: " + suite);
349                 }
350             }
351         }
352 
353         return Collections.unmodifiableList(suites);
354     }
355 
356     /**
357      * Parse the handshake record and return the contentType
358      */
getHandshakeType(TransportContext conContext, Plaintext plaintext)359     static byte getHandshakeType(TransportContext conContext,
360             Plaintext plaintext) throws IOException {
361         //     struct {
362         //         HandshakeType msg_type;    /* handshake type */
363         //         uint24 length;             /* bytes in message */
364         //         select (HandshakeType) {
365         //             ...
366         //         } body;
367         //     } Handshake;
368 
369         if (plaintext.contentType != ContentType.HANDSHAKE.id) {
370             throw conContext.fatal(Alert.INTERNAL_ERROR,
371                 "Unexpected operation for record: " + plaintext.contentType);
372         }
373 
374         if (plaintext.fragment == null || plaintext.fragment.remaining() < 4) {
375             throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
376                     "Invalid handshake message: insufficient data");
377         }
378 
379         byte handshakeType = (byte)Record.getInt8(plaintext.fragment);
380         int handshakeLen = Record.getInt24(plaintext.fragment);
381         if (handshakeLen != plaintext.fragment.remaining()) {
382             throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
383                     "Invalid handshake message: insufficient handshake body");
384         }
385 
386         return handshakeType;
387     }
388 
dispatch(byte handshakeType, Plaintext plaintext)389     void dispatch(byte handshakeType, Plaintext plaintext) throws IOException {
390         if (conContext.transport.useDelegatedTask()) {
391             boolean hasDelegated = !delegatedActions.isEmpty();
392             if (hasDelegated ||
393                    (handshakeType != SSLHandshake.FINISHED.id &&
394                     handshakeType != SSLHandshake.KEY_UPDATE.id &&
395                     handshakeType != SSLHandshake.NEW_SESSION_TICKET.id)) {
396                 if (!hasDelegated) {
397                     taskDelegated = false;
398                     delegatedThrown = null;
399                 }
400 
401                 // Clone the fragment for delegated actions.
402                 //
403                 // The plaintext may share the application buffers.  It is
404                 // fine to use shared buffers if no delegated actions.
405                 // However, for delegated actions, the shared buffers may be
406                 // polluted in application layer before the delegated actions
407                 // executed.
408                 ByteBuffer fragment = ByteBuffer.wrap(
409                         new byte[plaintext.fragment.remaining()]);
410                 fragment.put(plaintext.fragment);
411                 fragment = fragment.rewind();
412 
413                 delegatedActions.add(new SimpleImmutableEntry<>(
414                         handshakeType,
415                         fragment
416                     ));
417             } else {
418                 dispatch(handshakeType, plaintext.fragment);
419             }
420         } else {
421             dispatch(handshakeType, plaintext.fragment);
422         }
423     }
424 
dispatch(byte handshakeType, ByteBuffer fragment)425     void dispatch(byte handshakeType,
426             ByteBuffer fragment) throws IOException {
427         SSLConsumer consumer;
428         if (handshakeType == SSLHandshake.HELLO_REQUEST.id) {
429             // For TLS 1.2 and prior versions, the HelloRequest message MAY
430             // be sent by the server at any time.
431             consumer = SSLHandshake.HELLO_REQUEST;
432         } else {
433             consumer = handshakeConsumers.get(handshakeType);
434         }
435 
436         if (consumer == null) {
437             throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
438                     "Unexpected handshake message: " +
439                     SSLHandshake.nameOf(handshakeType));
440         }
441 
442         try {
443             consumer.consume(this, fragment);
444         } catch (UnsupportedOperationException unsoe) {
445             throw conContext.fatal(Alert.UNEXPECTED_MESSAGE,
446                     "Unsupported handshake message: " +
447                     SSLHandshake.nameOf(handshakeType), unsoe);
448         } catch (BufferUnderflowException | BufferOverflowException be) {
449             throw conContext.fatal(Alert.DECODE_ERROR,
450                     "Illegal handshake message: " +
451                     SSLHandshake.nameOf(handshakeType), be);
452         }
453 
454         // update handshake hash after handshake message consumption.
455         handshakeHash.consume();
456     }
457 
kickstart()458     abstract void kickstart() throws IOException;
459 
460     /**
461      * Check if the given cipher suite is enabled and available within
462      * the current active cipher suites.
463      *
464      * Does not check if the required server certificates are available.
465      */
isNegotiable(CipherSuite cs)466     boolean isNegotiable(CipherSuite cs) {
467         return isNegotiable(activeCipherSuites, cs);
468     }
469 
470     /**
471      * Check if the given cipher suite is enabled and available within
472      * the proposed cipher suite list.
473      *
474      * Does not check if the required server certificates are available.
475      */
isNegotiable( List<CipherSuite> proposed, CipherSuite cs)476     static final boolean isNegotiable(
477             List<CipherSuite> proposed, CipherSuite cs) {
478         return proposed.contains(cs) && cs.isNegotiable();
479     }
480 
481     /**
482      * Check if the given cipher suite is enabled and available within
483      * the proposed cipher suite list and specific protocol version.
484      *
485      * Does not check if the required server certificates are available.
486      */
isNegotiable(List<CipherSuite> proposed, ProtocolVersion protocolVersion, CipherSuite cs)487     static final boolean isNegotiable(List<CipherSuite> proposed,
488             ProtocolVersion protocolVersion, CipherSuite cs) {
489         return proposed.contains(cs) &&
490                 cs.isNegotiable() && cs.supports(protocolVersion);
491     }
492 
493     /**
494      * Check if the given protocol version is enabled and available.
495      */
isNegotiable(ProtocolVersion protocolVersion)496     boolean isNegotiable(ProtocolVersion protocolVersion) {
497         return activeProtocols.contains(protocolVersion);
498     }
499 
500     /**
501      * Set the active protocol version and propagate it to the SSLSocket
502      * and our handshake streams. Called from ClientHandshaker
503      * and ServerHandshaker with the negotiated protocol version.
504      */
setVersion(ProtocolVersion protocolVersion)505     void setVersion(ProtocolVersion protocolVersion) {
506         this.conContext.protocolVersion = protocolVersion;
507     }
508 
isActivatable(CipherSuite suite, AlgorithmConstraints algorithmConstraints, Map<NamedGroupSpec, Boolean> cachedStatus)509     private static boolean isActivatable(CipherSuite suite,
510             AlgorithmConstraints algorithmConstraints,
511             Map<NamedGroupSpec, Boolean> cachedStatus) {
512 
513         if (algorithmConstraints.permits(
514                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
515             if (suite.keyExchange == null) {
516                 // TLS 1.3, no definition of key exchange in cipher suite.
517                 return true;
518             }
519 
520             // Is at least one of the group types available?
521             boolean groupAvailable, retval = false;
522             NamedGroupSpec[] groupTypes = suite.keyExchange.groupTypes;
523             for (NamedGroupSpec groupType : groupTypes) {
524                 if (groupType != NAMED_GROUP_NONE) {
525                     Boolean checkedStatus = cachedStatus.get(groupType);
526                     if (checkedStatus == null) {
527                         groupAvailable = SupportedGroups.isActivatable(
528                                 algorithmConstraints, groupType);
529                         cachedStatus.put(groupType, groupAvailable);
530 
531                         if (!groupAvailable &&
532                                 SSLLogger.isOn && SSLLogger.isOn("verbose")) {
533                             SSLLogger.fine(
534                                     "No activated named group in " + groupType);
535                         }
536                     } else {
537                         groupAvailable = checkedStatus;
538                     }
539 
540                     retval |= groupAvailable;
541                 } else {
542                     retval |= true;
543                 }
544             }
545 
546             if (!retval && SSLLogger.isOn && SSLLogger.isOn("verbose")) {
547                 SSLLogger.fine("No active named group(s), ignore " + suite);
548             }
549 
550             return retval;
551 
552         } else if (SSLLogger.isOn && SSLLogger.isOn("verbose")) {
553             SSLLogger.fine("Ignore disabled cipher suite: " + suite);
554         }
555 
556         return false;
557     }
558 
getRequestedServerNames()559     List<SNIServerName> getRequestedServerNames() {
560         if (requestedServerNames == null) {
561             return Collections.<SNIServerName>emptyList();
562         }
563         return requestedServerNames;
564     }
565 }
566 
567