< prev index next >

src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java

Print this page


   1 /*
   2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
   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 javax.net.ssl.SSLProtocolException;







  30 
  31 /**
  32  * Extended Master Secret TLS extension (TLS 1.0+). This extension
  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  */
  41 final class ExtendedMasterSecretExtension extends HelloExtension {
  42     ExtendedMasterSecretExtension() {
  43         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);




  44     }
  45 
  46     ExtendedMasterSecretExtension(HandshakeInStream s,
  47             int len) throws IOException {
  48         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);





  49 
  50         if (len != 0) {
  51             throw new SSLProtocolException("Invalid " + type + " extension");

  52         }
  53     }
  54 


  55     @Override
  56     int length() {
  57         return 4;       // 4: extension type and length fields

























































  58     }
  59 
  60     @Override
  61     void send(HandshakeOutStream s) throws IOException {
  62         s.putInt16(type.id);    // ExtensionType extension_type;
  63         s.putInt16(0);          // extension_data length










  64     }
  65 









































  66     @Override
  67     public String toString() {
  68         return "Extension " + type;












































































































































































  69     }
  70 }
  71 
   1 /*
   2  * Copyright (c) 2017, 2018, Red Hat, Inc. and/or its affiliates.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package sun.security.ssl;
  27 
  28 import java.io.IOException;
  29 import java.nio.ByteBuffer;
  30 import javax.net.ssl.SSLProtocolException;
  31 import static sun.security.ssl.SSLConfiguration.allowLegacyMasterSecret;
  32 import static sun.security.ssl.SSLConfiguration.allowLegacyResumption;
  33 import static sun.security.ssl.SSLExtension.CH_EXTENDED_MASTER_SECRET;
  34 import sun.security.ssl.SSLExtension.ExtensionConsumer;
  35 import static sun.security.ssl.SSLExtension.SH_EXTENDED_MASTER_SECRET;
  36 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
  37 import sun.security.ssl.SSLHandshake.HandshakeMessage;
  38 
  39 /**
  40  * Pack of the "extended_master_secret" extensions [RFC 5746].
  41  */
  42 final class ExtendedMasterSecretExtension {
  43     static final HandshakeProducer chNetworkProducer =
  44             new CHExtendedMasterSecretProducer();
  45     static final ExtensionConsumer chOnLoadConcumer =
  46             new CHExtendedMasterSecretConsumer();
  47     static final HandshakeAbsence chOnLoadAbsence =
  48             new CHExtendedMasterSecretAbsence();
  49 
  50     static final HandshakeProducer shNetworkProducer =
  51             new SHExtendedMasterSecretProducer();
  52     static final ExtensionConsumer shOnLoadConcumer =
  53             new SHExtendedMasterSecretConsumer();
  54     static final HandshakeAbsence shOnLoadAbsence =
  55             new SHExtendedMasterSecretAbsence();
  56 
  57     static final SSLStringize emsStringize =
  58             new ExtendedMasterSecretStringize();
  59 
  60     /**
  61      * The "extended_master_secret" extension.
  62      */
  63     static final class ExtendedMasterSecretSpec implements SSLExtensionSpec {
  64         // A nominal object that does not holding any real renegotiation info.
  65         static final ExtendedMasterSecretSpec NOMINAL =
  66                 new ExtendedMasterSecretSpec();
  67 
  68         private ExtendedMasterSecretSpec() {
  69             // blank
  70         }
  71 
  72         private ExtendedMasterSecretSpec(ByteBuffer m) throws IOException {
  73             // Parse the extension.
  74             if (m.hasRemaining()) {
  75                 throw new SSLProtocolException(
  76                     "Invalid extended_master_secret extension data: " +
  77                     "not empty");
  78             }
  79         }
  80 
  81         @Override
  82         public String toString() {
  83             return "<empty>";
  84         }
  85     }
  86 
  87     private static final
  88             class ExtendedMasterSecretStringize implements SSLStringize {
  89         @Override
  90         public String toString(ByteBuffer buffer) {
  91             try {
  92                 return (new ExtendedMasterSecretSpec(buffer)).toString();
  93             } catch (IOException ioe) {
  94                 // For debug logging only, so please swallow exceptions.
  95                 return ioe.getMessage();
  96             }
  97         }
  98     }
  99 
 100     /**
 101      * Network data producer of a "extended_master_secret" extension in
 102      * the ClientHello handshake message.
 103      */
 104     private static final
 105             class CHExtendedMasterSecretProducer implements HandshakeProducer {
 106         // Prevent instantiation of this class.
 107         private CHExtendedMasterSecretProducer() {
 108             // blank
 109         }
 110 
 111         @Override
 112         public byte[] produce(ConnectionContext context,
 113                 HandshakeMessage message) throws IOException {
 114             // The producing happens in client side only.
 115             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 116 
 117             // Is it a supported and enabled extension?
 118             if (!chc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET)) {
 119                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 120                     SSLLogger.fine(
 121                         "Ignore unavailable extended_master_secret extension");
 122                 }
 123 
 124                 return null;
 125             }
 126 
 127             if (chc.handshakeSession == null ||
 128                     chc.handshakeSession.useExtendedMasterSecret) {
 129                 byte[] extData = new byte[0];
 130                 chc.handshakeExtensions.put(CH_EXTENDED_MASTER_SECRET,
 131                         ExtendedMasterSecretSpec.NOMINAL);
 132 
 133                 return extData;
 134             }
 135 
 136             return null;
 137         }
 138     }
 139 
 140     /**
 141      * Network data producer of a "extended_master_secret" extension in
 142      * the ServerHello handshake message.
 143      */
 144     private static final
 145             class CHExtendedMasterSecretConsumer implements ExtensionConsumer {
 146         // Prevent instantiation of this class.
 147         private CHExtendedMasterSecretConsumer() {
 148             // blank
 149         }
 150 
 151         @Override
 152         public void consume(ConnectionContext context,
 153             HandshakeMessage message, ByteBuffer buffer) throws IOException {
 154 
 155             // The comsuming happens in server side only.
 156             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 157 
 158             // Is it a supported and enabled extension?
 159             if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET)) {
 160                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 161                     SSLLogger.fine("Ignore unavailable extension: " +
 162                             CH_EXTENDED_MASTER_SECRET.name);
 163                 }
 164                 return;     // ignore the extension
 165             }
 166 
 167             // Parse the extension.
 168             ExtendedMasterSecretSpec spec;
 169             try {
 170                 spec = new ExtendedMasterSecretSpec(buffer);
 171             } catch (IOException ioe) {
 172                 shc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
 173                 return;     // fatal() always throws, make the compiler happy.
 174             }
 175 
 176             if (shc.isResumption && shc.resumingSession != null &&
 177                     !shc.resumingSession.useExtendedMasterSecret) {
 178                 // For abbreviated handshake request, If the original
 179                 // session did not use the "extended_master_secret"
 180                 // extension but the new ClientHello contains the
 181                 // extension, then the server MUST NOT perform the
 182                 // abbreviated handshake.  Instead, it SHOULD continue
 183                 // with a full handshake.
 184                 shc.isResumption = false;
 185                 shc.resumingSession = null;
 186                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 187                     SSLLogger.fine(
 188                         "abort session resumption which did not use " +
 189                         "Extended Master Secret extension");
 190                 }
 191             }
 192 
 193             // Update the context.
 194             //
 195             shc.handshakeExtensions.put(
 196                 CH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);
 197 
 198             // No impact on session resumption.
 199         }
 200     }
 201 
 202     /**
 203      * The absence processing if a "extended_master_secret" extension is
 204      * not present in the ClientHello handshake message.
 205      */
 206     private static final
 207             class CHExtendedMasterSecretAbsence implements HandshakeAbsence {
 208         @Override
 209         public void absent(ConnectionContext context,
 210                 HandshakeMessage message) throws IOException {
 211             // The producing happens in server side only.
 212             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 213 
 214             // Is it a supported and enabled extension?
 215             if (!shc.sslConfig.isAvailable(CH_EXTENDED_MASTER_SECRET)) {
 216                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 217                     SSLLogger.fine("Ignore unavailable extension: " +
 218                             CH_EXTENDED_MASTER_SECRET.name);
 219                 }
 220                 return;     // ignore the extension
 221             }
 222 
 223             if (!allowLegacyMasterSecret) {
 224                 // For full handshake, if the server receives a ClientHello
 225                 // without the extension, it SHOULD abort the handshake if
 226                 // it does not wish to interoperate with legacy clients.
 227                 //
 228                 // As if extended master extension is required for full
 229                 // handshake, it MUST be used in abbreviated handshake too.
 230                 shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 231                     "Extended Master Secret extension is required");
 232             }
 233 
 234             if (shc.isResumption && shc.resumingSession != null) {
 235                 if (shc.resumingSession.useExtendedMasterSecret) {
 236                     // For abbreviated handshake request, if the original
 237                     // session used the "extended_master_secret" extension
 238                     // but the new ClientHello does not contain it, the
 239                     // server MUST abort the abbreviated handshake.
 240                     shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 241                             "Missing Extended Master Secret extension " +
 242                             "on session resumption");
 243                 } else {
 244                     // For abbreviated handshake request, if neither the
 245                     // original session nor the new ClientHello uses the
 246                     // extension, the server SHOULD abort the handshake.
 247                     if (!allowLegacyResumption) {
 248                         shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 249                             "Missing Extended Master Secret extension " +
 250                             "on session resumption");
 251                     } else {  // Otherwise, continue with a full handshake.
 252                         shc.isResumption = false;
 253                         shc.resumingSession = null;
 254                         if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
 255                             SSLLogger.fine(
 256                                 "abort session resumption, " +
 257                                 "missing Extended Master Secret extension");
 258                         }
 259                     }
 260                 }
 261             }
 262         }
 263     }
 264 
 265     /**
 266      * Network data producer of a "extended_master_secret" extension in
 267      * the ServerHello handshake message.
 268      */
 269     private static final
 270             class SHExtendedMasterSecretProducer implements HandshakeProducer {
 271         // Prevent instantiation of this class.
 272         private SHExtendedMasterSecretProducer() {
 273             // blank
 274         }
 275 
 276         @Override
 277         public byte[] produce(ConnectionContext context,
 278                 HandshakeMessage message) throws IOException {
 279             // The producing happens in server side only.
 280             ServerHandshakeContext shc = (ServerHandshakeContext)context;
 281 
 282             if (shc.handshakeSession.useExtendedMasterSecret) {
 283                 byte[] extData = new byte[0];
 284                 shc.handshakeExtensions.put(SH_EXTENDED_MASTER_SECRET,
 285                         ExtendedMasterSecretSpec.NOMINAL);
 286 
 287                 return extData;
 288             }
 289 
 290             return null;
 291         }
 292     }
 293 
 294     /**
 295      * Network data consumer of a "extended_master_secret" extension in
 296      * the ServerHello handshake message.
 297      */
 298     private static final
 299             class SHExtendedMasterSecretConsumer implements ExtensionConsumer {
 300         // Prevent instantiation of this class.
 301         private SHExtendedMasterSecretConsumer() {
 302             // blank
 303         }
 304 
 305         @Override
 306         public void consume(ConnectionContext context,
 307             HandshakeMessage message, ByteBuffer buffer) throws IOException {
 308             // The producing happens in client side only.
 309             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 310 
 311             // In response to the client extended_master_secret extension
 312             // request, which is mandatory for ClientHello message.
 313             ExtendedMasterSecretSpec requstedSpec = (ExtendedMasterSecretSpec)
 314                     chc.handshakeExtensions.get(CH_EXTENDED_MASTER_SECRET);
 315             if (requstedSpec == null) {
 316                 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,
 317                         "Server sent the extended_master_secret " +
 318                         "extension improperly");
 319             }
 320 
 321             // Parse the extension.
 322             ExtendedMasterSecretSpec spec;
 323             try {
 324                 spec = new ExtendedMasterSecretSpec(buffer);
 325             } catch (IOException ioe) {
 326                 chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, ioe);
 327                 return;     // fatal() always throws, make the compiler happy.
 328             }
 329 
 330             if (chc.isResumption && chc.resumingSession != null &&
 331                     !chc.resumingSession.useExtendedMasterSecret) {
 332                 chc.conContext.fatal(Alert.UNSUPPORTED_EXTENSION,
 333                         "Server sent an unexpected extended_master_secret " +
 334                         "extension on session resumption");
 335             }
 336 
 337             // Update the context.
 338             chc.handshakeExtensions.put(
 339                 SH_EXTENDED_MASTER_SECRET, ExtendedMasterSecretSpec.NOMINAL);
 340 
 341             // No impact on session resumption.
 342         }
 343     }
 344 
 345     /**
 346      * The absence processing if a "extended_master_secret" extension is
 347      * not present in the ServerHello handshake message.
 348      */
 349     private static final
 350             class SHExtendedMasterSecretAbsence implements HandshakeAbsence {
 351         @Override
 352         public void absent(ConnectionContext context,
 353                 HandshakeMessage message) throws IOException {
 354             // The producing happens in client side only.
 355             ClientHandshakeContext chc = (ClientHandshakeContext)context;
 356 
 357             if (SSLConfiguration.useExtendedMasterSecret
 358                     && !SSLConfiguration.allowLegacyMasterSecret) {
 359                 // For full handshake, if a client receives a ServerHello
 360                 // without the extension, it SHOULD abort the handshake if
 361                 // it does not wish to interoperate with legacy servers.
 362                 chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 363                         "Extended Master Secret extension is required");
 364             }
 365 
 366             if (chc.isResumption && chc.resumingSession != null) {
 367                 if (chc.resumingSession.useExtendedMasterSecret) {
 368                     // For abbreviated handshake, if the original session used
 369                     // the "extended_master_secret" extension but the new
 370                     // ServerHello does not contain the extension, the client
 371                     // MUST abort the handshake.
 372                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 373                             "Missing Extended Master Secret extension " +
 374                             "on session resumption");
 375                 } else if (SSLConfiguration.useExtendedMasterSecret &&
 376                         !SSLConfiguration.allowLegacyResumption) {
 377                     // Unlikely, abbreviated handshake should be discarded.
 378                     chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
 379                         "Extended Master Secret extension is required");
 380                 }
 381             }
 382         }
 383     }
 384 }
 385 
< prev index next >