src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java
changeset 50768 68fa3d4026ea
parent 48373 f9152f462cbc
child 53064 103ed9569fc8
equal deleted inserted replaced
50767:356eaea05bf0 50768:68fa3d4026ea
     1 /*
     1 /*
     2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
     2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
       
     3  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * 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  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     8  * published by the Free Software Foundation.  Oracle designates this
    24  */
    25  */
    25 
    26 
    26 package sun.security.ssl;
    27 package sun.security.ssl;
    27 
    28 
    28 import java.io.IOException;
    29 import java.io.IOException;
       
    30 import java.nio.ByteBuffer;
    29 import javax.net.ssl.SSLProtocolException;
    31 import javax.net.ssl.SSLProtocolException;
       
    32 import static sun.security.ssl.SSLExtension.CH_EXTENDED_MASTER_SECRET;
       
    33 import sun.security.ssl.SSLExtension.ExtensionConsumer;
       
    34 import static sun.security.ssl.SSLExtension.SH_EXTENDED_MASTER_SECRET;
       
    35 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
       
    36 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    30 
    37 
    31 /**
    38 /**
    32  * Extended Master Secret TLS extension (TLS 1.0+). This extension
    39  * Pack of the "extended_master_secret" extensions [RFC 7627].
    33  * defines how to calculate the TLS connection master secret and
       
    34  * mitigates some types of man-in-the-middle attacks.
       
    35  *
       
    36  * See further information in
       
    37  * <a href="https://tools.ietf.org/html/rfc7627">RFC 7627</a>.
       
    38  *
       
    39  * @author Martin Balao (mbalao@redhat.com)
       
    40  */
    40  */
    41 final class ExtendedMasterSecretExtension extends HelloExtension {
    41 final class ExtendedMasterSecretExtension {
    42     ExtendedMasterSecretExtension() {
    42     static final HandshakeProducer chNetworkProducer =
    43         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
    43             new CHExtendedMasterSecretProducer();
    44     }
    44     static final ExtensionConsumer chOnLoadConsumer =
    45 
    45             new CHExtendedMasterSecretConsumer();
    46     ExtendedMasterSecretExtension(HandshakeInStream s,
    46     static final HandshakeAbsence chOnLoadAbsence =
    47             int len) throws IOException {
    47             new CHExtendedMasterSecretAbsence();
    48         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
    48 
    49 
    49     static final HandshakeProducer shNetworkProducer =
    50         if (len != 0) {
    50             new SHExtendedMasterSecretProducer();
    51             throw new SSLProtocolException("Invalid " + type + " extension");
    51     static final ExtensionConsumer shOnLoadConsumer =
    52         }
    52             new SHExtendedMasterSecretConsumer();
    53     }
    53     static final HandshakeAbsence shOnLoadAbsence =
    54 
    54             new SHExtendedMasterSecretAbsence();
    55     @Override
    55 
    56     int length() {
    56     static final SSLStringizer emsStringizer =
    57         return 4;       // 4: extension type and length fields
    57             new ExtendedMasterSecretStringizer();
    58     }
    58 
    59 
    59     /**
    60     @Override
    60      * The "extended_master_secret" extension.
    61     void send(HandshakeOutStream s) throws IOException {
    61      */
    62         s.putInt16(type.id);    // ExtensionType extension_type;
    62     static final class ExtendedMasterSecretSpec implements SSLExtensionSpec {
    63         s.putInt16(0);          // extension_data length
    63         // A nominal object that does not holding any real renegotiation info.
    64     }
    64         static final ExtendedMasterSecretSpec NOMINAL =
    65 
    65                 new ExtendedMasterSecretSpec();
    66     @Override
    66 
    67     public String toString() {
    67         private ExtendedMasterSecretSpec() {
    68         return "Extension " + type;
    68             // blank
       
    69         }
       
    70 
       
    71         private ExtendedMasterSecretSpec(ByteBuffer m) throws IOException {
       
    72             // Parse the extension.
       
    73             if (m.hasRemaining()) {
       
    74                 throw new SSLProtocolException(
       
    75                     "Invalid extended_master_secret extension data: " +
       
    76                     "not empty");
       
    77             }
       
    78         }
       
    79 
       
    80         @Override
       
    81         public String toString() {
       
    82             return "<empty>";
       
    83         }
       
    84     }
       
    85 
       
    86     private static final
       
    87             class ExtendedMasterSecretStringizer implements SSLStringizer {
       
    88         @Override
       
    89         public String toString(ByteBuffer buffer) {
       
    90             try {
       
    91                 return (new ExtendedMasterSecretSpec(buffer)).toString();
       
    92             } catch (IOException ioe) {
       
    93                 // For debug logging only, so please swallow exceptions.
       
    94                 return ioe.getMessage();
       
    95             }
       
    96         }
       
    97     }
       
    98 
       
    99     /**
       
   100      * Network data producer of a "extended_master_secret" extension in
       
   101      * the ClientHello handshake message.
       
   102      */
       
   103     private static final
       
   104             class CHExtendedMasterSecretProducer implements HandshakeProducer {
       
   105         // Prevent instantiation of this class.
       
   106         private CHExtendedMasterSecretProducer() {
       
   107             // blank
       
   108         }
       
   109 
       
   110         @Override
       
   111         public byte[] produce(ConnectionContext context,
       
   112                 HandshakeMessage message) throws IOException {
       
   113             // The producing happens in client side only.
       
   114             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   115 
       
   116             // Is it a supported and enabled extension?
       
   117             if (!chc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||
       
   118                     !SSLConfiguration.useExtendedMasterSecret ||
       
   119                     !chc.conContext.protocolVersion.useTLS10PlusSpec()) {
       
   120                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   121                     SSLLogger.fine(
       
   122                         "Ignore unavailable extended_master_secret extension");
       
   123                 }
       
   124 
       
   125                 return null;
       
   126             }
       
   127 
       
   128             if (chc.handshakeSession == null ||
       
   129                     chc.handshakeSession.useExtendedMasterSecret) {
       
   130                 byte[] extData = new byte[0];
       
   131                 chc.handshakeExtensions.put(CH_EXTENDED_MASTER_SECRET,
       
   132                         ExtendedMasterSecretSpec.NOMINAL);
       
   133 
       
   134                 return extData;
       
   135             }
       
   136 
       
   137             return null;
       
   138         }
       
   139     }
       
   140 
       
   141     /**
       
   142      * Network data producer of a "extended_master_secret" extension in
       
   143      * the ServerHello handshake message.
       
   144      */
       
   145     private static final
       
   146             class CHExtendedMasterSecretConsumer implements ExtensionConsumer {
       
   147         // Prevent instantiation of this class.
       
   148         private CHExtendedMasterSecretConsumer() {
       
   149             // blank
       
   150         }
       
   151 
       
   152         @Override
       
   153         public void consume(ConnectionContext context,
       
   154             HandshakeMessage message, ByteBuffer buffer) throws IOException {
       
   155 
       
   156             // The consuming happens in server side only.
       
   157             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   158 
       
   159             // Is it a supported and enabled extension?
       
   160             if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||
       
   161                     !SSLConfiguration.useExtendedMasterSecret ||
       
   162                     !shc.negotiatedProtocol.useTLS10PlusSpec()) {
       
   163                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   164                     SSLLogger.fine("Ignore unavailable extension: " +
       
   165                             CH_EXTENDED_MASTER_SECRET.name);
       
   166                 }
       
   167                 return;     // ignore the extension
       
   168             }
       
   169 
       
   170             // Parse the extension.
       
   171             ExtendedMasterSecretSpec spec;
       
   172             try {
       
   173                 spec = new ExtendedMasterSecretSpec(buffer);
       
   174             } catch (IOException ioe) {
       
   175                 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
       
   176                 return;     // fatal() always throws, make the compiler happy.
       
   177             }
       
   178 
       
   179             if (shc.isResumption && shc.resumingSession != null &&
       
   180                     !shc.resumingSession.useExtendedMasterSecret) {
       
   181                 // For abbreviated handshake request, If the original
       
   182                 // session did not use the "extended_master_secret"
       
   183                 // extension but the new ClientHello contains the
       
   184                 // extension, then the server MUST NOT perform the
       
   185                 // abbreviated handshake.  Instead, it SHOULD continue
       
   186                 // with a full handshake.
       
   187                 shc.isResumption = false;
       
   188                 shc.resumingSession = null;
       
   189                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   190                     SSLLogger.fine(
       
   191                         "abort session resumption which did not use " +
       
   192                         "Extended Master Secret extension");
       
   193                 }
       
   194             }
       
   195 
       
   196             // Update the context.
       
   197             //
       
   198             shc.handshakeExtensions.put(
       
   199                 CH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);
       
   200 
       
   201             // No impact on session resumption.
       
   202         }
       
   203     }
       
   204 
       
   205     /**
       
   206      * The absence processing if a "extended_master_secret" extension is
       
   207      * not present in the ClientHello handshake message.
       
   208      */
       
   209     private static final
       
   210             class CHExtendedMasterSecretAbsence implements HandshakeAbsence {
       
   211         @Override
       
   212         public void absent(ConnectionContext context,
       
   213                 HandshakeMessage message) throws IOException {
       
   214             // The producing happens in server side only.
       
   215             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   216 
       
   217             // Is it a supported and enabled extension?
       
   218             if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET) ||
       
   219                     !SSLConfiguration.useExtendedMasterSecret) {
       
   220                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   221                     SSLLogger.fine("Ignore unavailable extension: " +
       
   222                             CH_EXTENDED_MASTER_SECRET.name);
       
   223                 }
       
   224                 return;     // ignore the extension
       
   225             }
       
   226 
       
   227             if (shc.negotiatedProtocol.useTLS10PlusSpec() &&
       
   228                     !SSLConfiguration.allowLegacyMasterSecret) {
       
   229                 // For full handshake, if the server receives a ClientHello
       
   230                 // without the extension, it SHOULD abort the handshake if
       
   231                 // it does not wish to interoperate with legacy clients.
       
   232                 //
       
   233                 // As if extended master extension is required for full
       
   234                 // handshake, it MUST be used in abbreviated handshake too.
       
   235                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   236                     "Extended Master Secret extension is required");
       
   237             }
       
   238 
       
   239             if (shc.isResumption && shc.resumingSession != null) {
       
   240                 if (shc.resumingSession.useExtendedMasterSecret) {
       
   241                     // For abbreviated handshake request, if the original
       
   242                     // session used the "extended_master_secret" extension
       
   243                     // but the new ClientHello does not contain it, the
       
   244                     // server MUST abort the abbreviated handshake.
       
   245                     shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   246                             "Missing Extended Master Secret extension " +
       
   247                             "on session resumption");
       
   248                 } else {
       
   249                     // For abbreviated handshake request, if neither the
       
   250                     // original session nor the new ClientHello uses the
       
   251                     // extension, the server SHOULD abort the handshake.
       
   252                     if (!SSLConfiguration.allowLegacyResumption) {
       
   253                         shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   254                             "Missing Extended Master Secret extension " +
       
   255                             "on session resumption");
       
   256                     } else {  // Otherwise, continue with a full handshake.
       
   257                         shc.isResumption = false;
       
   258                         shc.resumingSession = null;
       
   259                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
       
   260                             SSLLogger.fine(
       
   261                                 "abort session resumption, " +
       
   262                                 "missing Extended Master Secret extension");
       
   263                         }
       
   264                     }
       
   265                 }
       
   266             }
       
   267         }
       
   268     }
       
   269 
       
   270     /**
       
   271      * Network data producer of a "extended_master_secret" extension in
       
   272      * the ServerHello handshake message.
       
   273      */
       
   274     private static final
       
   275             class SHExtendedMasterSecretProducer implements HandshakeProducer {
       
   276         // Prevent instantiation of this class.
       
   277         private SHExtendedMasterSecretProducer() {
       
   278             // blank
       
   279         }
       
   280 
       
   281         @Override
       
   282         public byte[] produce(ConnectionContext context,
       
   283                 HandshakeMessage message) throws IOException {
       
   284             // The producing happens in server side only.
       
   285             ServerHandshakeContext shc = (ServerHandshakeContext)context;
       
   286 
       
   287             if (shc.handshakeSession.useExtendedMasterSecret) {
       
   288                 byte[] extData = new byte[0];
       
   289                 shc.handshakeExtensions.put(SH_EXTENDED_MASTER_SECRET,
       
   290                         ExtendedMasterSecretSpec.NOMINAL);
       
   291 
       
   292                 return extData;
       
   293             }
       
   294 
       
   295             return null;
       
   296         }
       
   297     }
       
   298 
       
   299     /**
       
   300      * Network data consumer of a "extended_master_secret" extension in
       
   301      * the ServerHello handshake message.
       
   302      */
       
   303     private static final
       
   304             class SHExtendedMasterSecretConsumer implements ExtensionConsumer {
       
   305         // Prevent instantiation of this class.
       
   306         private SHExtendedMasterSecretConsumer() {
       
   307             // blank
       
   308         }
       
   309 
       
   310         @Override
       
   311         public void consume(ConnectionContext context,
       
   312             HandshakeMessage message, ByteBuffer buffer) throws IOException {
       
   313             // The producing happens in client side only.
       
   314             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   315 
       
   316             // In response to the client extended_master_secret extension
       
   317             // request, which is mandatory for ClientHello message.
       
   318             ExtendedMasterSecretSpec requstedSpec = (ExtendedMasterSecretSpec)
       
   319                     chc.handshakeExtensions.get(CH_EXTENDED_MASTER_SECRET);
       
   320             if (requstedSpec == null) {
       
   321                 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,
       
   322                         "Server sent the extended_master_secret " +
       
   323                         "extension improperly");
       
   324             }
       
   325 
       
   326             // Parse the extension.
       
   327             ExtendedMasterSecretSpec spec;
       
   328             try {
       
   329                 spec = new ExtendedMasterSecretSpec(buffer);
       
   330             } catch (IOException ioe) {
       
   331                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
       
   332                 return;     // fatal() always throws, make the compiler happy.
       
   333             }
       
   334 
       
   335             if (chc.isResumption && chc.resumingSession != null &&
       
   336                     !chc.resumingSession.useExtendedMasterSecret) {
       
   337                 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,
       
   338                         "Server sent an unexpected extended_master_secret " +
       
   339                         "extension on session resumption");
       
   340             }
       
   341 
       
   342             // Update the context.
       
   343             chc.handshakeExtensions.put(
       
   344                 SH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);
       
   345 
       
   346             // No impact on session resumption.
       
   347         }
       
   348     }
       
   349 
       
   350     /**
       
   351      * The absence processing if a "extended_master_secret" extension is
       
   352      * not present in the ServerHello handshake message.
       
   353      */
       
   354     private static final
       
   355             class SHExtendedMasterSecretAbsence implements HandshakeAbsence {
       
   356         @Override
       
   357         public void absent(ConnectionContext context,
       
   358                 HandshakeMessage message) throws IOException {
       
   359             // The producing happens in client side only.
       
   360             ClientHandshakeContext chc = (ClientHandshakeContext)context;
       
   361 
       
   362             if (SSLConfiguration.useExtendedMasterSecret &&
       
   363                     !SSLConfiguration.allowLegacyMasterSecret) {
       
   364                 // For full handshake, if a client receives a ServerHello
       
   365                 // without the extension, it SHOULD abort the handshake if
       
   366                 // it does not wish to interoperate with legacy servers.
       
   367                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   368                         "Extended Master Secret extension is required");
       
   369             }
       
   370 
       
   371             if (chc.isResumption && chc.resumingSession != null) {
       
   372                 if (chc.resumingSession.useExtendedMasterSecret) {
       
   373                     // For abbreviated handshake, if the original session used
       
   374                     // the "extended_master_secret" extension but the new
       
   375                     // ServerHello does not contain the extension, the client
       
   376                     // MUST abort the handshake.
       
   377                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   378                             "Missing Extended Master Secret extension " +
       
   379                             "on session resumption");
       
   380                 } else if (SSLConfiguration.useExtendedMasterSecret &&
       
   381                         !SSLConfiguration.allowLegacyResumption &&
       
   382                         chc.negotiatedProtocol.useTLS10PlusSpec()) {
       
   383                     // Unlikely, abbreviated handshake should be discarded.
       
   384                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
       
   385                         "Extended Master Secret extension is required");
       
   386                 }
       
   387             }
       
   388         }
    69     }
   389     }
    70 }
   390 }
    71 
   391