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.NamedGroupType;
  50 import static sun.security.ssl.NamedGroup.NamedGroupType.*;
  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 
 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      */
 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.
 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 
 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<NamedGroupType, Boolean> cachedStatus =
 286                     new EnumMap<>(NamedGroupType.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 
 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<NamedGroupType, Boolean> cachedStatus =
 326                     new EnumMap<>(NamedGroupType.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      */
 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 
 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 
 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 
 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      */
 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      */
 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      */
 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      */
 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      */
 505     void setVersion(ProtocolVersion protocolVersion) {
 506         this.conContext.protocolVersion = protocolVersion;
 507     }
 508 
 509     private static boolean isActivatable(CipherSuite suite,
 510             AlgorithmConstraints algorithmConstraints,
 511             Map<NamedGroupType, 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             NamedGroupType[] groupTypes = suite.keyExchange.groupTypes;
 523             for (NamedGroupType 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 
 559     List<SNIServerName> getRequestedServerNames() {
 560         if (requestedServerNames == null) {
 561             return Collections.<SNIServerName>emptyList();
 562         }
 563         return requestedServerNames;
 564     }
 565 }
 566