src/java.base/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 48373 f9152f462cbc
child 56557 daa34bd1c8dc
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
     2  * Copyright (c) 2017, 2018, Red Hat, Inc. and/or its affiliates.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    24  */
    24  */
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
       
    29 import java.nio.ByteBuffer;
    29 import javax.net.ssl.SSLProtocolException;
    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;
    30 
    38 
    31 /**
    39 /**
    32  * Extended Master Secret TLS extension (TLS 1.0+). This extension
    40  * Pack of the "extended_master_secret" extensions [RFC 5746].
    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  */
    41 final class ExtendedMasterSecretExtension extends HelloExtension {
    42 final class ExtendedMasterSecretExtension {
    42     ExtendedMasterSecretExtension() {
    43     static final HandshakeProducer chNetworkProducer =
    43         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
    44             new CHExtendedMasterSecretProducer();
    44     }
    45     static final ExtensionConsumer chOnLoadConcumer =
    45 
    46             new CHExtendedMasterSecretConsumer();
    46     ExtendedMasterSecretExtension(HandshakeInStream s,
    47     static final HandshakeAbsence chOnLoadAbsence =
    47             int len) throws IOException {
    48             new CHExtendedMasterSecretAbsence();
    48         super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
    49 
    49 
    50     static final HandshakeProducer shNetworkProducer =
    50         if (len != 0) {
    51             new SHExtendedMasterSecretProducer();
    51             throw new SSLProtocolException("Invalid " + type + " extension");
    52     static final ExtensionConsumer shOnLoadConcumer =
    52         }
    53             new SHExtendedMasterSecretConsumer();
    53     }
    54     static final HandshakeAbsence shOnLoadAbsence =
    54 
    55             new SHExtendedMasterSecretAbsence();
    55     @Override
    56 
    56     int length() {
    57     static final SSLStringize emsStringize =
    57         return 4;       // 4: extension type and length fields
    58             new ExtendedMasterSecretStringize();
    58     }
    59 
    59 
    60     /**
    60     @Override
    61      * The "extended_master_secret" extension.
    61     void send(HandshakeOutStream s) throws IOException {
    62      */
    62         s.putInt16(type.id);    // ExtensionType extension_type;
    63     static final class ExtendedMasterSecretSpec implements SSLExtensionSpec {
    63         s.putInt16(0);          // extension_data length
    64         // A nominal object that does not holding any real renegotiation info.
    64     }
    65         static final ExtendedMasterSecretSpec NOMINAL =
    65 
    66                 new ExtendedMasterSecretSpec();
    66     @Override
    67 
    67     public String toString() {
    68         private ExtendedMasterSecretSpec() {
    68         return "Extension " + type;
    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         }
    69     }
   383     }
    70 }
   384 }
    71 
   385