Factoring out some duplicate code. JDK-8171279-XDH-TLS-branch-2
authorapetcher
Mon, 20 Aug 2018 13:16:49 -0400
branchJDK-8171279-XDH-TLS-branch-2
changeset 56864 ec60669bc501
parent 56863 c9d3ea14d270
child 56865 05c7b789076f
Factoring out some duplicate code.
src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java
src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java
src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java
src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java
src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java
--- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java	Fri Aug 17 14:37:01 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java	Mon Aug 20 13:16:49 2018 -0400
@@ -406,7 +406,7 @@
 
         @Override
         public SSLKeyDerivation createKeyDerivation(
-                HandshakeContext context) throws IOException {
+        HandshakeContext context) throws IOException {
             DHEPossession dhePossession = null;
             DHECredentials dheCredentials = null;
             for (SSLPossession poss : context.handshakePossessions) {
@@ -414,126 +414,41 @@
                     continue;
                 }
 
-                DHEPossession dhep = (DHEPossession)poss;
+                DHEPossession dhep = (DHEPossession) poss;
                 for (SSLCredentials cred : context.handshakeCredentials) {
                     if (!(cred instanceof DHECredentials)) {
                         continue;
                     }
-                    DHECredentials dhec = (DHECredentials)cred;
+                    DHECredentials dhec = (DHECredentials) cred;
                     if (dhep.namedGroup != null && dhec.namedGroup != null) {
                         if (dhep.namedGroup.equals(dhec.namedGroup)) {
-                            dheCredentials = (DHECredentials)cred;
+                            dheCredentials = (DHECredentials) cred;
                             break;
                         }
                     } else {
                         DHParameterSpec pps = dhep.publicKey.getParams();
                         DHParameterSpec cps = dhec.popPublicKey.getParams();
                         if (pps.getP().equals(cps.getP()) &&
-                                pps.getG().equals(cps.getG())) {
-                            dheCredentials = (DHECredentials)cred;
+                        pps.getG().equals(cps.getG())) {
+                            dheCredentials = (DHECredentials) cred;
                             break;
                         }
                     }
                 }
 
                 if (dheCredentials != null) {
-                    dhePossession = (DHEPossession)poss;
+                    dhePossession = (DHEPossession) poss;
                     break;
                 }
             }
 
             if (dhePossession == null || dheCredentials == null) {
                 context.conContext.fatal(Alert.HANDSHAKE_FAILURE,
-                    "No sufficient DHE key agreement parameters negotiated");
-            }
-
-            return new DHEKAKeyDerivation(context,
-                    dhePossession.privateKey, dheCredentials.popPublicKey);
-        }
-
-        private static final
-                class DHEKAKeyDerivation implements SSLKeyDerivation {
-            private final HandshakeContext context;
-            private final PrivateKey localPrivateKey;
-            private final PublicKey peerPublicKey;
-
-            DHEKAKeyDerivation(HandshakeContext context,
-                    PrivateKey localPrivateKey,
-                    PublicKey peerPublicKey) {
-                this.context = context;
-                this.localPrivateKey = localPrivateKey;
-                this.peerPublicKey = peerPublicKey;
-            }
-
-            @Override
-            public SecretKey deriveKey(String algorithm,
-                    AlgorithmParameterSpec params) throws IOException {
-                if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
-                    return t12DeriveKey(algorithm, params);
-                } else {
-                    return t13DeriveKey(algorithm, params);
-                }
+                "No sufficient DHE key agreement parameters negotiated");
             }
 
