changeset 12872:95df717479b1 jdk8u162-b11

Merge
author asaha
date Fri, 15 Dec 2017 09:05:18 -0800
parents 0710db75a001 c8ea457b727c
children 19a5eb7025aa
files .hgtags
diffstat 14 files changed, 438 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Tue Dec 05 13:56:48 2017 -0800
+++ b/.hgtags	Fri Dec 15 09:05:18 2017 -0800
@@ -832,6 +832,7 @@
 e7c79f48e83772546a1d35d98101853e2ca17947 jdk8u161-b08
 2c4e596e0cc3281fe976d9a730677c0a15113153 jdk8u161-b09
 3eaad567db074e4d3df7d4088a4a029ef5ad1179 jdk8u161-b10
+8d358ca3cfb813af87aa4bed5a1e7fbb678ea6be jdk8u161-b11
 e03f9868f7df1e3db537f3b61704658e8a9dafb5 jdk8u162-b00
 538bdf24383954cd2356e39e8081c2cb3ac27281 jdk8u162-b01
 18e0bc77adafd0e5e459e381b6993bb0625b05be jdk8u162-b02
--- a/src/share/classes/com/sun/crypto/provider/SunJCE.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/com/sun/crypto/provider/SunJCE.java	Fri Dec 15 09:05:18 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -762,6 +762,8 @@
                         "com.sun.crypto.provider.TlsMasterSecretGenerator");
                     put("Alg.Alias.KeyGenerator.SunTls12MasterSecret",
                         "SunTlsMasterSecret");
+                    put("Alg.Alias.KeyGenerator.SunTlsExtendedMasterSecret",
+                        "SunTlsMasterSecret");
 
                     put("KeyGenerator.SunTlsKeyMaterial",
                         "com.sun.crypto.provider.TlsKeyMaterialGenerator");
--- a/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/com/sun/crypto/provider/TlsMasterSecretGenerator.java	Fri Dec 15 09:05:18 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -100,21 +100,32 @@
 
         try {
             byte[] master;
-            byte[] clientRandom = spec.getClientRandom();
-            byte[] serverRandom = spec.getServerRandom();
-
             if (protocolVersion >= 0x0301) {
-                byte[] seed = concat(clientRandom, serverRandom);
+                byte[] label;
+                byte[] seed;
+                byte[] extendedMasterSecretSessionHash =
+                        spec.getExtendedMasterSecretSessionHash();
+                if (extendedMasterSecretSessionHash.length != 0) {
+                    label = LABEL_EXTENDED_MASTER_SECRET;
+                    seed = extendedMasterSecretSessionHash;
+                } else {
+                    byte[] clientRandom = spec.getClientRandom();
+                    byte[] serverRandom = spec.getServerRandom();
+                    label = LABEL_MASTER_SECRET;
+                    seed = concat(clientRandom, serverRandom);
+                }
                 master = ((protocolVersion >= 0x0303) ?
-                    doTLS12PRF(premaster, LABEL_MASTER_SECRET, seed, 48,
-                        spec.getPRFHashAlg(), spec.getPRFHashLength(),
-                        spec.getPRFBlockSize()) :
-                    doTLS10PRF(premaster, LABEL_MASTER_SECRET, seed, 48));
+                        doTLS12PRF(premaster, label, seed, 48,
+                                spec.getPRFHashAlg(), spec.getPRFHashLength(),
+                                spec.getPRFBlockSize()) :
+                        doTLS10PRF(premaster, label, seed, 48));
             } else {
                 master = new byte[48];
                 MessageDigest md5 = MessageDigest.getInstance("MD5");
                 MessageDigest sha = MessageDigest.getInstance("SHA");
 
+                byte[] clientRandom = spec.getClientRandom();
+                byte[] serverRandom = spec.getServerRandom();
                 byte[] tmp = new byte[20];
                 for (int i = 0; i < 3; i++) {
                     sha.update(SSL3_CONST[i]);
@@ -172,5 +183,5 @@
         }
 
     }
+}
 
