src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 53734 cb1642ccc732
child 58679 9c3209ff7550
--- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java	Thu Oct 17 20:53:35 2019 +0100
@@ -28,31 +28,21 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.security.AlgorithmConstraints;
-import java.security.AlgorithmParameters;
-import java.security.CryptoPrimitive;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.AlgorithmParameterSpec;
-import java.security.spec.ECGenParameterSpec;
-import java.security.spec.ECParameterSpec;
-import java.security.spec.InvalidParameterSpecException;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
-import javax.crypto.spec.DHParameterSpec;
 import javax.net.ssl.SSLProtocolException;
 import sun.security.action.GetPropertyAction;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
 import sun.security.ssl.SSLExtension.ExtensionConsumer;
 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
 import sun.security.ssl.SSLHandshake.HandshakeMessage;
-import sun.security.util.ECUtil;
+
 
 /**
  * Pack of the "supported_groups" extensions [RFC 4492/7919].
@@ -158,320 +148,11 @@
         }
     }
 
-    static enum NamedGroupType {
-        NAMED_GROUP_ECDHE     ("EC"),
-        NAMED_GROUP_FFDHE     ("DiffieHellman"),
-        NAMED_GROUP_X25519    ("x25519"),
-        NAMED_GROUP_X448      ("x448"),
-        NAMED_GROUP_ARBITRARY ("EC"),
-        NAMED_GROUP_NONE      ("");
-
-        private final String algorithm;
-
-        private NamedGroupType(String algorithm) {
-            this.algorithm = algorithm;
-        }
-
-        boolean isSupported(List<CipherSuite> cipherSuites) {
-            for (CipherSuite cs : cipherSuites) {
-                if (cs.keyExchange == null ||
-                        cs.keyExchange.groupType == this) {
-                    return true;
-                }
-            }
-
-            return false;
-        }
-    }
-
-    static enum NamedGroup {
-        // Elliptic Curves (RFC 4492)
-        //
-        // See sun.security.util.CurveDB for the OIDs
-        // NIST K-163
-        SECT163_K1  (0x0001, "sect163k1", "1.3.132.0.1",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECT163_R1  (0x0002, "sect163r1", "1.3.132.0.2",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST B-163
-        SECT163_R2  (0x0003, "sect163r2", "1.3.132.0.15",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECT193_R1  (0x0004, "sect193r1", "1.3.132.0.24",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECT193_R2  (0x0005, "sect193r2", "1.3.132.0.25",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST K-233
-        SECT233_K1  (0x0006, "sect233k1", "1.3.132.0.26",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST B-233
-        SECT233_R1  (0x0007, "sect233r1", "1.3.132.0.27",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECT239_K1  (0x0008, "sect239k1", "1.3.132.0.3",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST K-283
-        SECT283_K1  (0x0009, "sect283k1", "1.3.132.0.16",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST B-283
-        SECT283_R1  (0x000A, "sect283r1", "1.3.132.0.17",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST K-409
-        SECT409_K1  (0x000B, "sect409k1", "1.3.132.0.36",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST B-409
-        SECT409_R1  (0x000C, "sect409r1", "1.3.132.0.37",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST K-571
-        SECT571_K1  (0x000D, "sect571k1", "1.3.132.0.38",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST B-571
-        SECT571_R1  (0x000E, "sect571r1", "1.3.132.0.39",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP160_K1  (0x000F, "secp160k1", "1.3.132.0.9",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP160_R1  (0x0010, "secp160r1", "1.3.132.0.8",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP160_R2  (0x0011, "secp160r2", "1.3.132.0.30",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP192_K1  (0x0012, "secp192k1", "1.3.132.0.31",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST P-192
-        SECP192_R1  (0x0013, "secp192r1", "1.2.840.10045.3.1.1",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP224_K1  (0x0014, "secp224k1", "1.3.132.0.32",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        // NIST P-224
-        SECP224_R1  (0x0015, "secp224r1", "1.3.132.0.33",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        SECP256_K1  (0x0016, "secp256k1", "1.3.132.0.10",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-
-        // NIST P-256
-        SECP256_R1  (0x0017, "secp256r1", "1.2.840.10045.3.1.7",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-
-        // NIST P-384
-        SECP384_R1  (0x0018, "secp384r1", "1.3.132.0.34",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-
-        // NIST P-521
-        SECP521_R1  (0x0019, "secp521r1", "1.3.132.0.35",
-                            NamedGroupType.NAMED_GROUP_ECDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-
-        // x25519 and x448
-        X25519      (0x001D, "x25519", null,
-                            NamedGroupType.NAMED_GROUP_X25519,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-        X448        (0x001E, "x448", null,
-                            NamedGroupType.NAMED_GROUP_X448,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-
-        // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
-        FFDHE_2048  (0x0100, "ffdhe2048", null,
-                            NamedGroupType.NAMED_GROUP_FFDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-        FFDHE_3072  (0x0101, "ffdhe3072", null,
-                            NamedGroupType.NAMED_GROUP_FFDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-        FFDHE_4096  (0x0102, "ffdhe4096", null,
-                            NamedGroupType.NAMED_GROUP_FFDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-        FFDHE_6144  (0x0103, "ffdhe6144", null,
-                            NamedGroupType.NAMED_GROUP_FFDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-        FFDHE_8192  (0x0104, "ffdhe8192", null,
-                            NamedGroupType.NAMED_GROUP_FFDHE,
-                            ProtocolVersion.PROTOCOLS_TO_13),
-
-        // Elliptic Curves (RFC 4492)
-        //
-        // arbitrary prime and characteristic-2 curves
-        ARBITRARY_PRIME  (0xFF01, "arbitrary_explicit_prime_curves", null,
-                            NamedGroupType.NAMED_GROUP_ARBITRARY,
-                            ProtocolVersion.PROTOCOLS_TO_12),
-        ARBITRARY_CHAR2  (0xFF02, "arbitrary_explicit_char2_curves", null,
-                            NamedGroupType.NAMED_GROUP_ARBITRARY,
-                            ProtocolVersion.PROTOCOLS_TO_12);
-
-        final int id;               // hash + signature
-        final NamedGroupType type;  // group type
-        final String name;          // literal name
-        final String oid;           // object identifier of the named group
-        final String algorithm;     // signature algorithm
-        final ProtocolVersion[] supportedProtocols;
-
-        private NamedGroup(int id, String name, String oid,
-                NamedGroupType namedGroupType,
-                ProtocolVersion[] supportedProtocols) {
-            this.id = id;
-            this.type = namedGroupType;
-            this.name = name;
-            this.oid = oid;
-            this.algorithm = namedGroupType.algorithm;
-            this.supportedProtocols = supportedProtocols;
-        }
-
-        static NamedGroup valueOf(int id) {
-            for (NamedGroup group : NamedGroup.values()) {
-                if (group.id == id) {
-                    return group;
-                }
-            }
-
-            return null;
-        }
-
-        static NamedGroup valueOf(ECParameterSpec params) {
-            String oid = ECUtil.getCurveName(null, params);
-            if ((oid != null) && (!oid.isEmpty())) {
-                for (NamedGroup group : NamedGroup.values()) {
-                    if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE) &&
-                            oid.equals(group.oid)) {
-                        return group;
-                    }
-                }
-            }
-
-            return null;
-        }
-
-        static NamedGroup valueOf(DHParameterSpec params) {
-            for (Map.Entry<NamedGroup, AlgorithmParameters> me :
-                    SupportedGroups.namedGroupParams.entrySet()) {
-                NamedGroup ng = me.getKey();
-                if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
-                    continue;
-                }
-
-                DHParameterSpec ngParams = null;
-                AlgorithmParameters aps = me.getValue();
-                try {
-                    ngParams = aps.getParameterSpec(DHParameterSpec.class);
-                } catch (InvalidParameterSpecException ipse) {
-                    // should be unlikely
-                }
-
-                if (ngParams == null) {
-                    continue;
-                }
-
-                if (ngParams.getP().equals(params.getP()) &&
-                        ngParams.getG().equals(params.getG())) {
-                    return ng;
-                }
-            }
-
-            return null;
-        }
-
-        static NamedGroup nameOf(String name) {
-            for (NamedGroup group : NamedGroup.values()) {
-                if (group.name.equals(name)) {
-                    return group;
-                }
-            }
-
-            return null;
-        }
-
-        static String nameOf(int id) {
-            for (NamedGroup group : NamedGroup.values()) {
-                if (group.id == id) {
-                    return group.name;
-                }
-            }
-
-            return "UNDEFINED-NAMED-GROUP(" + id + ")";
-        }
-
-        boolean isAvailable(List<ProtocolVersion> protocolVersions) {
-            for (ProtocolVersion pv : supportedProtocols) {
-                if (protocolVersions.contains(pv)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        boolean isAvailable(ProtocolVersion protocolVersion) {
-            for (ProtocolVersion pv : supportedProtocols) {
-                if (protocolVersion == pv) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        boolean isSupported(List<CipherSuite> cipherSuites) {
-            for (CipherSuite cs : cipherSuites) {
-                boolean isMatch = isAvailable(cs.supportedProtocols);
-                if (isMatch && (cs.keyExchange == null ||
-                        cs.keyExchange.groupType == type)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        // lazy loading of parameters
-        AlgorithmParameters getParameters() {
-            return SupportedGroups.namedGroupParams.get(this);
-        }
-
-        AlgorithmParameterSpec getParameterSpec() {
-            if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
-                return SupportedGroups.getECGenParamSpec(this);
-            } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
-                return SupportedGroups.getDHParameterSpec(this);
-            }
-
-            return null;
-        }
-    }
-
     static class SupportedGroups {
         // To switch off the supported_groups extension for DHE cipher suite.
         static final boolean enableFFDHE =
                 Utilities.getBooleanProperty("jsse.enableFFDHE", true);
 
-        // cache to speed up the parameters construction
-        static final Map<NamedGroup,
-                    AlgorithmParameters> namedGroupParams = new HashMap<>();
-
         // the supported named groups
         static final NamedGroup[] supportedNamedGroups;
 
@@ -502,7 +183,7 @@
                     if (!group.isEmpty()) {
                         NamedGroup namedGroup = NamedGroup.nameOf(group);
                         if (namedGroup != null) {
-                            if (isAvailableGroup(namedGroup)) {
+                            if (namedGroup.isAvailable) {
                                 groupList.add(namedGroup);
                             }
                         }   // ignore unknown groups
@@ -516,21 +197,19 @@
                 }
             } else {        // default groups
                 NamedGroup[] groups = new NamedGroup[] {
-                        // NIST curves first
+
+                        // Primary XDH (RFC 7748) curves
+                        NamedGroup.X25519,
+
+                        // Primary NIST Suite B curves
                         NamedGroup.SECP256_R1,
                         NamedGroup.SECP384_R1,
                         NamedGroup.SECP521_R1,
-                        NamedGroup.SECT283_K1,
-                        NamedGroup.SECT283_R1,
-                        NamedGroup.SECT409_K1,
-                        NamedGroup.SECT409_R1,
-                        NamedGroup.SECT571_K1,
-                        NamedGroup.SECT571_R1,
 
-                        // non-NIST curves
-                        NamedGroup.SECP256_K1,
+                        // Secondary XDH curves
+                        NamedGroup.X448,
 
-                        // FFDHE 2048
+                        // FFDHE (RFC 7919)
                         NamedGroup.FFDHE_2048,
                         NamedGroup.FFDHE_3072,
                         NamedGroup.FFDHE_4096,
@@ -540,7 +219,7 @@
 
                 groupList = new ArrayList<>(groups.length);
                 for (NamedGroup group : groups) {
-                    if (isAvailableGroup(group)) {
+                    if (group.isAvailable) {
                         groupList.add(group);
                     }
                 }
@@ -558,147 +237,19 @@
             }
         }
 
-        // check whether the group is supported by the underlying providers
-        private static boolean isAvailableGroup(NamedGroup namedGroup) {
-            AlgorithmParameters params = null;
-            AlgorithmParameterSpec spec = null;
-            if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
-                if (namedGroup.oid != null) {
-                    try {
-                        params = AlgorithmParameters.getInstance("EC");
-                        spec = new ECGenParameterSpec(namedGroup.oid);
-                    } catch (NoSuchAlgorithmException e) {
-                        return false;
-                    }
-                }
-            } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
-                try {
-                    params = AlgorithmParameters.getInstance("DiffieHellman");
-                    spec = getFFDHEDHParameterSpec(namedGroup);
-                } catch (NoSuchAlgorithmException e) {
-                    return false;
-                }
-            }   // Otherwise, unsupported.
-
-            if ((params != null) && (spec != null)) {
-                try {
-                    params.init(spec);
-                } catch (InvalidParameterSpecException e) {
-                    return false;
-                }
-
-                // cache the parameters
-                namedGroupParams.put(namedGroup, params);
-
-                return true;
-            }
-
-            return false;
-        }
-
-        private static DHParameterSpec getFFDHEDHParameterSpec(
-                NamedGroup namedGroup) {
-            DHParameterSpec spec = null;
-            switch (namedGroup) {
-                case FFDHE_2048:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
-                    break;
-                case FFDHE_3072:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
-                    break;
-                case FFDHE_4096:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
-                    break;
-                case FFDHE_6144:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
-                    break;
-                case FFDHE_8192:
-                    spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
-            }
-
-            return spec;
-        }
-
-        private static DHParameterSpec getPredefinedDHParameterSpec(
-                NamedGroup namedGroup) {
-            DHParameterSpec spec = null;
-            switch (namedGroup) {
-                case FFDHE_2048:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(2048);
-                    break;
-                case FFDHE_3072:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(3072);
-                    break;
-                case FFDHE_4096:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(4096);
-                    break;
-                case FFDHE_6144:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(6144);
-                    break;
-                case FFDHE_8192:
-                    spec = PredefinedDHParameterSpecs.definedParams.get(8192);
-            }
-
-            return spec;
-        }
-
-        static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
-            if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
-                throw new RuntimeException(
-                        "Not a named EC group: " + namedGroup);
-            }
-
-            AlgorithmParameters params = namedGroupParams.get(namedGroup);
-            if (params == null) {
-                throw new RuntimeException(
-                        "Not a supported EC named group: " + namedGroup);
-            }
-
-            try {
-                return params.getParameterSpec(ECGenParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                // should be unlikely
-                return new ECGenParameterSpec(namedGroup.oid);
-            }
-        }
-
-        static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
-            if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
-                throw new RuntimeException(
-                        "Not a named DH group: " + namedGroup);
-            }
-
-            AlgorithmParameters params = namedGroupParams.get(namedGroup);
-            if (params == null) {
-                throw new RuntimeException(
-                        "Not a supported DH named group: " + namedGroup);
-            }
-
-            try {
-                return params.getParameterSpec(DHParameterSpec.class);
-            } catch (InvalidParameterSpecException ipse) {
-                // should be unlikely
-                return getPredefinedDHParameterSpec(namedGroup);
-            }
-        }
-
         // Is there any supported group permitted by the constraints?
         static boolean isActivatable(
-                AlgorithmConstraints constraints, NamedGroupType type) {
+                AlgorithmConstraints constraints, NamedGroupSpec type) {
 
             boolean hasFFDHEGroups = false;
             for (NamedGroup namedGroup : supportedNamedGroups) {
-                if (namedGroup.type == type) {
-                    if (constraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            namedGroup.algorithm,
-                            namedGroupParams.get(namedGroup))) {
-
+                if (namedGroup.isAvailable && namedGroup.spec == type) {
+                    if (namedGroup.isPermitted(constraints)) {
                         return true;
                     }
 
                     if (!hasFFDHEGroups &&
-                            (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                            (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                         hasFFDHEGroups = true;
                     }
                 }
@@ -710,20 +261,17 @@
             //
             // Note that the constraints checking on DHE parameters will be
             // performed during key exchanging in a handshake.
-            return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE;
+            return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
         }
 
         // Is the named group permitted by the constraints?
         static boolean isActivatable(
                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
-            if (!isSupported(namedGroup)) {
+            if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
                 return false;
             }
 
-            return constraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            namedGroup.algorithm,
-                            namedGroupParams.get(namedGroup));
+            return namedGroup.isPermitted(constraints);
         }
 
         // Is the named group supported?
@@ -739,16 +287,13 @@
 
         static NamedGroup getPreferredGroup(
                 ProtocolVersion negotiatedProtocol,
-                AlgorithmConstraints constraints, NamedGroupType type,
+                AlgorithmConstraints constraints, NamedGroupSpec[] types,
                 List<NamedGroup> requestedNamedGroups) {
             for (NamedGroup namedGroup : requestedNamedGroups) {
-                if ((namedGroup.type == type) &&
+                if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
                         namedGroup.isAvailable(negotiatedProtocol) &&
                         isSupported(namedGroup) &&
-                        constraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                namedGroup.algorithm,
-                                namedGroupParams.get(namedGroup))) {
+                        namedGroup.isPermitted(constraints)) {
                     return namedGroup;
                 }
             }
@@ -758,14 +303,11 @@
 
         static NamedGroup getPreferredGroup(
                 ProtocolVersion negotiatedProtocol,
-                AlgorithmConstraints constraints, NamedGroupType type) {
+                AlgorithmConstraints constraints, NamedGroupSpec[] types) {
             for (NamedGroup namedGroup : supportedNamedGroups) {
-                if ((namedGroup.type == type) &&
+                if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
                         namedGroup.isAvailable(negotiatedProtocol) &&
-                        constraints.permits(
-                                EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                                namedGroup.algorithm,
-                                namedGroupParams.get(namedGroup))) {
+                        namedGroup.isPermitted(constraints)) {
                     return namedGroup;
                 }
             }
@@ -805,15 +347,13 @@
                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
                 if ((!SupportedGroups.enableFFDHE) &&
-                    (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                    (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                     continue;
                 }
 
                 if (ng.isAvailable(chc.activeProtocols) &&
                         ng.isSupported(chc.activeCipherSuites) &&
-                        chc.algorithmConstraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, namedGroupParams.get(ng))) {
+                        ng.isPermitted(chc.algorithmConstraints)) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(
@@ -932,15 +472,13 @@
                     SupportedGroups.supportedNamedGroups.length);
             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
                 if ((!SupportedGroups.enableFFDHE) &&
-                    (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
+                    (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
                     continue;
                 }
 
                 if (ng.isAvailable(shc.activeProtocols) &&
                         ng.isSupported(shc.activeCipherSuites) &&
-                        shc.algorithmConstraints.permits(
-                            EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
-                            ng.algorithm, namedGroupParams.get(ng))) {
+                        ng.isPermitted(shc.algorithmConstraints)) {
                     namedGroups.add(ng);
                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
                     SSLLogger.fine(