-            private SecretKey t12DeriveKey(String algorithm,
-                    AlgorithmParameterSpec params) throws IOException {
-                try {
-                    KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-                    ka.init(localPrivateKey);
-                    ka.doPhase(peerPublicKey, true);
-                    SecretKey preMasterSecret =
-                            ka.generateSecret("TlsPremasterSecret");
-                    SSLMasterKeyDerivation mskd =
-                            SSLMasterKeyDerivation.valueOf(
-                                    context.negotiatedProtocol);
-                    if (mskd == null) {
-                        // unlikely
-                        throw new SSLHandshakeException(
-                            "No expected master key derivation for protocol: " +
-                            context.negotiatedProtocol.name);
-                    }
-                    SSLKeyDerivation kd = mskd.createKeyDerivation(
-                            context, preMasterSecret);
-                    return kd.deriveKey("MasterSecret", params);
-                } catch (GeneralSecurityException gse) {
-                    throw (SSLHandshakeException) new SSLHandshakeException(
-                        "Could not generate secret").initCause(gse);
-                }
-            }
-
-            private SecretKey t13DeriveKey(String algorithm,
-                    AlgorithmParameterSpec params) throws IOException {
-                try {
-                    KeyAgreement ka = JsseJce.getKeyAgreement("DiffieHellman");
-                    ka.init(localPrivateKey);
-                    ka.doPhase(peerPublicKey, true);
-                    SecretKey sharedSecret =
-                            ka.generateSecret("TlsPremasterSecret");
-
-                    HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
-                    SSLKeyDerivation kd = context.handshakeKeyDerivation;
-                    HKDF hkdf = new HKDF(hashAlg.name);
-                    if (kd == null) {   // No PSK is in use.
-                        // If PSK is not in use Early Secret will still be
-                        // HKDF-Extract(0, 0).
-                        byte[] zeros = new byte[hashAlg.hashLength];
-                        SecretKeySpec ikm =
-                                new SecretKeySpec(zeros, "TlsPreSharedSecret");
-                        SecretKey earlySecret =
-                                hkdf.extract(zeros, ikm, "TlsEarlySecret");
-                        kd = new SSLSecretDerivation(context, earlySecret);
-                    }
-
-                    // derive salt secret
-                    SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
-                    // derive handshake secret
-                    return hkdf.extract(saltSecret, sharedSecret, algorithm);
-                } catch (GeneralSecurityException gse) {
-                    throw (SSLHandshakeException) new SSLHandshakeException(
-                        "Could not generate secret").initCause(gse);
-                }
-            }
+            return new KAKeyDerivation("DiffieHellman", context,
+                dhePossession.privateKey, dheCredentials.popPublicKey);
         }
     }
 }
--- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java	Fri Aug 17 14:37:01 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java	Mon Aug 20 13:16:49 2018 -0400
@@ -304,7 +304,7 @@
                     "No sufficient ECDHE key agreement parameters negotiated");
             }
 
-            return new ECDHEKAKeyDerivation(shc,
+            return new KAKeyDerivation("ECDH", shc,
                 x509Possession.popPrivateKey, ecdheCredentials.popPublicKey);
         }
 
@@ -353,7 +353,7 @@
                     "No sufficient ECDH key agreement parameters negotiated");
             }
 
-            return new ECDHEKAKeyDerivation(chc,
+            return new KAKeyDerivation("ECDH", chc,
                 ecdhePossession.privateKey, x509Credentials.popPublicKey);
         }
     }
@@ -397,94 +397,8 @@
                     "No sufficient ECDHE key agreement parameters negotiated");
             }
 
-            return new ECDHEKAKeyDerivation(context,
+            return new KAKeyDerivation("ECDH", context,
                 ecdhePossession.privateKey, ecdheCredentials.popPublicKey);
         }
     }