-}
--- a/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/com/sun/crypto/provider/TlsPrfGenerator.java	Fri Dec 15 09:05:18 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -55,6 +55,11 @@
     final static byte[] LABEL_MASTER_SECRET = // "master secret"
         { 109, 97, 115, 116, 101, 114, 32, 115, 101, 99, 114, 101, 116 };
 
+    final static byte[] LABEL_EXTENDED_MASTER_SECRET =
+                                            // "extended master secret"
+        { 101, 120, 116, 101, 110, 100, 101, 100, 32, 109, 97, 115, 116,
+          101, 114, 32, 115, 101, 99, 114, 101, 116 };
+
     final static byte[] LABEL_KEY_EXPANSION = // "key expansion"
         { 107, 101, 121, 32, 101, 120, 112, 97, 110, 115, 105, 111, 110 };
 
--- a/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/internal/spec/TlsMasterSecretParameterSpec.java	Fri Dec 15 09:05:18 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -48,6 +48,7 @@
     private final SecretKey premasterSecret;
     private final int majorVersion, minorVersion;
     private final byte[] clientRandom, serverRandom;
+    private final byte[] extendedMasterSecretSessionHash;
     private final String prfHashAlg;
     private final int prfHashLength;
     private final int prfBlockSize;
@@ -80,6 +81,50 @@
             int majorVersion, int minorVersion,
             byte[] clientRandom, byte[] serverRandom,
             String prfHashAlg, int prfHashLength, int prfBlockSize) {
+        this(premasterSecret, majorVersion, minorVersion,
+                clientRandom, serverRandom,
+                new byte[0],
+                prfHashAlg, prfHashLength, prfBlockSize);
+    }
+
+    /**
+     * Constructs a new TlsMasterSecretParameterSpec.
+     *
+     * <p>The <code>getAlgorithm()</code> method of <code>premasterSecret</code>
+     * should return <code>"TlsRsaPremasterSecret"</code> if the key exchange
+     * algorithm was RSA and <code>"TlsPremasterSecret"</code> otherwise.
+     *
+     * @param premasterSecret the premaster secret
+     * @param majorVersion the major number of the protocol version
+     * @param minorVersion the minor number of the protocol version
+     * @param extendedMasterSecretSessionHash the session hash for
+     *        Extended Master Secret
+     * @param prfHashAlg the name of the TLS PRF hash algorithm to use.
+     *        Used only for TLS 1.2+.  TLS1.1 and earlier use a fixed PRF.
+     * @param prfHashLength the output length of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     * @param prfBlockSize the input block size of the TLS PRF hash algorithm.
+     *        Used only for TLS 1.2+.
+     *
+     * @throws NullPointerException if premasterSecret is null
+     * @throws IllegalArgumentException if minorVersion or majorVersion are
+     *   negative or larger than 255
+     */
+    public TlsMasterSecretParameterSpec(SecretKey premasterSecret,
+            int majorVersion, int minorVersion,
+            byte[] extendedMasterSecretSessionHash,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
+        this(premasterSecret, majorVersion, minorVersion,
+                new byte[0], new byte[0],
+                extendedMasterSecretSessionHash,
+                prfHashAlg, prfHashLength, prfBlockSize);
+    }
+
+    private TlsMasterSecretParameterSpec(SecretKey premasterSecret,
+            int majorVersion, int minorVersion,
+            byte[] clientRandom, byte[] serverRandom,
+            byte[] extendedMasterSecretSessionHash,
+            String prfHashAlg, int prfHashLength, int prfBlockSize) {
         if (premasterSecret == null) {
             throw new NullPointerException("premasterSecret must not be null");
         }
@@ -88,6 +133,9 @@
         this.minorVersion = checkVersion(minorVersion);
         this.clientRandom = clientRandom.clone();
         this.serverRandom = serverRandom.clone();
+        this.extendedMasterSecretSessionHash =
+                (extendedMasterSecretSessionHash != null ?
+                        extendedMasterSecretSessionHash.clone() : new byte[0]);
         this.prfHashAlg = prfHashAlg;
         this.prfHashLength = prfHashLength;
         this.prfBlockSize = prfBlockSize;
@@ -147,6 +195,17 @@
     }
 
     /**
+     * Returns a copy of the Extended Master Secret session hash.
+     *
+     * @return a copy of the Extended Master Secret session hash, or an empty
+     *         array if no extended master secret session hash was provided
+     *         at instantiation time
+     */
+    public byte[] getExtendedMasterSecretSessionHash() {
+        return extendedMasterSecretSessionHash.clone();
+    }
+
+    /**
      * Obtains the PRF hash algorithm to use in the PRF calculation.
      *
      * @return the hash algorithm.
--- a/src/share/classes/sun/security/ssl/ClientHandshaker.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java	Fri Dec 15 09:05:18 2017 -0800
@@ -633,6 +633,54 @@
             }
         }
 
+        // check the "extended_master_secret" extension
+        ExtendedMasterSecretExtension extendedMasterSecretExt =
+                (ExtendedMasterSecretExtension)mesg.extensions.get(
+                        ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+        if (extendedMasterSecretExt != null) {
+            // Is it the expected server extension?
+            if (!useExtendedMasterSecret ||
+                    !(mesgVersion.v >= ProtocolVersion.TLS10.v) || !requestedToUseEMS) {
+                fatalSE(Alerts.alert_unsupported_extension,
+                        "Server sent the extended_master_secret " +
+                        "extension improperly");
+            }
+
+            // For abbreviated handshake, if the original session did not use
+            // the "extended_master_secret" extension but the new ServerHello
+            // contains the extension, the client MUST abort the handshake.
+            if (resumingSession && (session != null) &&
+                    !session.getUseExtendedMasterSecret()) {
+                fatalSE(Alerts.alert_unsupported_extension,
+                        "Server sent an unexpected extended_master_secret " +
+                        "extension on session resumption");
+            }
+        } else {
+            if (useExtendedMasterSecret && !allowLegacyMasterSecret) {
+                // For full handshake, if a client receives a ServerHello
+                // without the extension, it SHOULD abort the handshake if
+                // it does not wish to interoperate with legacy servers.
+                fatalSE(Alerts.alert_handshake_failure,
+                    "Extended Master Secret extension is required");
+            }
+
+            if (resumingSession && (session != null)) {
+                if (session.getUseExtendedMasterSecret()) {
+                    // For abbreviated handshake, if the original session used
+                    // the "extended_master_secret" extension but the new
+                    // ServerHello does not contain the extension, the client
+                    // MUST abort the handshake.
+                    fatalSE(Alerts.alert_handshake_failure,
+                            "Missing Extended Master Secret extension " +
+                            "on session resumption");
+                } else if (useExtendedMasterSecret && !allowLegacyResumption) {
+                    // Unlikely, abbreviated handshake should be discarded.
+                    fatalSE(Alerts.alert_handshake_failure,
+                        "Extended Master Secret extension is required");
+                }
+            }
+        }
+
         if (resumingSession && session != null) {
             setHandshakeSessionSE(session);
             // Reserve the handshake state if this is a session-resumption
@@ -652,7 +700,8 @@
             } else if ((type != ExtensionType.EXT_ELLIPTIC_CURVES)
                     && (type != ExtensionType.EXT_EC_POINT_FORMATS)
                     && (type != ExtensionType.EXT_SERVER_NAME)
-                    && (type != ExtensionType.EXT_RENEGOTIATION_INFO)) {
+                    && (type != ExtensionType.EXT_RENEGOTIATION_INFO)
+                    && (type != ExtensionType.EXT_EXTENDED_MASTER_SECRET)){
                 fatalSE(Alerts.alert_unsupported_extension,
                     "Server sent an unsupported extension: " + type);
             }
@@ -661,7 +710,8 @@
         // Create a new session, we need to do the full handshake
         session = new SSLSessionImpl(protocolVersion, cipherSuite,
                             getLocalSupportedSignAlgs(),
-                            mesg.sessionId, getHostSE(), getPortSE());
+                            mesg.sessionId, getHostSE(), getPortSE(),
+                            (extendedMasterSecretExt != null));
         session.setRequestedServerNames(requestedServerNames);
         setHandshakeSessionSE(session);
         if (debug != null && Debug.isOn("handshake")) {
@@ -1297,6 +1347,44 @@
                 session = null;
             }
 
+            if ((session != null) && useExtendedMasterSecret) {
+                boolean isTLS10Plus = sessionVersion.v >= ProtocolVersion.TLS10.v;
+                if (isTLS10Plus && !session.getUseExtendedMasterSecret()) {
+                    if (!allowLegacyResumption) {
+                        // perform full handshake instead
+                        //
+                        // The client SHOULD NOT offer an abbreviated handshake
+                        // to resume a session that does not use an extended
+                        // master secret.  Instead, it SHOULD offer a full
+                        // handshake.
+                        session = null;
+                    }
+                }
+
+                if ((session != null) && !allowUnsafeServerCertChange) {
+                    // It is fine to move on with abbreviate handshake if
+                    // endpoint identification is enabled.
+                    String identityAlg = getEndpointIdentificationAlgorithmSE();
+                    if ((identityAlg == null || identityAlg.length() == 0)) {
+                        if (isTLS10Plus) {
+                            if (!session.getUseExtendedMasterSecret()) {
+                                // perform full handshake instead
+                                session = null;
+                            }   // Otherwise, use extended master secret.
+                        } else {
+                            // The extended master secret extension does not
+                            // apply to SSL 3.0.  Perform a full handshake
+                            // instead.
+                            //
+                            // Note that the useExtendedMasterSecret is
+                            // extended to protect SSL 3.0 connections,
+                            // by discarding abbreviate handshake.
+                            session = null;
+                        }
+                    }
+                }
+            }
+
             if (session != null) {
                 if (debug != null) {
                     if (Debug.isOn("handshake") || Debug.isOn("session")) {
@@ -1403,6 +1491,14 @@
             clientHelloMessage.addSignatureAlgorithmsExtension(localSignAlgs);
         }
 
+        // add Extended Master Secret extension
+        if (useExtendedMasterSecret && (maxProtocolVersion.v >= ProtocolVersion.TLS10.v)) {
+            if ((session == null) || session.getUseExtendedMasterSecret()) {
+                clientHelloMessage.addExtendedMasterSecretExtension();
+                requestedToUseEMS = true;
+            }
+        }
+
         // add server_name extension
         if (enableSNIExtension) {
             if (session != null) {
@@ -1463,10 +1559,14 @@
         // Allow server certificate change in client side during renegotiation
         // after a session-resumption abbreviated initial handshake?
         //
-        // DO NOT need to check allowUnsafeServerCertChange here. We only
+        // DO NOT need to check allowUnsafeServerCertChange here.  We only
         // reserve server certificates when allowUnsafeServerCertChange is
         // flase.
-        if (reservedServerCerts != null) {
+        //
+        // Allow server certificate change if it is negotiated to use the
+        // extended master secret.
+        if ((reservedServerCerts != null) &&
+                !session.getUseExtendedMasterSecret()) {
             // It is not necessary to check the certificate update if endpoint
             // identification is enabled.
             String identityAlg = getEndpointIdentificationAlgorithmSE();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/sun/security/ssl/ExtendedMasterSecretExtension.java	Fri Dec 15 09:05:18 2017 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates.
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.security.ssl;
+
+import java.io.IOException;
+import javax.net.ssl.SSLProtocolException;
+
+/**
+ * Extended Master Secret TLS extension (TLS 1.0+). This extension
+ * defines how to calculate the TLS connection master secret and
+ * mitigates some types of man-in-the-middle attacks.
+ *
+ * See further information in
+ * <a href="https://tools.ietf.org/html/rfc7627">RFC 7627</a>.
+ *
+ * @author Martin Balao (mbalao@redhat.com)
+ */
+final class ExtendedMasterSecretExtension extends HelloExtension {
+    ExtendedMasterSecretExtension() {
+        super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+    }
+
+    ExtendedMasterSecretExtension(HandshakeInStream s,
+            int len) throws IOException {
+        super(ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+
+        if (len != 0) {
+            throw new SSLProtocolException("Invalid " + type + " extension");
+        }
+    }
+
+    @Override
+    int length() {
+        return 4;       // 4: extension type and length fields
+    }
+
+    @Override
+    void send(HandshakeOutStream s) throws IOException {
+        s.putInt16(type.id);    // ExtensionType extension_type;
+        s.putInt16(0);          // extension_data length
+    }
+
+    @Override
+    public String toString() {
+        return "Extension " + type;
+    }
+}
+
--- a/src/share/classes/sun/security/ssl/ExtensionType.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/ExtensionType.java	Fri Dec 15 09:05:18 2017 -0800
@@ -43,7 +43,7 @@
         return name;
     }
 
