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