-
-    private static final
-            class ECDHEKAKeyDerivation implements SSLKeyDerivation {
-        private final HandshakeContext context;
-        private final PrivateKey localPrivateKey;
-        private final PublicKey peerPublicKey;
-
-        ECDHEKAKeyDerivation(HandshakeContext context,
-                PrivateKey localPrivateKey,
-                PublicKey peerPublicKey) {
-            this.context = context;
-            this.localPrivateKey = localPrivateKey;
-            this.peerPublicKey = peerPublicKey;
-        }
-
-        @Override
-        public SecretKey deriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
-                return t12DeriveKey(algorithm, params);
-            } else {
-                return t13DeriveKey(algorithm, params);
-            }
-        }
-
-        private SecretKey t12DeriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            try {
-                KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
-                ka.init(localPrivateKey);
-                ka.doPhase(peerPublicKey, true);
-                SecretKey preMasterSecret =
-                        ka.generateSecret("TlsPremasterSecret");
-
-                SSLMasterKeyDerivation mskd =
-                        SSLMasterKeyDerivation.valueOf(
-                                context.negotiatedProtocol);
-                if (mskd == null) {
-                    // unlikely
-                    throw new SSLHandshakeException(
-                            "No expected master key derivation for protocol: " +
-                            context.negotiatedProtocol.name);
-                }
-                SSLKeyDerivation kd = mskd.createKeyDerivation(
-                        context, preMasterSecret);
-                return kd.deriveKey("MasterSecret", params);
-            } catch (GeneralSecurityException gse) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(gse);
-            }
-        }
-
-        private SecretKey t13DeriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            try {
-                KeyAgreement ka = JsseJce.getKeyAgreement("ECDH");
-                ka.init(localPrivateKey);
-                ka.doPhase(peerPublicKey, true);
-                SecretKey sharedSecret =
-                        ka.generateSecret("TlsPremasterSecret");
-
-                HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
-                SSLKeyDerivation kd = context.handshakeKeyDerivation;
-                HKDF hkdf = new HKDF(hashAlg.name);
-                if (kd == null) {   // No PSK is in use.
-                    // If PSK is not in use Early Secret will still be
-                    // HKDF-Extract(0, 0).
-                    byte[] zeros = new byte[hashAlg.hashLength];
-                    SecretKeySpec ikm =
-                            new SecretKeySpec(zeros, "TlsPreSharedSecret");
-                    SecretKey earlySecret =
-                            hkdf.extract(zeros, ikm, "TlsEarlySecret");
-                    kd = new SSLSecretDerivation(context, earlySecret);
-                }
-
-                // derive salt secret
-                SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
-                // derive handshake secret
-                return hkdf.extract(saltSecret, sharedSecret, algorithm);
-            } catch (GeneralSecurityException gse) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(gse);
-            }
-        }
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java	Mon Aug 20 13:16:49 2018 -0400
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018, 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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 javax.crypto.KeyAgreement;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import javax.net.ssl.SSLHandshakeException;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.AlgorithmParameterSpec;
+
+public class KAKeyDerivation implements SSLKeyDerivation {
+
+    private final String algorithmName;
+    private final HandshakeContext context;
+    private final PrivateKey localPrivateKey;
+    private final PublicKey peerPublicKey;
+
+    KAKeyDerivation(String algorithmName,
+                    HandshakeContext context,
+                    PrivateKey localPrivateKey,
+                    PublicKey peerPublicKey) {
+        this.algorithmName = algorithmName;
+        this.context = context;
+        this.localPrivateKey = localPrivateKey;
+        this.peerPublicKey = peerPublicKey;
+    }
+
+    @Override
+    public SecretKey deriveKey(String algorithm,
+                               AlgorithmParameterSpec params) throws IOException {
+        if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
+            return t12DeriveKey(algorithm, params);
+        } else {
+            return t13DeriveKey(algorithm, params);
+        }
+    }
+
+    private SecretKey t12DeriveKey(String algorithm,
+                                   AlgorithmParameterSpec params) throws IOException {
+        try {
+            KeyAgreement ka = JsseJce.getKeyAgreement(algorithmName);
+            ka.init(localPrivateKey);
+            ka.doPhase(peerPublicKey, true);
+            SecretKey preMasterSecret =
+            ka.generateSecret("TlsPremasterSecret");
+            SSLMasterKeyDerivation mskd =
+            SSLMasterKeyDerivation.valueOf(
+            context.negotiatedProtocol);
+            if (mskd == null) {
+                // unlikely
+                throw new SSLHandshakeException(
+                "No expected master key derivation for protocol: " +
+                context.negotiatedProtocol.name);
+            }
+            SSLKeyDerivation kd = mskd.createKeyDerivation(
+            context, preMasterSecret);
+            return kd.deriveKey("MasterSecret", params);
+        } catch (GeneralSecurityException gse) {
+            throw (SSLHandshakeException) new SSLHandshakeException(
+            "Could not generate secret").initCause(gse);
+        }
+    }
+
+    private SecretKey t13DeriveKey(String algorithm,
+                                   AlgorithmParameterSpec params) throws IOException {
+        try {
+            KeyAgreement ka = JsseJce.getKeyAgreement(algorithmName);
+            ka.init(localPrivateKey);
+            ka.doPhase(peerPublicKey, true);
+            SecretKey sharedSecret =
+            ka.generateSecret("TlsPremasterSecret");
+
+            CipherSuite.HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
+            SSLKeyDerivation kd = context.handshakeKeyDerivation;
+            HKDF hkdf = new HKDF(hashAlg.name);
+            if (kd == null) {   // No PSK is in use.
+                // If PSK is not in use Early Secret will still be
+                // HKDF-Extract(0, 0).
+                byte[] zeros = new byte[hashAlg.hashLength];
+                SecretKeySpec ikm =
+                new SecretKeySpec(zeros, "TlsPreSharedSecret");
+                SecretKey earlySecret =
+                hkdf.extract(zeros, ikm, "TlsEarlySecret");
+                kd = new SSLSecretDerivation(context, earlySecret);
+            }
+
+            // derive salt secret
+            SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
+
+            // derive handshake secret
+            return hkdf.extract(saltSecret, sharedSecret, algorithm);
+        } catch (GeneralSecurityException gse) {
+            throw (SSLHandshakeException) new SSLHandshakeException(
+            "Could not generate secret").initCause(gse);
+        }
+    }
+}
\ No newline at end of file
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Fri Aug 17 14:37:01 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Mon Aug 20 13:16:49 2018 -0400
@@ -193,6 +193,7 @@
         }
 
         public AlgorithmParameters getParameters() {
+
             AlgorithmParameters result = namedGroupParams.get(ng);
             if (result == null) {
                 Optional<AlgorithmParameters> paramsOpt = getParametersImpl();
@@ -201,6 +202,7 @@
                     namedGroupParams.put(ng, result);
                 }
             }