-    static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(9);
+    static List<ExtensionType> knownExtensions = new ArrayList<ExtensionType>(14);
 
     static ExtensionType get(int id) {
         for (ExtensionType ext : knownExtensions) {
@@ -96,6 +96,10 @@
     final static ExtensionType EXT_SIGNATURE_ALGORITHMS =
             e(0x000D, "signature_algorithms");   // IANA registry value: 13
 
+    // extensions defined in RFC 7627
+    static final ExtensionType EXT_EXTENDED_MASTER_SECRET =
+            e(0x0017, "extended_master_secret"); // IANA registry value: 23
+
     // extensions defined in RFC 5746
     final static ExtensionType EXT_RENEGOTIATION_INFO =
             e(0xff01, "renegotiation_info");     // IANA registry value: 65281
--- a/src/share/classes/sun/security/ssl/HandshakeMessage.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java	Fri Dec 15 09:05:18 2017 -0800
@@ -274,6 +274,10 @@
         extensions.add(signatureAlgorithm);
     }
 
+    void addExtendedMasterSecretExtension() {
+        extensions.add(new ExtendedMasterSecretExtension());
+    }
+
     @Override
     int messageType() { return ht_client_hello; }
 
@@ -1024,7 +1028,7 @@
         } else {
             sig = getSignature(privateKey.getAlgorithm());
         }
