src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 53734 cb1642ccc732
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.nio.ByteBuffer;
    29 import java.nio.ByteBuffer;
    30 import java.security.AlgorithmConstraints;
    30 import java.security.AlgorithmConstraints;
    31 import java.security.AlgorithmParameters;
       
    32 import java.security.CryptoPrimitive;
       
    33 import java.security.NoSuchAlgorithmException;
       
    34 import java.security.spec.AlgorithmParameterSpec;
       
    35 import java.security.spec.ECGenParameterSpec;
       
    36 import java.security.spec.ECParameterSpec;
       
    37 import java.security.spec.InvalidParameterSpecException;
       
    38 import java.text.MessageFormat;
    31 import java.text.MessageFormat;
    39 import java.util.ArrayList;
    32 import java.util.ArrayList;
    40 import java.util.Collections;
    33 import java.util.Collections;
    41 import java.util.EnumSet;
       
    42 import java.util.HashMap;
       
    43 import java.util.LinkedList;
    34 import java.util.LinkedList;
    44 import java.util.List;
    35 import java.util.List;
    45 import java.util.Locale;
    36 import java.util.Locale;
    46 import java.util.Map;
       
    47 import javax.crypto.spec.DHParameterSpec;
       
    48 import javax.net.ssl.SSLProtocolException;
    37 import javax.net.ssl.SSLProtocolException;
    49 import sun.security.action.GetPropertyAction;
    38 import sun.security.action.GetPropertyAction;
       
    39 import sun.security.ssl.NamedGroup.NamedGroupSpec;
    50 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
    40 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
    51 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
    41 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
    52 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    42 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    53 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    43 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    54 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    44 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    55 import sun.security.util.ECUtil;
    45 
    56 
    46 
    57 /**
    47 /**
    58  * Pack of the "supported_groups" extensions [RFC 4492/7919].
    48  * Pack of the "supported_groups" extensions [RFC 4492/7919].
    59  */
    49  */
    60 final class SupportedGroupsExtension {
    50 final class SupportedGroupsExtension {
   156                 return ioe.getMessage();
   146                 return ioe.getMessage();
   157             }
   147             }
   158         }
   148         }
   159     }
   149     }
   160 
   150 
   161     static enum NamedGroupType {
       
   162         NAMED_GROUP_ECDHE     ("EC"),
       
   163         NAMED_GROUP_FFDHE     ("DiffieHellman"),
       
   164         NAMED_GROUP_X25519    ("x25519"),
       
   165         NAMED_GROUP_X448      ("x448"),
       
   166         NAMED_GROUP_ARBITRARY ("EC"),
       
   167         NAMED_GROUP_NONE      ("");
       
   168 
       
   169         private final String algorithm;
       
   170 
       
   171         private NamedGroupType(String algorithm) {
       
   172             this.algorithm = algorithm;
       
   173         }
       
   174 
       
   175         boolean isSupported(List<CipherSuite> cipherSuites) {
       
   176             for (CipherSuite cs : cipherSuites) {
       
   177                 if (cs.keyExchange == null ||
       
   178                         cs.keyExchange.groupType == this) {
       
   179                     return true;
       
   180                 }
       
   181             }
       
   182 
       
   183             return false;
       
   184         }
       
   185     }
       
   186 
       
   187     static enum NamedGroup {
       
   188         // Elliptic Curves (RFC 4492)
       
   189         //
       
   190         // See sun.security.util.CurveDB for the OIDs
       
   191         // NIST K-163
       
   192         SECT163_K1  (0x0001, "sect163k1", "1.3.132.0.1",
       
   193                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   194                             ProtocolVersion.PROTOCOLS_TO_12),
       
   195         SECT163_R1  (0x0002, "sect163r1", "1.3.132.0.2",
       
   196                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   197                             ProtocolVersion.PROTOCOLS_TO_12),
       
   198 
       
   199         // NIST B-163
       
   200         SECT163_R2  (0x0003, "sect163r2", "1.3.132.0.15",
       
   201                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   202                             ProtocolVersion.PROTOCOLS_TO_12),
       
   203         SECT193_R1  (0x0004, "sect193r1", "1.3.132.0.24",
       
   204                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   205                             ProtocolVersion.PROTOCOLS_TO_12),
       
   206         SECT193_R2  (0x0005, "sect193r2", "1.3.132.0.25",
       
   207                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   208                             ProtocolVersion.PROTOCOLS_TO_12),
       
   209 
       
   210         // NIST K-233
       
   211         SECT233_K1  (0x0006, "sect233k1", "1.3.132.0.26",
       
   212                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   213                             ProtocolVersion.PROTOCOLS_TO_12),
       
   214 
       
   215         // NIST B-233
       
   216         SECT233_R1  (0x0007, "sect233r1", "1.3.132.0.27",
       
   217                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   218                             ProtocolVersion.PROTOCOLS_TO_12),
       
   219         SECT239_K1  (0x0008, "sect239k1", "1.3.132.0.3",
       
   220                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   221                             ProtocolVersion.PROTOCOLS_TO_12),
       
   222 
       
   223         // NIST K-283
       
   224         SECT283_K1  (0x0009, "sect283k1", "1.3.132.0.16",
       
   225                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   226                             ProtocolVersion.PROTOCOLS_TO_12),
       
   227 
       
   228         // NIST B-283
       
   229         SECT283_R1  (0x000A, "sect283r1", "1.3.132.0.17",
       
   230                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   231                             ProtocolVersion.PROTOCOLS_TO_12),
       
   232 
       
   233         // NIST K-409
       
   234         SECT409_K1  (0x000B, "sect409k1", "1.3.132.0.36",
       
   235                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   236                             ProtocolVersion.PROTOCOLS_TO_12),
       
   237 
       
   238         // NIST B-409
       
   239         SECT409_R1  (0x000C, "sect409r1", "1.3.132.0.37",
       
   240                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   241                             ProtocolVersion.PROTOCOLS_TO_12),
       
   242 
       
   243         // NIST K-571
       
   244         SECT571_K1  (0x000D, "sect571k1", "1.3.132.0.38",
       
   245                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   246                             ProtocolVersion.PROTOCOLS_TO_12),
       
   247 
       
   248         // NIST B-571
       
   249         SECT571_R1  (0x000E, "sect571r1", "1.3.132.0.39",
       
   250                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   251                             ProtocolVersion.PROTOCOLS_TO_12),
       
   252         SECP160_K1  (0x000F, "secp160k1", "1.3.132.0.9",
       
   253                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   254                             ProtocolVersion.PROTOCOLS_TO_12),
       
   255         SECP160_R1  (0x0010, "secp160r1", "1.3.132.0.8",
       
   256                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   257                             ProtocolVersion.PROTOCOLS_TO_12),
       
   258         SECP160_R2  (0x0011, "secp160r2", "1.3.132.0.30",
       
   259                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   260                             ProtocolVersion.PROTOCOLS_TO_12),
       
   261         SECP192_K1  (0x0012, "secp192k1", "1.3.132.0.31",
       
   262                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   263                             ProtocolVersion.PROTOCOLS_TO_12),
       
   264 
       
   265         // NIST P-192
       
   266         SECP192_R1  (0x0013, "secp192r1", "1.2.840.10045.3.1.1",
       
   267                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   268                             ProtocolVersion.PROTOCOLS_TO_12),
       
   269         SECP224_K1  (0x0014, "secp224k1", "1.3.132.0.32",
       
   270                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   271                             ProtocolVersion.PROTOCOLS_TO_12),
       
   272         // NIST P-224
       
   273         SECP224_R1  (0x0015, "secp224r1", "1.3.132.0.33",
       
   274                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   275                             ProtocolVersion.PROTOCOLS_TO_12),
       
   276         SECP256_K1  (0x0016, "secp256k1", "1.3.132.0.10",
       
   277                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   278                             ProtocolVersion.PROTOCOLS_TO_12),
       
   279 
       
   280         // NIST P-256
       
   281         SECP256_R1  (0x0017, "secp256r1", "1.2.840.10045.3.1.7",
       
   282                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   283                             ProtocolVersion.PROTOCOLS_TO_13),
       
   284 
       
   285         // NIST P-384
       
   286         SECP384_R1  (0x0018, "secp384r1", "1.3.132.0.34",
       
   287                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   288                             ProtocolVersion.PROTOCOLS_TO_13),
       
   289 
       
   290         // NIST P-521
       
   291         SECP521_R1  (0x0019, "secp521r1", "1.3.132.0.35",
       
   292                             NamedGroupType.NAMED_GROUP_ECDHE,
       
   293                             ProtocolVersion.PROTOCOLS_TO_13),
       
   294 
       
   295         // x25519 and x448
       
   296         X25519      (0x001D, "x25519", null,
       
   297                             NamedGroupType.NAMED_GROUP_X25519,
       
   298                             ProtocolVersion.PROTOCOLS_TO_13),
       
   299         X448        (0x001E, "x448", null,
       
   300                             NamedGroupType.NAMED_GROUP_X448,
       
   301                             ProtocolVersion.PROTOCOLS_TO_13),
       
   302 
       
   303         // Finite Field Diffie-Hellman Ephemeral Parameters (RFC 7919)
       
   304         FFDHE_2048  (0x0100, "ffdhe2048", null,
       
   305                             NamedGroupType.NAMED_GROUP_FFDHE,
       
   306                             ProtocolVersion.PROTOCOLS_TO_13),
       
   307         FFDHE_3072  (0x0101, "ffdhe3072", null,
       
   308                             NamedGroupType.NAMED_GROUP_FFDHE,
       
   309                             ProtocolVersion.PROTOCOLS_TO_13),
       
   310         FFDHE_4096  (0x0102, "ffdhe4096", null,
       
   311                             NamedGroupType.NAMED_GROUP_FFDHE,
       
   312                             ProtocolVersion.PROTOCOLS_TO_13),
       
   313         FFDHE_6144  (0x0103, "ffdhe6144", null,
       
   314                             NamedGroupType.NAMED_GROUP_FFDHE,
       
   315                             ProtocolVersion.PROTOCOLS_TO_13),
       
   316         FFDHE_8192  (0x0104, "ffdhe8192", null,
       
   317                             NamedGroupType.NAMED_GROUP_FFDHE,
       
   318                             ProtocolVersion.PROTOCOLS_TO_13),
       
   319 
       
   320         // Elliptic Curves (RFC 4492)
       
   321         //
       
   322         // arbitrary prime and characteristic-2 curves
       
   323         ARBITRARY_PRIME  (0xFF01, "arbitrary_explicit_prime_curves", null,
       
   324                             NamedGroupType.NAMED_GROUP_ARBITRARY,
       
   325                             ProtocolVersion.PROTOCOLS_TO_12),
       
   326         ARBITRARY_CHAR2  (0xFF02, "arbitrary_explicit_char2_curves", null,
       
   327                             NamedGroupType.NAMED_GROUP_ARBITRARY,
       
   328                             ProtocolVersion.PROTOCOLS_TO_12);
       
   329 
       
   330         final int id;               // hash + signature
       
   331         final NamedGroupType type;  // group type
       
   332         final String name;          // literal name
       
   333         final String oid;           // object identifier of the named group
       
   334         final String algorithm;     // signature algorithm
       
   335         final ProtocolVersion[] supportedProtocols;
       
   336 
       
   337         private NamedGroup(int id, String name, String oid,
       
   338                 NamedGroupType namedGroupType,
       
   339                 ProtocolVersion[] supportedProtocols) {
       
   340             this.id = id;
       
   341             this.type = namedGroupType;
       
   342             this.name = name;
       
   343             this.oid = oid;
       
   344             this.algorithm = namedGroupType.algorithm;
       
   345             this.supportedProtocols = supportedProtocols;
       
   346         }
       
   347 
       
   348         static NamedGroup valueOf(int id) {
       
   349             for (NamedGroup group : NamedGroup.values()) {
       
   350                 if (group.id == id) {
       
   351                     return group;
       
   352                 }
       
   353             }
       
   354 
       
   355             return null;
       
   356         }
       
   357 
       
   358         static NamedGroup valueOf(ECParameterSpec params) {
       
   359             String oid = ECUtil.getCurveName(null, params);
       
   360             if ((oid != null) && (!oid.isEmpty())) {
       
   361                 for (NamedGroup group : NamedGroup.values()) {
       
   362                     if ((group.type == NamedGroupType.NAMED_GROUP_ECDHE) &&
       
   363                             oid.equals(group.oid)) {
       
   364                         return group;
       
   365                     }
       
   366                 }
       
   367             }
       
   368 
       
   369             return null;
       
   370         }
       
   371 
       
   372         static NamedGroup valueOf(DHParameterSpec params) {
       
   373             for (Map.Entry<NamedGroup, AlgorithmParameters> me :
       
   374                     SupportedGroups.namedGroupParams.entrySet()) {
       
   375                 NamedGroup ng = me.getKey();
       
   376                 if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) {
       
   377                     continue;
       
   378                 }
       
   379 
       
   380                 DHParameterSpec ngParams = null;
       
   381                 AlgorithmParameters aps = me.getValue();
       
   382                 try {
       
   383                     ngParams = aps.getParameterSpec(DHParameterSpec.class);
       
   384                 } catch (InvalidParameterSpecException ipse) {
       
   385                     // should be unlikely
       
   386                 }
       
   387 
       
   388                 if (ngParams == null) {
       
   389                     continue;
       
   390                 }
       
   391 
       
   392                 if (ngParams.getP().equals(params.getP()) &&
       
   393                         ngParams.getG().equals(params.getG())) {
       
   394                     return ng;
       
   395                 }
       
   396             }
       
   397 
       
   398             return null;
       
   399         }
       
   400 
       
   401         static NamedGroup nameOf(String name) {
       
   402             for (NamedGroup group : NamedGroup.values()) {
       
   403                 if (group.name.equals(name)) {
       
   404                     return group;
       
   405                 }
       
   406             }
       
   407 
       
   408             return null;
       
   409         }
       
   410 
       
   411         static String nameOf(int id) {
       
   412             for (NamedGroup group : NamedGroup.values()) {
       
   413                 if (group.id == id) {
       
   414                     return group.name;
       
   415                 }
       
   416             }
       
   417 
       
   418             return "UNDEFINED-NAMED-GROUP(" + id + ")";
       
   419         }
       
   420 
       
   421         boolean isAvailable(List<ProtocolVersion> protocolVersions) {
       
   422             for (ProtocolVersion pv : supportedProtocols) {
       
   423                 if (protocolVersions.contains(pv)) {
       
   424                     return true;
       
   425                 }
       
   426             }
       
   427             return false;
       
   428         }
       
   429 
       
   430         boolean isAvailable(ProtocolVersion protocolVersion) {
       
   431             for (ProtocolVersion pv : supportedProtocols) {
       
   432                 if (protocolVersion == pv) {
       
   433                     return true;
       
   434                 }
       
   435             }
       
   436             return false;
       
   437         }
       
   438 
       
   439         boolean isSupported(List<CipherSuite> cipherSuites) {
       
   440             for (CipherSuite cs : cipherSuites) {
       
   441                 boolean isMatch = isAvailable(cs.supportedProtocols);
       
   442                 if (isMatch && (cs.keyExchange == null ||
       
   443                         cs.keyExchange.groupType == type)) {
       
   444                     return true;
       
   445                 }
       
   446             }
       
   447             return false;
       
   448         }
       
   449 
       
   450         // lazy loading of parameters
       
   451         AlgorithmParameters getParameters() {
       
   452             return SupportedGroups.namedGroupParams.get(this);
       
   453         }
       
   454 
       
   455         AlgorithmParameterSpec getParameterSpec() {
       
   456             if (this.type == NamedGroupType.NAMED_GROUP_ECDHE) {
       
   457                 return SupportedGroups.getECGenParamSpec(this);
       
   458             } else if (this.type == NamedGroupType.NAMED_GROUP_FFDHE) {
       
   459                 return SupportedGroups.getDHParameterSpec(this);
       
   460             }
       
   461 
       
   462             return null;
       
   463         }
       
   464     }
       
   465 
       
   466     static class SupportedGroups {
   151     static class SupportedGroups {
   467         // To switch off the supported_groups extension for DHE cipher suite.
   152         // To switch off the supported_groups extension for DHE cipher suite.
   468         static final boolean enableFFDHE =
   153         static final boolean enableFFDHE =
   469                 Utilities.getBooleanProperty("jsse.enableFFDHE", true);
   154                 Utilities.getBooleanProperty("jsse.enableFFDHE", true);
   470 
       
   471         // cache to speed up the parameters construction
       
   472         static final Map<NamedGroup,
       
   473                     AlgorithmParameters> namedGroupParams = new HashMap<>();
       
   474 
   155 
   475         // the supported named groups
   156         // the supported named groups
   476         static final NamedGroup[] supportedNamedGroups;
   157         static final NamedGroup[] supportedNamedGroups;
   477 
   158 
   478         static {
   159         static {
   500                 for (String group : groups) {
   181                 for (String group : groups) {
   501                     group = group.trim();
   182                     group = group.trim();
   502                     if (!group.isEmpty()) {
   183                     if (!group.isEmpty()) {
   503                         NamedGroup namedGroup = NamedGroup.nameOf(group);
   184                         NamedGroup namedGroup = NamedGroup.nameOf(group);
   504                         if (namedGroup != null) {
   185                         if (namedGroup != null) {
   505                             if (isAvailableGroup(namedGroup)) {
   186                             if (namedGroup.isAvailable) {
   506                                 groupList.add(namedGroup);
   187                                 groupList.add(namedGroup);
   507                             }
   188                             }
   508                         }   // ignore unknown groups
   189                         }   // ignore unknown groups
   509                     }
   190                     }
   510                 }
   191                 }
   514                             "System property jdk.tls.namedGroups(" +
   195                             "System property jdk.tls.namedGroups(" +
   515                             property + ") contains no supported named groups");
   196                             property + ") contains no supported named groups");
   516                 }
   197                 }
   517             } else {        // default groups
   198             } else {        // default groups
   518                 NamedGroup[] groups = new NamedGroup[] {
   199                 NamedGroup[] groups = new NamedGroup[] {
   519                         // NIST curves first
   200 
       
   201                         // Primary XDH (RFC 7748) curves
       
   202                         NamedGroup.X25519,
       
   203 
       
   204                         // Primary NIST Suite B curves
   520                         NamedGroup.SECP256_R1,
   205                         NamedGroup.SECP256_R1,
   521                         NamedGroup.SECP384_R1,
   206                         NamedGroup.SECP384_R1,
   522                         NamedGroup.SECP521_R1,
   207                         NamedGroup.SECP521_R1,
   523                         NamedGroup.SECT283_K1,
   208 
   524                         NamedGroup.SECT283_R1,
   209                         // Secondary XDH curves
   525                         NamedGroup.SECT409_K1,
   210                         NamedGroup.X448,
   526                         NamedGroup.SECT409_R1,
   211 
   527                         NamedGroup.SECT571_K1,
   212                         // FFDHE (RFC 7919)
   528                         NamedGroup.SECT571_R1,
       
   529 
       
   530                         // non-NIST curves
       
   531                         NamedGroup.SECP256_K1,
       
   532 
       
   533                         // FFDHE 2048
       
   534                         NamedGroup.FFDHE_2048,
   213                         NamedGroup.FFDHE_2048,
   535                         NamedGroup.FFDHE_3072,
   214                         NamedGroup.FFDHE_3072,
   536                         NamedGroup.FFDHE_4096,
   215                         NamedGroup.FFDHE_4096,
   537                         NamedGroup.FFDHE_6144,
   216                         NamedGroup.FFDHE_6144,
   538                         NamedGroup.FFDHE_8192,
   217                         NamedGroup.FFDHE_8192,
   539                     };
   218                     };
   540 
   219 
   541                 groupList = new ArrayList<>(groups.length);
   220                 groupList = new ArrayList<>(groups.length);
   542                 for (NamedGroup group : groups) {
   221                 for (NamedGroup group : groups) {
   543                     if (isAvailableGroup(group)) {
   222                     if (group.isAvailable) {
   544                         groupList.add(group);
   223                         groupList.add(group);
   545                     }
   224                     }
   546                 }
   225                 }
   547 
   226 
   548                 if (groupList.isEmpty() &&
   227                 if (groupList.isEmpty() &&
   556             for (NamedGroup namedGroup : groupList) {
   235             for (NamedGroup namedGroup : groupList) {
   557                 supportedNamedGroups[i++] = namedGroup;
   236                 supportedNamedGroups[i++] = namedGroup;
   558             }
   237             }
   559         }
   238         }
   560 
   239 
   561         // check whether the group is supported by the underlying providers
       
   562         private static boolean isAvailableGroup(NamedGroup namedGroup) {
       
   563             AlgorithmParameters params = null;
       
   564             AlgorithmParameterSpec spec = null;
       
   565             if (namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
       
   566                 if (namedGroup.oid != null) {
       
   567                     try {
       
   568                         params = AlgorithmParameters.getInstance("EC");
       
   569                         spec = new ECGenParameterSpec(namedGroup.oid);
       
   570                     } catch (NoSuchAlgorithmException e) {
       
   571                         return false;
       
   572                     }
       
   573                 }
       
   574             } else if (namedGroup.type == NamedGroupType.NAMED_GROUP_FFDHE) {
       
   575                 try {
       
   576                     params = AlgorithmParameters.getInstance("DiffieHellman");
       
   577                     spec = getFFDHEDHParameterSpec(namedGroup);
       
   578                 } catch (NoSuchAlgorithmException e) {
       
   579                     return false;
       
   580                 }
       
   581             }   // Otherwise, unsupported.
       
   582 
       
   583             if ((params != null) && (spec != null)) {
       
   584                 try {
       
   585                     params.init(spec);
       
   586                 } catch (InvalidParameterSpecException e) {
       
   587                     return false;
       
   588                 }
       
   589 
       
   590                 // cache the parameters
       
   591                 namedGroupParams.put(namedGroup, params);
       
   592 
       
   593                 return true;
       
   594             }
       
   595 
       
   596             return false;
       
   597         }
       
   598 
       
   599         private static DHParameterSpec getFFDHEDHParameterSpec(
       
   600                 NamedGroup namedGroup) {
       
   601             DHParameterSpec spec = null;
       
   602             switch (namedGroup) {
       
   603                 case FFDHE_2048:
       
   604                     spec = PredefinedDHParameterSpecs.ffdheParams.get(2048);
       
   605                     break;
       
   606                 case FFDHE_3072:
       
   607                     spec = PredefinedDHParameterSpecs.ffdheParams.get(3072);
       
   608                     break;
       
   609                 case FFDHE_4096:
       
   610                     spec = PredefinedDHParameterSpecs.ffdheParams.get(4096);
       
   611                     break;
       
   612                 case FFDHE_6144:
       
   613                     spec = PredefinedDHParameterSpecs.ffdheParams.get(6144);
       
   614                     break;
       
   615                 case FFDHE_8192:
       
   616                     spec = PredefinedDHParameterSpecs.ffdheParams.get(8192);
       
   617             }
       
   618 
       
   619             return spec;
       
   620         }
       
   621 
       
   622         private static DHParameterSpec getPredefinedDHParameterSpec(
       
   623                 NamedGroup namedGroup) {
       
   624             DHParameterSpec spec = null;
       
   625             switch (namedGroup) {
       
   626                 case FFDHE_2048:
       
   627                     spec = PredefinedDHParameterSpecs.definedParams.get(2048);
       
   628                     break;
       
   629                 case FFDHE_3072:
       
   630                     spec = PredefinedDHParameterSpecs.definedParams.get(3072);
       
   631                     break;
       
   632                 case FFDHE_4096:
       
   633                     spec = PredefinedDHParameterSpecs.definedParams.get(4096);
       
   634                     break;
       
   635                 case FFDHE_6144:
       
   636                     spec = PredefinedDHParameterSpecs.definedParams.get(6144);
       
   637                     break;
       
   638                 case FFDHE_8192:
       
   639                     spec = PredefinedDHParameterSpecs.definedParams.get(8192);
       
   640             }
       
   641 
       
   642             return spec;
       
   643         }
       
   644 
       
   645         static ECGenParameterSpec getECGenParamSpec(NamedGroup namedGroup) {
       
   646             if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) {
       
   647                 throw new RuntimeException(
       
   648                         "Not a named EC group: " + namedGroup);
       
   649             }
       
   650 
       
   651             AlgorithmParameters params = namedGroupParams.get(namedGroup);
       
   652             if (params == null) {
       
   653                 throw new RuntimeException(
       
   654                         "Not a supported EC named group: " + namedGroup);
       
   655             }
       
   656 
       
   657             try {
       
   658                 return params.getParameterSpec(ECGenParameterSpec.class);
       
   659             } catch (InvalidParameterSpecException ipse) {
       
   660                 // should be unlikely
       
   661                 return new ECGenParameterSpec(namedGroup.oid);
       
   662             }
       
   663         }
       
   664 
       
   665         static DHParameterSpec getDHParameterSpec(NamedGroup namedGroup) {
       
   666             if (namedGroup.type != NamedGroupType.NAMED_GROUP_FFDHE) {
       
   667                 throw new RuntimeException(
       
   668                         "Not a named DH group: " + namedGroup);
       
   669             }
       
   670 
       
   671             AlgorithmParameters params = namedGroupParams.get(namedGroup);
       
   672             if (params == null) {
       
   673                 throw new RuntimeException(
       
   674                         "Not a supported DH named group: " + namedGroup);
       
   675             }
       
   676 
       
   677             try {
       
   678                 return params.getParameterSpec(DHParameterSpec.class);
       
   679             } catch (InvalidParameterSpecException ipse) {
       
   680                 // should be unlikely
       
   681                 return getPredefinedDHParameterSpec(namedGroup);
       
   682             }
       
   683         }
       
   684 
       
   685         // Is there any supported group permitted by the constraints?
   240         // Is there any supported group permitted by the constraints?
   686         static boolean isActivatable(
   241         static boolean isActivatable(
   687                 AlgorithmConstraints constraints, NamedGroupType type) {
   242                 AlgorithmConstraints constraints, NamedGroupSpec type) {
   688 
   243 
   689             boolean hasFFDHEGroups = false;
   244             boolean hasFFDHEGroups = false;
   690             for (NamedGroup namedGroup : supportedNamedGroups) {
   245             for (NamedGroup namedGroup : supportedNamedGroups) {
   691                 if (namedGroup.type == type) {
   246                 if (namedGroup.isAvailable && namedGroup.spec == type) {
   692                     if (constraints.permits(
   247                     if (namedGroup.isPermitted(constraints)) {
   693                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   694                             namedGroup.algorithm,
       
   695                             namedGroupParams.get(namedGroup))) {
       
   696 
       
   697                         return true;
   248                         return true;
   698                     }
   249                     }
   699 
   250 
   700                     if (!hasFFDHEGroups &&
   251                     if (!hasFFDHEGroups &&
   701                             (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   252                             (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   702                         hasFFDHEGroups = true;
   253                         hasFFDHEGroups = true;
   703                     }
   254                     }
   704                 }
   255                 }
   705             }
   256             }
   706 
   257 
   708             // compatible mode (using DHE cipher suite without FFDHE extension)
   259             // compatible mode (using DHE cipher suite without FFDHE extension)
   709             // is allowed.
   260             // is allowed.
   710             //
   261             //
   711             // Note that the constraints checking on DHE parameters will be
   262             // Note that the constraints checking on DHE parameters will be
   712             // performed during key exchanging in a handshake.
   263             // performed during key exchanging in a handshake.
   713             return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE;
   264             return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
   714         }
   265         }
   715 
   266 
   716         // Is the named group permitted by the constraints?
   267         // Is the named group permitted by the constraints?
   717         static boolean isActivatable(
   268         static boolean isActivatable(
   718                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
   269                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
   719             if (!isSupported(namedGroup)) {
   270             if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
   720                 return false;
   271                 return false;
   721             }
   272             }
   722 
   273 
   723             return constraints.permits(
   274             return namedGroup.isPermitted(constraints);
   724                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   725                             namedGroup.algorithm,
       
   726                             namedGroupParams.get(namedGroup));
       
   727         }
   275         }
   728 
   276 
   729         // Is the named group supported?
   277         // Is the named group supported?
   730         static boolean isSupported(NamedGroup namedGroup) {
   278         static boolean isSupported(NamedGroup namedGroup) {
   731             for (NamedGroup group : supportedNamedGroups) {
   279             for (NamedGroup group : supportedNamedGroups) {
   737             return false;
   285             return false;
   738         }
   286         }
   739 
   287 
   740         static NamedGroup getPreferredGroup(
   288         static NamedGroup getPreferredGroup(
   741                 ProtocolVersion negotiatedProtocol,
   289                 ProtocolVersion negotiatedProtocol,
   742                 AlgorithmConstraints constraints, NamedGroupType type,
   290                 AlgorithmConstraints constraints, NamedGroupSpec[] types,
   743                 List<NamedGroup> requestedNamedGroups) {
   291                 List<NamedGroup> requestedNamedGroups) {
   744             for (NamedGroup namedGroup : requestedNamedGroups) {
   292             for (NamedGroup namedGroup : requestedNamedGroups) {
   745                 if ((namedGroup.type == type) &&
   293                 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
   746                         namedGroup.isAvailable(negotiatedProtocol) &&
   294                         namedGroup.isAvailable(negotiatedProtocol) &&
   747                         isSupported(namedGroup) &&
   295                         isSupported(namedGroup) &&
   748                         constraints.permits(
   296                         namedGroup.isPermitted(constraints)) {
   749                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   750                                 namedGroup.algorithm,
       
   751                                 namedGroupParams.get(namedGroup))) {
       
   752                     return namedGroup;
   297                     return namedGroup;
   753                 }
   298                 }
   754             }
   299             }
   755 
   300 
   756             return null;
   301             return null;
   757         }
   302         }
   758 
   303 
   759         static NamedGroup getPreferredGroup(
   304         static NamedGroup getPreferredGroup(
   760                 ProtocolVersion negotiatedProtocol,
   305                 ProtocolVersion negotiatedProtocol,
   761                 AlgorithmConstraints constraints, NamedGroupType type) {
   306                 AlgorithmConstraints constraints, NamedGroupSpec[] types) {
   762             for (NamedGroup namedGroup : supportedNamedGroups) {
   307             for (NamedGroup namedGroup : supportedNamedGroups) {
   763                 if ((namedGroup.type == type) &&
   308                 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
   764                         namedGroup.isAvailable(negotiatedProtocol) &&
   309                         namedGroup.isAvailable(negotiatedProtocol) &&
   765                         constraints.permits(
   310                         namedGroup.isPermitted(constraints)) {
   766                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   767                                 namedGroup.algorithm,
       
   768                                 namedGroupParams.get(namedGroup))) {
       
   769                     return namedGroup;
   311                     return namedGroup;
   770                 }
   312                 }
   771             }
   313             }
   772 
   314 
   773             return null;
   315             return null;
   803             // Produce the extension.
   345             // Produce the extension.
   804             ArrayList<NamedGroup> namedGroups =
   346             ArrayList<NamedGroup> namedGroups =
   805                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
   347                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
   806             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   348             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   807                 if ((!SupportedGroups.enableFFDHE) &&
   349                 if ((!SupportedGroups.enableFFDHE) &&
   808                     (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   350                     (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   809                     continue;
   351                     continue;
   810                 }
   352                 }
   811 
   353 
   812                 if (ng.isAvailable(chc.activeProtocols) &&
   354                 if (ng.isAvailable(chc.activeProtocols) &&
   813                         ng.isSupported(chc.activeCipherSuites) &&
   355                         ng.isSupported(chc.activeCipherSuites) &&
   814                         chc.algorithmConstraints.permits(
   356                         ng.isPermitted(chc.algorithmConstraints)) {
   815                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   816                             ng.algorithm, namedGroupParams.get(ng))) {
       
   817                     namedGroups.add(ng);
   357                     namedGroups.add(ng);
   818                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   358                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   819                     SSLLogger.fine(
   359                     SSLLogger.fine(
   820                         "Ignore inactive or disabled named group: " + ng.name);
   360                         "Ignore inactive or disabled named group: " + ng.name);
   821                 }
   361                 }
   930             // they are currently supported by the client.
   470             // they are currently supported by the client.
   931             ArrayList<NamedGroup> namedGroups = new ArrayList<>(
   471             ArrayList<NamedGroup> namedGroups = new ArrayList<>(
   932                     SupportedGroups.supportedNamedGroups.length);
   472                     SupportedGroups.supportedNamedGroups.length);
   933             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   473             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   934                 if ((!SupportedGroups.enableFFDHE) &&
   474                 if ((!SupportedGroups.enableFFDHE) &&
   935                     (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   475                     (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   936                     continue;
   476                     continue;
   937                 }
   477                 }
   938 
   478 
   939                 if (ng.isAvailable(shc.activeProtocols) &&
   479                 if (ng.isAvailable(shc.activeProtocols) &&
   940                         ng.isSupported(shc.activeCipherSuites) &&
   480                         ng.isSupported(shc.activeCipherSuites) &&
   941                         shc.algorithmConstraints.permits(
   481                         ng.isPermitted(shc.algorithmConstraints)) {
   942                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   943                             ng.algorithm, namedGroupParams.get(ng))) {
       
   944                     namedGroups.add(ng);
   482                     namedGroups.add(ng);
   945                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   483                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   946                     SSLLogger.fine(
   484                     SSLLogger.fine(
   947                         "Ignore inactive or disabled named group: " + ng.name);
   485                         "Ignore inactive or disabled named group: " + ng.name);
   948                 }
   486                 }