+
             return result;
         }
 
@@ -313,22 +315,18 @@
         @Override
         public boolean isAvailable() {
 
-            try {
-                AlgorithmParameters params = getParameters();
-                AlgorithmParameterSpec spec = getFFDHEDHParameterSpec(getNamedGroup());
-                params.init(spec);
-                return true;
-            } catch (InvalidParameterSpecException e) {
-                return false;
-            }
+            AlgorithmParameters params = getParameters();
+            return params != null;
         }
 
         @Override
         protected Optional<AlgorithmParameters> getParametersImpl() {
             try {
-                return Optional.of(
-                    JsseJce.getAlgorithmParameters("DiffieHellman"));
-            } catch(NoSuchAlgorithmException ex) {
+                AlgorithmParameters params = JsseJce.getAlgorithmParameters("DiffieHellman");
+                AlgorithmParameterSpec spec = getFFDHEDHParameterSpec(getNamedGroup());
+                params.init(spec);
+                return Optional.of(params);
+            } catch(InvalidParameterSpecException | NoSuchAlgorithmException ex) {
                 return Optional.empty();
             }
         }
@@ -366,22 +364,18 @@
         @Override
         public boolean isAvailable() {
 
-            try {
-                AlgorithmParameters params = getParameters();
-                AlgorithmParameterSpec spec = new ECGenParameterSpec(getNamedGroup().oid);
-                params.init(spec);
-                return true;
-            } catch (InvalidParameterSpecException e) {
-                return false;
-            }
+            AlgorithmParameters params = getParameters();
+            return params != null;
         }
 
         @Override
         protected Optional<AlgorithmParameters> getParametersImpl() {
             try {
-                return Optional.of(
-                    JsseJce.getAlgorithmParameters("EC"));
-            } catch(NoSuchAlgorithmException ex) {
+                AlgorithmParameters params = JsseJce.getAlgorithmParameters("EC");
+                AlgorithmParameterSpec spec = new ECGenParameterSpec(getNamedGroup().oid);
+                params.init(spec);
+                return Optional.of(params);
+            } catch(InvalidParameterSpecException | NoSuchAlgorithmException ex) {
                 return Optional.empty();
             }
         }