-        sig.initSign(privateKey);  // where is the SecureRandom?
+        sig.initSign(privateKey, sr);
 
         updateSignature(sig, clntNonce, svrNonce);
         signatureBytes = sig.sign();
--- a/src/share/classes/sun/security/ssl/Handshaker.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/Handshaker.java	Fri Dec 15 09:05:18 2017 -0800
@@ -29,12 +29,6 @@
 import java.io.*;
 import java.util.*;
 import java.security.*;
-import java.security.NoSuchAlgorithmException;
-import java.security.AccessController;
-import java.security.AlgorithmConstraints;
-import java.security.AccessControlContext;
-import java.security.PrivilegedExceptionAction;
-import java.security.PrivilegedActionException;
 
 import javax.crypto.*;
 import javax.crypto.spec.*;
@@ -204,9 +198,41 @@
             Debug.getBooleanProperty(
                 "jdk.tls.rejectClientInitiatedRenegotiation", false);
 
+    // To switch off the extended_master_secret extension.
+    static final boolean useExtendedMasterSecret;
+
+    // Allow session resumption without Extended Master Secret extension.
+    static final boolean allowLegacyResumption =
+            Debug.getBooleanProperty("jdk.tls.allowLegacyResumption", true);
+
+    // Allow full handshake without Extended Master Secret extension.
+    static final boolean allowLegacyMasterSecret =
+            Debug.getBooleanProperty("jdk.tls.allowLegacyMasterSecret", true);
+
+    // Is it requested to use extended master secret extension?
+    boolean requestedToUseEMS = false;
+
     // need to dispose the object when it is invalidated
     boolean invalidated;
 
