src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java
changeset 57718 a93b7b28f644
parent 55353 946f7f2d321c
child 58637 d66bdf0e2dfe
equal deleted inserted replaced
57716:bfcdcd00e4fb 57718:a93b7b28f644
    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.spec.ECGenParameterSpec;
       
    34 import java.security.spec.InvalidParameterSpecException;
       
    35 import java.text.MessageFormat;
    31 import java.text.MessageFormat;
    36 import java.util.ArrayList;
    32 import java.util.ArrayList;
    37 import java.util.Collections;
    33 import java.util.Collections;
    38 import java.util.EnumSet;
       
    39 import java.util.LinkedList;
    34 import java.util.LinkedList;
    40 import java.util.List;
    35 import java.util.List;
    41 import java.util.Locale;
    36 import java.util.Locale;
    42 import javax.net.ssl.SSLProtocolException;
    37 import javax.net.ssl.SSLProtocolException;
    43 import sun.security.action.GetPropertyAction;
    38 import sun.security.action.GetPropertyAction;
    44 import sun.security.ssl.NamedGroup.NamedGroupType;
    39 import sun.security.ssl.NamedGroup.NamedGroupSpec;
    45 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
    40 import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
    46 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
    41 import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
    47 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    42 import sun.security.ssl.SSLExtension.ExtensionConsumer;
    48 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    43 import sun.security.ssl.SSLExtension.SSLExtensionSpec;
    49 import sun.security.ssl.SSLHandshake.HandshakeMessage;
    44 import sun.security.ssl.SSLHandshake.HandshakeMessage;
   186                 for (String group : groups) {
   181                 for (String group : groups) {
   187                     group = group.trim();
   182                     group = group.trim();
   188                     if (!group.isEmpty()) {
   183                     if (!group.isEmpty()) {
   189                         NamedGroup namedGroup = NamedGroup.nameOf(group);
   184                         NamedGroup namedGroup = NamedGroup.nameOf(group);
   190                         if (namedGroup != null) {
   185                         if (namedGroup != null) {
   191                             if (isAvailableGroup(namedGroup)) {
   186                             if (namedGroup.isAvailable) {
   192                                 groupList.add(namedGroup);
   187                                 groupList.add(namedGroup);
   193                             }
   188                             }
   194                         }   // ignore unknown groups
   189                         }   // ignore unknown groups
   195                     }
   190                     }
   196                 }
   191                 }
   233                         NamedGroup.FFDHE_8192,
   228                         NamedGroup.FFDHE_8192,
   234                     };
   229                     };
   235 
   230 
   236                 groupList = new ArrayList<>(groups.length);
   231                 groupList = new ArrayList<>(groups.length);
   237                 for (NamedGroup group : groups) {
   232                 for (NamedGroup group : groups) {
   238                     if (isAvailableGroup(group)) {
   233                     if (group.isAvailable) {
   239                         groupList.add(group);
   234                         groupList.add(group);
   240                     }
   235                     }
   241                 }
   236                 }
   242 
   237 
   243                 if (groupList.isEmpty() &&
   238                 if (groupList.isEmpty() &&
   251             for (NamedGroup namedGroup : groupList) {
   246             for (NamedGroup namedGroup : groupList) {
   252                 supportedNamedGroups[i++] = namedGroup;
   247                 supportedNamedGroups[i++] = namedGroup;
   253             }
   248             }
   254         }
   249         }
   255 
   250 
   256         // check whether the group is supported by the underlying providers
       
   257         private static boolean isAvailableGroup(NamedGroup namedGroup) {
       
   258             return namedGroup.isAvailableGroup();
       
   259         }
       
   260 
       
   261         static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
       
   262             if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
       
   263                  throw new RuntimeException(
       
   264                          "Not a named EC group: " + ng);
       
   265             }
       
   266 
       
   267             // parameters are non-null
       
   268             AlgorithmParameters params = ng.getParameters();
       
   269             try {
       
   270                 return params.getParameterSpec(ECGenParameterSpec.class);
       
   271             } catch (InvalidParameterSpecException ipse) {
       
   272                 // should be unlikely
       
   273                 return new ECGenParameterSpec(ng.oid);
       
   274             }
       
   275         }
       
   276 
       
   277         static AlgorithmParameters getParameters(NamedGroup ng) {
       
   278             return ng.getParameters();
       
   279         }
       
   280 
       
   281         // Is there any supported group permitted by the constraints?
   251         // Is there any supported group permitted by the constraints?
   282         static boolean isActivatable(
   252         static boolean isActivatable(
   283                 AlgorithmConstraints constraints, NamedGroupType type) {
   253                 AlgorithmConstraints constraints, NamedGroupSpec type) {
   284 
   254 
   285             boolean hasFFDHEGroups = false;
   255             boolean hasFFDHEGroups = false;
   286             for (NamedGroup namedGroup : supportedNamedGroups) {
   256             for (NamedGroup namedGroup : supportedNamedGroups) {
   287                 if (namedGroup.type == type) {
   257                 if (namedGroup.isAvailable && namedGroup.spec == type) {
   288                     if (constraints.permits(
   258                     if (namedGroup.isPermitted(constraints)) {
   289                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   290                             namedGroup.algorithm,
       
   291                             getParameters(namedGroup))) {
       
   292 
       
   293                         return true;
   259                         return true;
   294                     }
   260                     }
   295 
   261 
   296                     if (!hasFFDHEGroups &&
   262                     if (!hasFFDHEGroups &&
   297                             (type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   263                             (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   298                         hasFFDHEGroups = true;
   264                         hasFFDHEGroups = true;
   299                     }
   265                     }
   300                 }
   266                 }
   301             }
   267             }
   302 
   268 
   304             // compatible mode (using DHE cipher suite without FFDHE extension)
   270             // compatible mode (using DHE cipher suite without FFDHE extension)
   305             // is allowed.
   271             // is allowed.
   306             //
   272             //
   307             // Note that the constraints checking on DHE parameters will be
   273             // Note that the constraints checking on DHE parameters will be
   308             // performed during key exchanging in a handshake.
   274             // performed during key exchanging in a handshake.
   309             return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE;
   275             return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
   310         }
   276         }
   311 
   277 
   312         // Is the named group permitted by the constraints?
   278         // Is the named group permitted by the constraints?
   313         static boolean isActivatable(
   279         static boolean isActivatable(
   314                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
   280                 AlgorithmConstraints constraints, NamedGroup namedGroup) {
   315             if (!isSupported(namedGroup)) {
   281             if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
   316                 return false;
   282                 return false;
   317             }
   283             }
   318 
   284 
   319             return constraints.permits(
   285             return namedGroup.isPermitted(constraints);
   320                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   321                             namedGroup.algorithm,
       
   322                             getParameters(namedGroup));
       
   323         }
   286         }
   324 
   287 
   325         // Is the named group supported?
   288         // Is the named group supported?
   326         static boolean isSupported(NamedGroup namedGroup) {
   289         static boolean isSupported(NamedGroup namedGroup) {
   327             for (NamedGroup group : supportedNamedGroups) {
   290             for (NamedGroup group : supportedNamedGroups) {
   333             return false;
   296             return false;
   334         }
   297         }
   335 
   298 
   336         static NamedGroup getPreferredGroup(
   299         static NamedGroup getPreferredGroup(
   337                 ProtocolVersion negotiatedProtocol,
   300                 ProtocolVersion negotiatedProtocol,
   338                 AlgorithmConstraints constraints, NamedGroupType[] types,
   301                 AlgorithmConstraints constraints, NamedGroupSpec[] types,
   339                 List<NamedGroup> requestedNamedGroups) {
   302                 List<NamedGroup> requestedNamedGroups) {
   340             for (NamedGroup namedGroup : requestedNamedGroups) {
   303             for (NamedGroup namedGroup : requestedNamedGroups) {
   341                 if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
   304                 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
   342                         namedGroup.isAvailable(negotiatedProtocol) &&
   305                         namedGroup.isAvailable(negotiatedProtocol) &&
   343                         isSupported(namedGroup) &&
   306                         isSupported(namedGroup) &&
   344                         constraints.permits(
   307                         namedGroup.isPermitted(constraints)) {
   345                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   346                                 namedGroup.algorithm,
       
   347                                 getParameters(namedGroup))) {
       
   348                     return namedGroup;
   308                     return namedGroup;
   349                 }
   309                 }
   350             }
   310             }
   351 
   311 
   352             return null;
   312             return null;
   353         }
   313         }
   354 
   314 
   355         static NamedGroup getPreferredGroup(
   315         static NamedGroup getPreferredGroup(
   356                 ProtocolVersion negotiatedProtocol,
   316                 ProtocolVersion negotiatedProtocol,
   357                 AlgorithmConstraints constraints, NamedGroupType[] types) {
   317                 AlgorithmConstraints constraints, NamedGroupSpec[] types) {
   358             for (NamedGroup namedGroup : supportedNamedGroups) {
   318             for (NamedGroup namedGroup : supportedNamedGroups) {
   359                 if ((NamedGroupType.arrayContains(types, namedGroup.type)) &&
   319                 if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
   360                         namedGroup.isAvailable(negotiatedProtocol) &&
   320                         namedGroup.isAvailable(negotiatedProtocol) &&
   361                         constraints.permits(
   321                         namedGroup.isPermitted(constraints)) {
   362                                 EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   363                                 namedGroup.algorithm,
       
   364                                 getParameters(namedGroup))) {
       
   365                     return namedGroup;
   322                     return namedGroup;
   366                 }
   323                 }
   367             }
   324             }
   368 
   325 
   369             return null;
   326             return null;
   399             // Produce the extension.
   356             // Produce the extension.
   400             ArrayList<NamedGroup> namedGroups =
   357             ArrayList<NamedGroup> namedGroups =
   401                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
   358                 new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
   402             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   359             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   403                 if ((!SupportedGroups.enableFFDHE) &&
   360                 if ((!SupportedGroups.enableFFDHE) &&
   404                     (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   361                     (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   405                     continue;
   362                     continue;
   406                 }
   363                 }
   407 
   364 
   408                 if (ng.isAvailable(chc.activeProtocols) &&
   365                 if (ng.isAvailable(chc.activeProtocols) &&
   409                         ng.isSupported(chc.activeCipherSuites) &&
   366                         ng.isSupported(chc.activeCipherSuites) &&
   410                         chc.algorithmConstraints.permits(
   367                         ng.isPermitted(chc.algorithmConstraints)) {
   411                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   412                             ng.algorithm, getParameters(ng))) {
       
   413                     namedGroups.add(ng);
   368                     namedGroups.add(ng);
   414                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   369                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   415                     SSLLogger.fine(
   370                     SSLLogger.fine(
   416                         "Ignore inactive or disabled named group: " + ng.name);
   371                         "Ignore inactive or disabled named group: " + ng.name);
   417                 }
   372                 }
   526             // they are currently supported by the client.
   481             // they are currently supported by the client.
   527             ArrayList<NamedGroup> namedGroups = new ArrayList<>(
   482             ArrayList<NamedGroup> namedGroups = new ArrayList<>(
   528                     SupportedGroups.supportedNamedGroups.length);
   483                     SupportedGroups.supportedNamedGroups.length);
   529             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   484             for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
   530                 if ((!SupportedGroups.enableFFDHE) &&
   485                 if ((!SupportedGroups.enableFFDHE) &&
   531                     (ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) {
   486                     (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
   532                     continue;
   487                     continue;
   533                 }
   488                 }
   534 
   489 
   535                 if (ng.isAvailable(shc.activeProtocols) &&
   490                 if (ng.isAvailable(shc.activeProtocols) &&
   536                         ng.isSupported(shc.activeCipherSuites) &&
   491                         ng.isSupported(shc.activeCipherSuites) &&
   537                         shc.algorithmConstraints.permits(
   492                         ng.isPermitted(shc.algorithmConstraints)) {
   538                             EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
       
   539                             ng.algorithm, getParameters(ng))) {
       
   540                     namedGroups.add(ng);
   493                     namedGroups.add(ng);
   541                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   494                 } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
   542                     SSLLogger.fine(
   495                     SSLLogger.fine(
   543                         "Ignore inactive or disabled named group: " + ng.name);
   496                         "Ignore inactive or disabled named group: " + ng.name);
   544                 }
   497                 }