@@ -849,11 +843,12 @@
         // check whether the group is supported by the underlying providers
         public static boolean isAvailableGroup(NamedGroup namedGroup) {
 
-            Optional<NamedGroupFunctions> ngf = namedGroup.getFunctions();
-            if (ngf.isEmpty()) {
+            Optional<NamedGroupFunctions> ngfOpt = namedGroup.getFunctions();
+            if (ngfOpt.isEmpty()) {
                 return false;
             }
-            return ngf.get().isAvailable();
+            NamedGroupFunctions ngf = ngfOpt.get();
+            return ngf.isAvailable();
 
         }
 
--- a/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java	Fri Aug 17 14:37:01 2018 -0400
+++ b/src/java.base/share/classes/sun/security/ssl/XDHKeyExchange.java	Mon Aug 20 13:16:49 2018 -0400
@@ -26,8 +26,6 @@
 package sun.security.ssl;
 
 import java.io.IOException;
-import java.security.AlgorithmConstraints;
-import java.security.CryptoPrimitive;
 import java.security.GeneralSecurityException;
 import java.security.KeyFactory;
 import java.security.KeyPair;
@@ -35,29 +33,15 @@
 import java.security.PrivateKey;
 import java.security.PublicKey;
 import java.security.SecureRandom;
-import java.security.interfaces.XECPrivateKey;
 import java.security.interfaces.XECPublicKey;
 import java.security.spec.*;
-import java.util.EnumSet;
-import javax.crypto.KeyAgreement;
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-import javax.net.ssl.SSLHandshakeException;
-import sun.security.ssl.CipherSuite.HashAlg;
 import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
 import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
-import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
-import sun.security.ssl.X509Authentication.X509Credentials;
-import sun.security.ssl.X509Authentication.X509Possession;
 import sun.security.util.ECUtil;
 
 final class XDHKeyExchange {
-    static final SSLPossessionGenerator poGenerator =
-            new XDHEPossessionGenerator();
     static final SSLKeyAgreementGenerator xdheKAGenerator =
             new XDHEKAGenerator();
-    static final SSLKeyAgreementGenerator xdhKAGenerator =
-            new XDHKAGenerator();
 
     static final class XDHECredentials implements SSLKeyAgreementCredentials {
         final XECPublicKey popPublicKey;
@@ -115,22 +99,6 @@
             this.namedGroup = namedGroup;
         }
 
-        XDHEPossession(XDHECredentials credentials, SecureRandom random) {
-            AlgorithmParameterSpec params = credentials.popPublicKey.getParams();
-            try {
-                KeyPairGenerator kpg = JsseJce.getKeyPairGenerator(credentials.namedGroup.algorithm);
-                kpg.initialize(params, random);
-                KeyPair kp = kpg.generateKeyPair();
-                privateKey = kp.getPrivate();
-                publicKey = (XECPublicKey)kp.getPublic();
-            } catch (GeneralSecurityException e) {
-                throw new RuntimeException(
-                    "Could not generate XDH keypair", e);
-            }
-
-            this.namedGroup = credentials.namedGroup;
-        }
-
         @Override
         public byte[] encode() {
             try {
@@ -139,222 +107,6 @@
                 throw new RuntimeException(ex);
             }
         }
-
-        // called by client handshaker
-        SecretKey getAgreedSecret(
-                PublicKey peerPublicKey) throws SSLHandshakeException {
-
-            try {
-                KeyAgreement ka = JsseJce.getKeyAgreement("XDH");
-                ka.init(privateKey);
-                ka.doPhase(peerPublicKey, true);
-                return ka.generateSecret("TlsPremasterSecret");
-            } catch (GeneralSecurityException e) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(e);
-            }
-        }
-
-        // called by ServerHandshaker
-        SecretKey getAgreedSecret(
-                byte[] encodedKey) throws SSLHandshakeException {
-            try {
-                AlgorithmParameterSpec params = publicKey.getParams();
-
-                KeyFactory kf = JsseJce.getKeyFactory("XDH");
-                XECPublicKeySpec spec = ECUtil.decodeXecPublicKey(encodedKey, params);
-                PublicKey peerPublicKey = kf.generatePublic(spec);
-                return getAgreedSecret(peerPublicKey);
-            } catch (GeneralSecurityException | java.io.IOException e) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(e);
-            }
-        }
-
-        // Check constraints of the specified EC public key.
-        void checkConstraints(AlgorithmConstraints constraints,
-                byte[] encodedKey) throws SSLHandshakeException {
-            try {
-
-                AlgorithmParameterSpec params = publicKey.getParams();
-                XECPublicKeySpec spec = ECUtil.decodeXecPublicKey(encodedKey, params);
-
-                KeyFactory kf = JsseJce.getKeyFactory("XDH");
-                PublicKey pubKey = kf.generatePublic(spec);
-
-                // check constraints of ECPublicKey
-                if (!constraints.permits(
-                        EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), pubKey)) {
-                    throw new SSLHandshakeException(
-                        "ECPublicKey does not comply to algorithm constraints");
-                }
-            } catch (GeneralSecurityException | java.io.IOException e) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                        "Could not generate ECPublicKey").initCause(e);
-            }
-        }
-    }
-
-    private static final
-            class XDHEPossessionGenerator implements SSLPossessionGenerator {
-        // Prevent instantiation of this class.
-        private XDHEPossessionGenerator() {
-            // blank
-        }
-
-        @Override
-        public SSLPossession createPossession(HandshakeContext context) {
-            NamedGroup preferableNamedGroup = null;
-            if ((context.clientRequestedNamedGroups != null) &&
-                    (!context.clientRequestedNamedGroups.isEmpty())) {
-                preferableNamedGroup = SupportedGroups.getPreferredGroup(
-                        context.negotiatedProtocol,
-                        context.algorithmConstraints,
-                        NamedGroupType.NAMED_GROUP_XDH,
-                        context.clientRequestedNamedGroups);
-            } else {
-                preferableNamedGroup = SupportedGroups.getPreferredGroup(
-                        context.negotiatedProtocol,
-                        context.algorithmConstraints,
-                        NamedGroupType.NAMED_GROUP_XDH);
-            }
-
-            if (preferableNamedGroup != null) {
-                return new XDHEPossession(preferableNamedGroup,
-                            context.sslContext.getSecureRandom());
-            }
-
-            // no match found, cannot use this cipher suite.
-            //
-            return null;
-        }
-    }
-
-    private static final
-            class XDHKAGenerator implements SSLKeyAgreementGenerator {
-        // Prevent instantiation of this class.
-        private XDHKAGenerator() {
-            // blank
-        }
-
-        @Override
-        public SSLKeyDerivation createKeyDerivation(
-                HandshakeContext context) throws IOException {
-            if (context instanceof ServerHandshakeContext) {
-                return createServerKeyDerivation(
-                        (ServerHandshakeContext)context);
-            } else {
-                return createClientKeyDerivation(
-                        (ClientHandshakeContext)context);
-            }
-        }
-
-        private SSLKeyDerivation createServerKeyDerivation(
-                ServerHandshakeContext shc) throws IOException {
-            X509Possession x509Possession = null;
-            XDHECredentials xdheCredentials = null;
-            for (SSLPossession poss : shc.handshakePossessions) {
-                if (!(poss instanceof X509Possession)) {
-                    continue;
-                }
-
-                PrivateKey privateKey = ((X509Possession)poss).popPrivateKey;
-                if (! (privateKey instanceof XECPrivateKey)) {
-                    continue;
-                }
-                AlgorithmParameterSpec params = ((XECPrivateKey)privateKey).getParams();
-                // group must be specified by name
-                if (!(params instanceof NamedParameterSpec)) {
-                    continue;
-                }
-                NamedParameterSpec namedParams = (NamedParameterSpec) params;
-                NamedGroup ng = NamedGroup.valueOf(namedParams.getName());
-                if (ng == null) {
-                    // unlikely, have been checked during cipher suite negotiation.
-                    shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
-                        "Unsupported server cert for XDH key exchange");
-                }
-
-                for (SSLCredentials cred : shc.handshakeCredentials) {
-                    if (!(cred instanceof XDHECredentials)) {
-                        continue;
-                    }
-                    if (ng.equals(((XDHECredentials)cred).namedGroup)) {
-                        xdheCredentials = (XDHECredentials)cred;
-                        break;
-                    }
-                }
-
-                if (xdheCredentials != null) {
-                    x509Possession = (X509Possession)poss;
-                    break;
-                }
-            }
-
-            if (x509Possession == null || xdheCredentials == null) {
-                shc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
-                    "No sufficient XDHE key agreement parameters negotiated");
-            }
-
-            return new XDHEKAKeyDerivation(shc,
-                x509Possession.popPrivateKey, xdheCredentials.popPublicKey);
-        }
-
-        private SSLKeyDerivation createClientKeyDerivation(
-                ClientHandshakeContext chc) throws IOException {
-
-            XDHEPossession xdhePossession = null;
-            X509Credentials x509Credentials = null;
-            for (SSLPossession poss : chc.handshakePossessions) {
-                if (!(poss instanceof XDHEPossession)) {
-                    continue;
-                }
-
-                NamedGroup ng = ((XDHEPossession)poss).namedGroup;
-                for (SSLCredentials cred : chc.handshakeCredentials) {
-                    if (!(cred instanceof X509Credentials)) {
-                        continue;
-                    }
-
-                    PublicKey publicKey = ((X509Credentials)cred).popPublicKey;
-                    if (!(publicKey instanceof XECPublicKey)) {
-                        continue;
-                    }
-                    XECPublicKey xecPublicKey = (XECPublicKey) publicKey;
-                    AlgorithmParameterSpec params = xecPublicKey.getParams();
-                    // group must be specified by name
-                    if (!(params instanceof NamedParameterSpec)) {
-                        continue;
-                    }
-                    NamedParameterSpec namedParams = (NamedParameterSpec) params;
-
-                    NamedGroup namedGroup = NamedGroup.valueOf(namedParams.getName());
-                    if (namedGroup == null) {
-                        // unlikely, should have been checked previously
-                        chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
-                            "Unsupported EC server cert for XDH key exchange");
-                    }
-
-                    if (ng.equals(namedGroup)) {
-                        x509Credentials = (X509Credentials)cred;
-                        break;
-                    }
-                }
-
-                if (x509Credentials != null) {
-                    xdhePossession = (XDHEPossession)poss;
-                    break;
-                }
-            }
-
-            if (xdhePossession == null || x509Credentials == null) {
-                chc.conContext.fatal(Alert.HANDSHAKE_FAILURE,
-                    "No sufficient XDH key agreement parameters negotiated");
-            }
-
-            return new XDHEKAKeyDerivation(chc,
-                xdhePossession.privateKey, x509Credentials.popPublicKey);
-        }
     }
 
     private static final