+    // Is the extended_master_secret extension supported?
+    static {
+        boolean supportExtendedMasterSecret = true;
+        try {
+            KeyGenerator kg =
+                JsseJce.getKeyGenerator("SunTlsExtendedMasterSecret");
+        } catch (NoSuchAlgorithmException nae) {
+            supportExtendedMasterSecret = false;
+        }
+
+        if (supportExtendedMasterSecret) {
+            useExtendedMasterSecret = Debug.getBooleanProperty(
+                    "jdk.tls.useExtendedMasterSecret", true);
+        } else {
+            useExtendedMasterSecret = false;
+        }
+    }
+
     Handshaker(SSLSocketImpl c, SSLContextImpl context,
             ProtocolList enabledProtocols, boolean needCertVerify,
             boolean isClient, ProtocolVersion activeProtocolVersion,
@@ -216,7 +242,7 @@
         init(context, enabledProtocols, needCertVerify, isClient,
             activeProtocolVersion, isInitialHandshake, secureRenegotiation,
             clientVerifyData, serverVerifyData);
-    }
+   }
 
     Handshaker(SSLEngineImpl engine, SSLContextImpl context,
             ProtocolList enabledProtocols, boolean needCertVerify,
@@ -1169,6 +1195,7 @@
      * SHA1 hashes are of (different) constant strings, the pre-master
      * secret, and the nonces provided by the client and the server.
      */
+    @SuppressWarnings("deprecation")
     private SecretKey calculateMasterSecret(SecretKey preMasterSecret,
             ProtocolVersion requestedVersion) {
 
@@ -1200,10 +1227,34 @@
         int prfHashLength = prf.getPRFHashLength();
         int prfBlockSize = prf.getPRFBlockSize();
 
-        TlsMasterSecretParameterSpec spec = new TlsMasterSecretParameterSpec(
-                preMasterSecret, protocolVersion.major, protocolVersion.minor,
-                clnt_random.random_bytes, svr_random.random_bytes,
-                prfHashAlg, prfHashLength, prfBlockSize);
+        TlsMasterSecretParameterSpec spec;
+        if (session.getUseExtendedMasterSecret()) {
+            // reset to use the extended master secret algorithm
+            masterAlg = "SunTlsExtendedMasterSecret";
+
+            byte[] sessionHash = null;
+            if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
+                sessionHash = handshakeHash.getFinishedHash();
+            } else {
+                // TLS 1.0/1.1
+                sessionHash = new byte[36];
+                try {
+                    handshakeHash.getMD5Clone().digest(sessionHash, 0, 16);
+                    handshakeHash.getSHAClone().digest(sessionHash, 16, 20);
+                } catch (DigestException de) {
+                    throw new ProviderException(de);
+                }
+            }
+
+            spec = new TlsMasterSecretParameterSpec(
+                    preMasterSecret, protocolVersion.major, protocolVersion.minor,
+                    sessionHash, prfHashAlg, prfHashLength, prfBlockSize);
+        } else {
+            spec = new TlsMasterSecretParameterSpec(
+                    preMasterSecret, protocolVersion.major, protocolVersion.minor,
+                    clnt_random.random_bytes, svr_random.random_bytes,
+                    prfHashAlg, prfHashLength, prfBlockSize);
+        }
 
         try {
             KeyGenerator kg = JsseJce.getKeyGenerator(masterAlg);
--- a/src/share/classes/sun/security/ssl/HelloExtensions.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/HelloExtensions.java	Fri Dec 15 09:05:18 2017 -0800
@@ -84,6 +84,8 @@
                 extension = new EllipticPointFormatsExtension(s, extlen);
             } else if (extType == ExtensionType.EXT_RENEGOTIATION_INFO) {
                 extension = new RenegotiationInfoExtension(s, extlen);
+            } else if (extType == ExtensionType.EXT_EXTENDED_MASTER_SECRET) {
+                extension = new ExtendedMasterSecretExtension(s, extlen);
             } else {
                 extension = new UnknownExtension(s, extlen, extType);
             }
--- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java	Fri Dec 15 09:05:18 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -91,6 +91,7 @@
     private byte                compressionMethod;
     private CipherSuite         cipherSuite;
     private SecretKey           masterSecret;
+    private final boolean       useExtendedMasterSecret;
 
     /*
      * Information not part of the SSLv3 protocol spec, but used
@@ -145,7 +146,7 @@
      */
     private SSLSessionImpl() {
         this(ProtocolVersion.NONE, CipherSuite.C_NULL, null,
-            new SessionId(false, null), null, -1);
+            new SessionId(false, null), null, -1, false);
     }
 
     /*
@@ -155,9 +156,11 @@
      */
     SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
             Collection<SignatureAndHashAlgorithm> algorithms,