@@ -396,88 +148,9 @@
                     "No sufficient XDHE key agreement parameters negotiated");
             }
 
-            return new XDHEKAKeyDerivation(context,
+            return new KAKeyDerivation("XDH", context,
                 xdhePossession.privateKey, xdheCredentials.popPublicKey);
         }
     }
 
-    private static final
-            class XDHEKAKeyDerivation implements SSLKeyDerivation {
-        private final HandshakeContext context;
-        private final PrivateKey localPrivateKey;
-        private final PublicKey peerPublicKey;
-
-        XDHEKAKeyDerivation(HandshakeContext context,
-                PrivateKey localPrivateKey,
-                PublicKey peerPublicKey) {
-            this.context = context;
-            this.localPrivateKey = localPrivateKey;
-            this.peerPublicKey = peerPublicKey;
-        }
-
-        @Override
-        public SecretKey deriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            if (!context.negotiatedProtocol.useTLS13PlusSpec()) {
-                return t12DeriveKey(algorithm, params);
-            } else {
-                return t13DeriveKey(algorithm, params);
-            }
-        }
-
-        private SecretKey t12DeriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            try {
-                KeyAgreement ka = JsseJce.getKeyAgreement("XDH");
-                ka.init(localPrivateKey);
-                ka.doPhase(peerPublicKey, true);
-                SecretKey preMasterSecret =
-                        ka.generateSecret("TlsPremasterSecret");
-
-                SSLMasterKeyDerivation mskd =
-                        SSLMasterKeyDerivation.valueOf(
-                                context.negotiatedProtocol);
-                SSLKeyDerivation kd = mskd.createKeyDerivation(
-                        context, preMasterSecret);
-                return kd.deriveKey("TODO", params);
-            } catch (GeneralSecurityException gse) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(gse);
-            }
-        }
-
-        private SecretKey t13DeriveKey(String algorithm,
-                AlgorithmParameterSpec params) throws IOException {
-            try {
-                KeyAgreement ka = JsseJce.getKeyAgreement("XDH");
-                ka.init(localPrivateKey);
-                ka.doPhase(peerPublicKey, true);
-                SecretKey sharedSecret =
-                        ka.generateSecret("TlsPremasterSecret");
-
-                HashAlg hashAlg = context.negotiatedCipherSuite.hashAlg;
-                SSLKeyDerivation kd = context.handshakeKeyDerivation;
-                HKDF hkdf = new HKDF(hashAlg.name);
-                if (kd == null) {   // No PSK is in use.
-                    // If PSK is not in use Early Secret will still be
-                    // HKDF-Extract(0, 0).
-                    byte[] zeros = new byte[hashAlg.hashLength];
-                    SecretKeySpec ikm =
-                            new SecretKeySpec(zeros, "TlsPreSharedSecret");
-                    SecretKey earlySecret =
-                            hkdf.extract(zeros, ikm, "TlsEarlySecret");
-                    kd = new SSLSecretDerivation(context, earlySecret);
-                }
-
-                // derive salt secret
-                SecretKey saltSecret = kd.deriveKey("TlsSaltSecret", null);
-
-                // derive handshake secret
-                return hkdf.extract(saltSecret, sharedSecret, algorithm);
-            } catch (GeneralSecurityException gse) {
-                throw (SSLHandshakeException) new SSLHandshakeException(
-                    "Could not generate secret").initCause(gse);
-            }
-        }
-    }
 }