-            SecureRandom generator, String host, int port) {
+            SecureRandom generator, String host, int port,
+            boolean useExtendedMasterSecret) {
         this(protocolVersion, cipherSuite, algorithms,
-             new SessionId(defaultRejoinable, generator), host, port);
+             new SessionId(defaultRejoinable, generator), host, port,
+             useExtendedMasterSecret);
     }
 
     /*
@@ -165,7 +168,8 @@
      */
     SSLSessionImpl(ProtocolVersion protocolVersion, CipherSuite cipherSuite,
             Collection<SignatureAndHashAlgorithm> algorithms,
-            SessionId id, String host, int port) {
+            SessionId id, String host, int port,
+            boolean useExtendedMasterSecret) {
         this.protocolVersion = protocolVersion;
         sessionId = id;
         peerCerts = null;
@@ -177,6 +181,7 @@
         sessionCount = ++counter;
         localSupportedSignAlgs =
             SignatureAndHashAlgorithm.getAlgorithmNames(algorithms);
+        this.useExtendedMasterSecret = useExtendedMasterSecret;
 
         if (debug != null && Debug.isOn("session")) {
             System.out.println("%% Initialized:  " + this);
@@ -198,6 +203,10 @@
         return masterSecret;
     }
 
+    boolean getUseExtendedMasterSecret() {
+        return useExtendedMasterSecret;
+    }
+
     void setPeerCertificates(X509Certificate[] peer) {
         if (peerCerts == null) {
             peerCerts = peer;
--- a/src/share/classes/sun/security/ssl/ServerHandshaker.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java	Fri Dec 15 09:05:18 2017 -0800
@@ -289,6 +289,11 @@
                         ("Unrecognized key exchange: " + keyExchange);
                 }
 
+                // Need to add the hash for RFC 7627.
+                if (session.getUseExtendedMasterSecret()) {
+                    input.digestNow();
+                }
+
                 //
                 // All keys are calculated from the premaster secret
                 // and the exchanged nonces in the same way.
@@ -495,6 +500,27 @@
             }
         }
 
+        // check out the "extended_master_secret" extension
+        if (useExtendedMasterSecret) {
+            ExtendedMasterSecretExtension extendedMasterSecretExtension =
+                    (ExtendedMasterSecretExtension)mesg.extensions.get(
+                            ExtensionType.EXT_EXTENDED_MASTER_SECRET);
+            if (extendedMasterSecretExtension != null) {
+                requestedToUseEMS = true;
+            } else if (mesg.protocolVersion.v >= ProtocolVersion.TLS10.v) {
+                if (!allowLegacyMasterSecret) {
+                    // For full handshake, if the server receives a ClientHello
+                    // without the extension, it SHOULD abort the handshake if
+                    // it does not wish to interoperate with legacy clients.
+                    //
+                    // As if extended master extension is required for full
+                    // handshake, it MUST be used in abbreviated handshake too.
+                    fatalSE(Alerts.alert_handshake_failure,
+                        "Extended Master Secret extension is required");
+                }
+            }
+        }
+
         /*
          * Always make sure this entire record has been digested before we
          * start emitting output, to ensure correct digesting order.
@@ -569,11 +595,45 @@
                 if (resumingSession) {
                     ProtocolVersion oldVersion = previous.getProtocolVersion();
                     // cannot resume session with different version
-                    if (oldVersion != protocolVersion) {
+                    if (oldVersion != mesg.protocolVersion) {
                         resumingSession = false;
                     }
                 }
 
+                if (resumingSession && useExtendedMasterSecret) {
+                    if (requestedToUseEMS &&
+                            !previous.getUseExtendedMasterSecret()) {
+                        // For abbreviated handshake request, If the original
+                        // session did not use the "extended_master_secret"
+                        // extension but the new ClientHello contains the
+                        // extension, then the server MUST NOT perform the
+                        // abbreviated handshake.  Instead, it SHOULD continue
+                        // with a full handshake.
+                        resumingSession = false;
+                    } else if (!requestedToUseEMS &&
+                            previous.getUseExtendedMasterSecret()) {
+                        // For abbreviated handshake request, if the original
+                        // session used the "extended_master_secret" extension
+                        // but the new ClientHello does not contain it, the
+                        // server MUST abort the abbreviated handshake.
+                        fatalSE(Alerts.alert_handshake_failure,
+                                "Missing Extended Master Secret extension " +
+                                "on session resumption");
+                    } else if (!requestedToUseEMS &&
+                            !previous.getUseExtendedMasterSecret()) {
+                        // For abbreviated handshake request, if neither the
+                        // original session nor the new ClientHello uses the
+                        // extension, the server SHOULD abort the handshake.
+                        if (!allowLegacyResumption) {
+                            fatalSE(Alerts.alert_handshake_failure,
+                                "Missing Extended Master Secret extension " +
+                                "on session resumption");
+                        } else {  // Otherwise, continue with a full handshake.
+                            resumingSession = false;
+                        }
+                    }
+                }
+
                 // cannot resume session with different server name indication
                 if (resumingSession) {
                     List<SNIServerName> oldServerNames =
@@ -720,7 +780,9 @@
             session = new SSLSessionImpl(protocolVersion, CipherSuite.C_NULL,
                         getLocalSupportedSignAlgs(),
                         sslContext.getSecureRandom(),
-                        getHostAddressSE(), getPortSE());
+                        getHostAddressSE(), getPortSE(),
+                        (requestedToUseEMS &&
+                                (protocolVersion.v >= ProtocolVersion.TLS10.v)));
 
             if (protocolVersion.v >= ProtocolVersion.TLS12.v) {
                 if (peerSupportedSignAlgs != null) {
@@ -785,6 +847,10 @@
             }
         }
 
+        if (session.getUseExtendedMasterSecret()) {
+            m1.extensions.add(new ExtendedMasterSecretExtension());
+        }
+
         if (debug != null && Debug.isOn("handshake")) {
             m1.print(System.out);
             System.out.println("Cipher suite:  " + session.getSuite());
--- a/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java	Tue Dec 05 13:56:48 2017 -0800
+++ b/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/DHKeyExchange/DHEKeySizing.java	Fri Dec 15 09:05:18 2017 -0800
@@ -31,34 +31,34 @@
  * @bug 6956398
  * @summary make ephemeral DH key match the length of the certificate key
  * @run main/othervm
- *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 75
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
- *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 75
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
- *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 75
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
- *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1255 75
+ *      DHEKeySizing SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA true 1259 75
  *
  * @run main/othervm
- *      DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 229 75
+ *      DHEKeySizing SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA true 233 75
  *
  * @run main/othervm
- *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1383 139
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1387 139
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
- *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1319 107
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1323 107
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
- *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1639 267
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1643 267
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
- *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1383 139
+ *      DHEKeySizing TLS_DHE_RSA_WITH_AES_128_CBC_SHA  false 1387 139
  *
  * @run main/othervm
- *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 357 139
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 361 139
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy
- *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 293 107
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 297 107
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=matched
- *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 357 139
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 361 139
  * @run main/othervm -Djdk.tls.ephemeralDHKeySize=1024
- *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 357 139
+ *      DHEKeySizing SSL_DH_anon_WITH_RC4_128_MD5  false 361 139
  */
 
 /*
@@ -90,10 +90,10 @@
  * Here is a summary of the record length in the test case.
  *
  *            |  ServerHello Series  |  ClientKeyExchange | ServerHello Anon
- *   512-bit  |          1255 bytes  |           75 bytes |        229 bytes
- *   768-bit  |          1319 bytes  |          107 bytes |        293 bytes
- *  1024-bit  |          1383 bytes  |          139 bytes |        357 bytes
- *  2048-bit  |          1639 bytes  |          267 bytes |        357 bytes
+ *   512-bit  |          1259 bytes  |           75 bytes |        233 bytes
+ *   768-bit  |          1323 bytes  |          107 bytes |        297 bytes
+ *  1024-bit  |          1387 bytes  |          139 bytes |        361 bytes
+ *  2048-bit  |          1643 bytes  |          267 bytes |        361 bytes
  */
 
 import javax.net.ssl.*;