8281236: (D)TLS key exchange named groups
Reviewed-by: mullan
This commit is contained in:
parent
10356e767a
commit
5d4c71c8bd
@ -34,8 +34,8 @@ import java.util.*;
|
||||
* the list of protocols to be allowed, the endpoint identification
|
||||
* algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
|
||||
* the maximum network packet size, the algorithm constraints, the signature
|
||||
* schemes and whether SSL/TLS/DTLS servers should request or require client
|
||||
* authentication, etc.
|
||||
* schemes, the key exchange named groups and whether SSL/TLS/DTLS servers
|
||||
* should request or require client authentication, etc.
|
||||
* <p>
|
||||
* {@code SSLParameter} objects can be created via the constructors in this
|
||||
* class, and can be described as pre-populated objects. {@code SSLParameter}
|
||||
@ -85,6 +85,7 @@ public class SSLParameters {
|
||||
private int maximumPacketSize = 0;
|
||||
private String[] applicationProtocols = new String[0];
|
||||
private String[] signatureSchemes = null;
|
||||
private String[] namedGroups = null;
|
||||
|
||||
/**
|
||||
* Constructs SSLParameters.
|
||||
@ -810,4 +811,130 @@ public class SSLParameters {
|
||||
|
||||
this.signatureSchemes = tempSchemes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a prioritized array of key exchange named groups names that
|
||||
* can be used over the SSL/TLS/DTLS protocols.
|
||||
* <p>
|
||||
* Note that the standard list of key exchange named groups are defined
|
||||
* in the <a href=
|
||||
* "{@docRoot}/../specs/security/standard-names.html#named-groups">
|
||||
* Named Groups</a> section of the Java Security Standard Algorithm
|
||||
* Names Specification. Providers may support named groups not defined
|
||||
* in this list or may not use the recommended name for a certain named
|
||||
* group.
|
||||
* <p>
|
||||
* The set of named groups that will be used over the SSL/TLS/DTLS
|
||||
* connections is determined by the returned array of this method and the
|
||||
* underlying provider-specific default named groups.
|
||||
* <p>
|
||||
* If the returned array is {@code null}, then the underlying
|
||||
* provider-specific default named groups will be used over the
|
||||
* SSL/TLS/DTLS connections.
|
||||
* <p>
|
||||
* If the returned array is empty (zero-length), then the named group
|
||||
* negotiation mechanism is turned off for SSL/TLS/DTLS protocols, and
|
||||
* the connections may not be able to be established if the negotiation
|
||||
* mechanism is required by a certain SSL/TLS/DTLS protocol. This
|
||||
* parameter will override the underlying provider-specific default
|
||||
* name groups.
|
||||
* <p>
|
||||
* If the returned array is not {@code null} or empty (zero-length),
|
||||
* then the named groups in the returned array will be used over
|
||||
* the SSL/TLS/DTLS connections. This parameter will override the
|
||||
* underlying provider-specific default named groups.
|
||||
* <p>
|
||||
* This method returns the most recent value passed to
|
||||
* {@link #setNamedGroups} if that method has been called and otherwise
|
||||
* returns the default named groups for connection populated objects,
|
||||
* or {@code null} for pre-populated objects.
|
||||
*
|
||||
* @apiNote
|
||||
* Note that a provider may not have been updated to support this method
|
||||
* and in that case may return {@code null} instead of the default
|
||||
* named groups for connection populated objects.
|
||||
*
|
||||
* @implNote
|
||||
* The SunJSSE provider supports this method.
|
||||
*
|
||||
* @implNote
|
||||
* Note that applications may use the
|
||||
* {@systemProperty jdk.tls.namedGroups} system property with the SunJSSE
|
||||
* provider to override the provider-specific default named groups.
|
||||
*
|
||||
* @return an array of key exchange named group names {@code Strings} or
|
||||
* {@code null} if none have been set. For non-null returns, this
|
||||
* method will return a new array each time it is invoked. The
|
||||
* array is ordered based on named group preference, with the first
|
||||
* entry being the most preferred. Providers should ignore unknown
|
||||
* named group names while establishing the SSL/TLS/DTLS
|
||||
* connections.
|
||||
* @see #setNamedGroups
|
||||
*
|
||||
* @since 20
|
||||
*/
|
||||
public String[] getNamedGroups() {
|
||||
return clone(namedGroups);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the prioritized array of key exchange named groups names that
|
||||
* can be used over the SSL/TLS/DTLS protocols.
|
||||
* <p>
|
||||
* Note that the standard list of key exchange named groups are defined in
|
||||
* the <a href=
|
||||
* "{@docRoot}/../specs/security/standard-names.html#named-groups">
|
||||
* Named Groups</a> section of the Java Security Standard Algorithm
|
||||
* Names Specification. Providers may support named groups not defined
|
||||
* in this list or may not use the recommended name for a certain named
|
||||
* group.
|
||||
* <p>
|
||||
* The set of named groups that will be used over the SSL/TLS/DTLS
|
||||
* connections is determined by the input parameter {@code namedGroups}
|
||||
* array and the underlying provider-specific default named groups.
|
||||
* See {@link #getNamedGroups} for specific details on how the
|
||||
* parameters are used in SSL/TLS/DTLS connections.
|
||||
*
|
||||
* @apiNote
|
||||
* Note that a provider may not have been updated to support this method
|
||||
* and in that case may ignore the named groups that are set.
|
||||
*
|
||||
* @implNote
|
||||
* The SunJSSE provider supports this method.
|
||||
*
|
||||
* @param namedGroups an ordered array of key exchange named group names
|
||||
* with the first entry being the most preferred, or {@code null}.
|
||||
* This method will make a copy of this array. Providers should
|
||||
* ignore unknown named group scheme names while establishing the
|
||||
* SSL/TLS/DTLS connections.
|
||||
* @throws IllegalArgumentException if any element in the
|
||||
* {@code namedGroups} array is a duplicate, {@code null} or
|
||||
* {@linkplain String#isBlank() blank}.
|
||||
*
|
||||
* @see #getNamedGroups
|
||||
*
|
||||
* @since 20
|
||||
*/
|
||||
public void setNamedGroups(String[] namedGroups) {
|
||||
String[] tempGroups = null;
|
||||
|
||||
if (namedGroups != null) {
|
||||
tempGroups = namedGroups.clone();
|
||||
Set<String> groupsSet = new HashSet<>();
|
||||
for (String namedGroup : tempGroups) {
|
||||
if (namedGroup == null || namedGroup.isBlank()) {
|
||||
throw new IllegalArgumentException(
|
||||
"An element of namedGroups is null or blank");
|
||||
}
|
||||
|
||||
if (groupsSet.contains(namedGroup)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Duplicate element of namedGroups: " + namedGroup);
|
||||
}
|
||||
groupsSet.add(namedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
this.namedGroups = tempGroups;
|
||||
}
|
||||
}
|
||||
|
@ -590,6 +590,7 @@ final class CertificateVerify {
|
||||
ClientHandshakeContext chc = (ClientHandshakeContext)context;
|
||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||
chc.sslConfig,
|
||||
chc.algorithmConstraints,
|
||||
chc.peerRequestedSignatureSchemes,
|
||||
x509Possession,
|
||||
@ -901,6 +902,7 @@ final class CertificateVerify {
|
||||
|
||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||
context.sslConfig,
|
||||
context.algorithmConstraints,
|
||||
context.peerRequestedSignatureSchemes,
|
||||
x509Possession,
|
||||
|
@ -42,7 +42,6 @@ import javax.crypto.spec.DHParameterSpec;
|
||||
import javax.crypto.spec.DHPublicKeySpec;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.ssl.X509Authentication.X509Possession;
|
||||
import sun.security.util.KeyUtil;
|
||||
|
||||
@ -313,12 +312,13 @@ final class DHKeyExchange {
|
||||
if (!useLegacyEphemeralDHKeys &&
|
||||
(context.clientRequestedNamedGroups != null) &&
|
||||
(!context.clientRequestedNamedGroups.isEmpty())) {
|
||||
preferableNamedGroup =
|
||||
SupportedGroups.getPreferredGroup(context.negotiatedProtocol,
|
||||
context.algorithmConstraints,
|
||||
new NamedGroupSpec [] {
|
||||
NamedGroupSpec.NAMED_GROUP_FFDHE },
|
||||
context.clientRequestedNamedGroups);
|
||||
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||
context.sslConfig,
|
||||
context.negotiatedProtocol,
|
||||
context.algorithmConstraints,
|
||||
new NamedGroupSpec [] {
|
||||
NamedGroupSpec.NAMED_GROUP_FFDHE },
|
||||
context.clientRequestedNamedGroups);
|
||||
if (preferableNamedGroup != null) {
|
||||
return new DHEPossession(preferableNamedGroup,
|
||||
context.sslContext.getSecureRandom());
|
||||
|
@ -127,6 +127,7 @@ final class DHServerKeyExchange {
|
||||
if (useExplicitSigAlgorithm) {
|
||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||
shc.sslConfig,
|
||||
shc.algorithmConstraints,
|
||||
shc.peerRequestedSignatureSchemes,
|
||||
x509Possession,
|
||||
|
@ -44,7 +44,6 @@ import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.ssl.X509Authentication.X509Credentials;
|
||||
import sun.security.ssl.X509Authentication.X509Possession;
|
||||
import sun.security.ssl.XDHKeyExchange.XDHECredentials;
|
||||
@ -236,7 +235,8 @@ final class ECDHKeyExchange {
|
||||
// Find most preferred EC or XEC groups
|
||||
if ((context.clientRequestedNamedGroups != null) &&
|
||||
(!context.clientRequestedNamedGroups.isEmpty())) {
|
||||
preferableNamedGroup = SupportedGroups.getPreferredGroup(
|
||||
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||
context.sslConfig,
|
||||
context.negotiatedProtocol,
|
||||
context.algorithmConstraints,
|
||||
new NamedGroupSpec[] {
|
||||
@ -244,7 +244,8 @@ final class ECDHKeyExchange {
|
||||
NamedGroupSpec.NAMED_GROUP_XDH },
|
||||
context.clientRequestedNamedGroups);
|
||||
} else {
|
||||
preferableNamedGroup = SupportedGroups.getPreferredGroup(
|
||||
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||
context.sslConfig,
|
||||
context.negotiatedProtocol,
|
||||
context.algorithmConstraints,
|
||||
new NamedGroupSpec[] {
|
||||
|
@ -42,7 +42,6 @@ import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.ssl.X509Authentication.X509Credentials;
|
||||
import sun.security.ssl.X509Authentication.X509Possession;
|
||||
import sun.security.util.HexDumpEncoder;
|
||||
@ -139,6 +138,7 @@ final class ECDHServerKeyExchange {
|
||||
if (useExplicitSigAlgorithm) {
|
||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||
shc.sslConfig,
|
||||
shc.algorithmConstraints,
|
||||
shc.peerRequestedSignatureSchemes,
|
||||
x509Possession,
|
||||
@ -204,7 +204,7 @@ final class ECDHServerKeyExchange {
|
||||
"Unknown named group ID: " + namedGroupId);
|
||||
}
|
||||
|
||||
if (!SupportedGroups.isSupported(namedGroup)) {
|
||||
if (!NamedGroup.isEnabled(chc.sslConfig, namedGroup)) {
|
||||
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
|
||||
"Unsupported named group: " + namedGroup);
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.security.auth.x500.X500Principal;
|
||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||
import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
|
||||
abstract class HandshakeContext implements ConnectionContext {
|
||||
// System properties
|
||||
@ -157,8 +156,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
|
||||
this.algorithmConstraints = SSLAlgorithmConstraints.wrap(
|
||||
sslConfig.userSpecifiedAlgorithmConstraints);
|
||||
this.activeProtocols = getActiveProtocols(sslConfig.enabledProtocols,
|
||||
sslConfig.enabledCipherSuites, algorithmConstraints);
|
||||
this.activeProtocols =
|
||||
getActiveProtocols(sslConfig, algorithmConstraints);
|
||||
if (activeProtocols.isEmpty()) {
|
||||
throw new SSLHandshakeException(
|
||||
"No appropriate protocol (protocol is disabled or " +
|
||||
@ -173,8 +172,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
}
|
||||
}
|
||||
this.maximumActiveProtocol = maximumVersion;
|
||||
this.activeCipherSuites = getActiveCipherSuites(this.activeProtocols,
|
||||
sslConfig.enabledCipherSuites, algorithmConstraints);
|
||||
this.activeCipherSuites = getActiveCipherSuites(sslConfig,
|
||||
this.activeProtocols, algorithmConstraints);
|
||||
if (activeCipherSuites.isEmpty()) {
|
||||
throw new SSLHandshakeException("No appropriate cipher suite");
|
||||
}
|
||||
@ -256,12 +255,11 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
}
|
||||
|
||||
private static List<ProtocolVersion> getActiveProtocols(
|
||||
List<ProtocolVersion> enabledProtocols,
|
||||
List<CipherSuite> enabledCipherSuites,
|
||||
SSLConfiguration sslConfig,
|
||||
AlgorithmConstraints algorithmConstraints) {
|
||||
boolean enabledSSL20Hello = false;
|
||||
ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
|
||||
for (ProtocolVersion protocol : enabledProtocols) {
|
||||
for (ProtocolVersion protocol : sslConfig.enabledProtocols) {
|
||||
if (!enabledSSL20Hello && protocol == ProtocolVersion.SSL20Hello) {
|
||||
enabledSSL20Hello = true;
|
||||
continue;
|
||||
@ -277,9 +275,9 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
boolean found = false;
|
||||
Map<NamedGroupSpec, Boolean> cachedStatus =
|
||||
new EnumMap<>(NamedGroupSpec.class);
|
||||
for (CipherSuite suite : enabledCipherSuites) {
|
||||
for (CipherSuite suite : sslConfig.enabledCipherSuites) {
|
||||
if (suite.isAvailable() && suite.supports(protocol)) {
|
||||
if (isActivatable(suite,
|
||||
if (isActivatable(sslConfig, suite,
|
||||
algorithmConstraints, cachedStatus)) {
|
||||
protocols.add(protocol);
|
||||
found = true;
|
||||
@ -309,15 +307,15 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
}
|
||||
|
||||
private static List<CipherSuite> getActiveCipherSuites(
|
||||
SSLConfiguration sslConfig,
|
||||
List<ProtocolVersion> enabledProtocols,
|
||||
List<CipherSuite> enabledCipherSuites,
|
||||
AlgorithmConstraints algorithmConstraints) {
|
||||
|
||||
List<CipherSuite> suites = new LinkedList<>();
|
||||
if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
|
||||
Map<NamedGroupSpec, Boolean> cachedStatus =
|
||||
new EnumMap<>(NamedGroupSpec.class);
|
||||
for (CipherSuite suite : enabledCipherSuites) {
|
||||
for (CipherSuite suite : sslConfig.enabledCipherSuites) {
|
||||
if (!suite.isAvailable()) {
|
||||
continue;
|
||||
}
|
||||
@ -327,7 +325,7 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
if (!suite.supports(protocol)) {
|
||||
continue;
|
||||
}
|
||||
if (isActivatable(suite,
|
||||
if (isActivatable(sslConfig, suite,
|
||||
algorithmConstraints, cachedStatus)) {
|
||||
suites.add(suite);
|
||||
isSupported = true;
|
||||
@ -525,7 +523,9 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
return activeProtocols.contains(protocolVersion);
|
||||
}
|
||||
|
||||
private static boolean isActivatable(CipherSuite suite,
|
||||
private static boolean isActivatable(
|
||||
SSLConfiguration sslConfig,
|
||||
CipherSuite suite,
|
||||
AlgorithmConstraints algorithmConstraints,
|
||||
Map<NamedGroupSpec, Boolean> cachedStatus) {
|
||||
|
||||
@ -543,8 +543,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
||||
if (groupType != NAMED_GROUP_NONE) {
|
||||
Boolean checkedStatus = cachedStatus.get(groupType);
|
||||
if (checkedStatus == null) {
|
||||
groupAvailable = SupportedGroups.isActivatable(
|
||||
algorithmConstraints, groupType);
|
||||
groupAvailable = NamedGroup.isActivatable(
|
||||
sslConfig, algorithmConstraints, groupType);
|
||||
cachedStatus.put(groupType, groupAvailable);
|
||||
|
||||
if (!groupAvailable &&
|
||||
|
@ -36,7 +36,6 @@ import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||
import sun.security.ssl.SSLExtension.ExtensionConsumer;
|
||||
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
|
||||
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.util.HexDumpEncoder;
|
||||
|
||||
/**
|
||||
@ -345,7 +344,7 @@ final class KeyShareExtension {
|
||||
List<SSLCredentials> credentials = new LinkedList<>();
|
||||
for (KeyShareEntry entry : spec.clientShares) {
|
||||
NamedGroup ng = NamedGroup.valueOf(entry.namedGroupId);
|
||||
if (ng == null || !SupportedGroups.isActivatable(
|
||||
if (ng == null || !NamedGroup.isActivatable(shc.sslConfig,
|
||||
shc.algorithmConstraints, ng)) {
|
||||
if (SSLLogger.isOn &&
|
||||
SSLLogger.isOn("ssl,handshake")) {
|
||||
@ -647,7 +646,7 @@ final class KeyShareExtension {
|
||||
SHKeyShareSpec spec = new SHKeyShareSpec(chc, buffer);
|
||||
KeyShareEntry keyShare = spec.serverShare;
|
||||
NamedGroup ng = NamedGroup.valueOf(keyShare.namedGroupId);
|
||||
if (ng == null || !SupportedGroups.isActivatable(
|
||||
if (ng == null || !NamedGroup.isActivatable(chc.sslConfig,
|
||||
chc.algorithmConstraints, ng)) {
|
||||
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||
"Unsupported named group: " +
|
||||
@ -800,7 +799,7 @@ final class KeyShareExtension {
|
||||
|
||||
NamedGroup selectedGroup = null;
|
||||
for (NamedGroup ng : shc.clientRequestedNamedGroups) {
|
||||
if (SupportedGroups.isActivatable(
|
||||
if (NamedGroup.isActivatable(shc.sslConfig,
|
||||
shc.algorithmConstraints, ng)) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
|
@ -33,12 +33,13 @@ import java.security.spec.NamedParameterSpec;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import javax.crypto.KeyAgreement;
|
||||
import javax.crypto.spec.DHParameterSpec;
|
||||
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
|
||||
import sun.security.util.CurveDB;
|
||||
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
||||
/**
|
||||
* An enum containing all known named groups for use in TLS.
|
||||
@ -241,9 +242,9 @@ enum NamedGroup {
|
||||
|
||||
// Constructor used for all NamedGroup types
|
||||
NamedGroup(int id, String name,
|
||||
NamedGroupSpec namedGroupSpec,
|
||||
ProtocolVersion[] supportedProtocols,
|
||||
AlgorithmParameterSpec keAlgParamSpec) {
|
||||
NamedGroupSpec namedGroupSpec,
|
||||
ProtocolVersion[] supportedProtocols,
|
||||
AlgorithmParameterSpec keAlgParamSpec) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.spec = namedGroupSpec;
|
||||
@ -369,6 +370,126 @@ enum NamedGroup {
|
||||
return "UNDEFINED-NAMED-GROUP(" + id + ")";
|
||||
}
|
||||
|
||||
public static List<NamedGroup> namesOf(String[] namedGroups) {
|
||||
if (namedGroups == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (namedGroups.length == 0) {
|
||||
return List.of();
|
||||
}
|
||||
|
||||
List<NamedGroup> ngs = new ArrayList<>(namedGroups.length);
|
||||
for (String ss : namedGroups) {
|
||||
NamedGroup ng = NamedGroup.nameOf(ss);
|
||||
if (ng == null || !ng.isAvailable) {
|
||||
if (SSLLogger.isOn &&
|
||||
SSLLogger.isOn("ssl,handshake,verbose")) {
|
||||
SSLLogger.finest(
|
||||
"Ignore the named group (" + ss
|
||||
+ "), unsupported or unavailable");
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
ngs.add(ng);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(ngs);
|
||||
}
|
||||
|
||||
// Is there any supported group permitted by the constraints?
|
||||
static boolean isActivatable(SSLConfiguration sslConfig,
|
||||
AlgorithmConstraints constraints, NamedGroupSpec type) {
|
||||
|
||||
boolean hasFFDHEGroups = false;
|
||||
for (String ng : sslConfig.namedGroups) {
|
||||
NamedGroup namedGroup = NamedGroup.nameOf(ng);
|
||||
if (namedGroup != null &&
|
||||
namedGroup.isAvailable && namedGroup.spec == type) {
|
||||
if (namedGroup.isPermitted(constraints)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hasFFDHEGroups &&
|
||||
(type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||
hasFFDHEGroups = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For compatibility, if no FFDHE groups are defined, the non-FFDHE
|
||||
// compatible mode (using DHE cipher suite without FFDHE extension)
|
||||
// is allowed.
|
||||
//
|
||||
// Note that the constraints checking on DHE parameters will be
|
||||
// performed during key exchanging in a handshake.
|
||||
return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
|
||||
}
|
||||
|
||||
// Is the named group permitted by the constraints?
|
||||
static boolean isActivatable(
|
||||
SSLConfiguration sslConfig,
|
||||
AlgorithmConstraints constraints, NamedGroup namedGroup) {
|
||||
if (!namedGroup.isAvailable || !isEnabled(sslConfig, namedGroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return namedGroup.isPermitted(constraints);
|
||||
}
|
||||
|
||||
// Is the named group supported?
|
||||
static boolean isEnabled(SSLConfiguration sslConfig,
|
||||
NamedGroup namedGroup) {
|
||||
for (String ng : sslConfig.namedGroups) {
|
||||
if (namedGroup.name.equalsIgnoreCase(ng)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get preferred named group from the configured named groups for the
|
||||
// negotiated protocol and named group types.
|
||||
static NamedGroup getPreferredGroup(
|
||||
SSLConfiguration sslConfig,
|
||||
ProtocolVersion negotiatedProtocol,
|
||||
AlgorithmConstraints constraints, NamedGroupSpec[] types) {
|
||||
for (String name : sslConfig.namedGroups) {
|
||||
NamedGroup ng = NamedGroup.nameOf(name);
|
||||
if (ng != null && ng.isAvailable &&
|
||||
(NamedGroupSpec.arrayContains(types, ng.spec)) &&
|
||||
ng.isAvailable(negotiatedProtocol) &&
|
||||
ng.isPermitted(constraints)) {
|
||||
return ng;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get preferred named group from the requested and configured named
|
||||
// groups for the negotiated protocol and named group types.
|
||||
static NamedGroup getPreferredGroup(
|
||||
SSLConfiguration sslConfig,
|
||||
ProtocolVersion negotiatedProtocol,
|
||||
AlgorithmConstraints constraints, NamedGroupSpec[] types,
|
||||
List<NamedGroup> requestedNamedGroups) {
|
||||
for (NamedGroup namedGroup : requestedNamedGroups) {
|
||||
if ((namedGroup.isAvailable &&
|
||||
NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
|
||||
namedGroup.isAvailable(negotiatedProtocol) &&
|
||||
isEnabled(sslConfig, namedGroup) &&
|
||||
namedGroup.isPermitted(constraints)) {
|
||||
return namedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// Is the NamedGroup available for the protocols desired?
|
||||
boolean isAvailable(List<ProtocolVersion> protocolVersions) {
|
||||
if (this.isAvailable) {
|
||||
@ -618,4 +739,86 @@ enum NamedGroup {
|
||||
return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
|
||||
}
|
||||
}
|
||||
|
||||
static final class SupportedGroups {
|
||||
// the supported named groups, non-null immutable list
|
||||
static final String[] namedGroups;
|
||||
|
||||
static {
|
||||
// The value of the System Property defines a list of enabled named
|
||||
// groups in preference order, separated with comma. For example:
|
||||
//
|
||||
// jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048"
|
||||
//
|
||||
// If the System Property is not defined or the value is empty, the
|
||||
// default groups and preferences will be used.
|
||||
String property = GetPropertyAction
|
||||
.privilegedGetProperty("jdk.tls.namedGroups");
|
||||
if (property != null && !property.isEmpty()) {
|
||||
// remove double quote marks from beginning/end of the property
|
||||
if (property.length() > 1 && property.charAt(0) == '"' &&
|
||||
property.charAt(property.length() - 1) == '"') {
|
||||
property = property.substring(1, property.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> groupList;
|
||||
if (property != null && !property.isEmpty()) {
|
||||
String[] groups = property.split(",");
|
||||
groupList = new ArrayList<>(groups.length);
|
||||
for (String group : groups) {
|
||||
group = group.trim();
|
||||
if (!group.isEmpty()) {
|
||||
NamedGroup namedGroup = nameOf(group);
|
||||
if (namedGroup != null) {
|
||||
if (namedGroup.isAvailable) {
|
||||
groupList.add(namedGroup.name);
|
||||
}
|
||||
} // ignore unknown groups
|
||||
}
|
||||
}
|
||||
|
||||
if (groupList.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"System property jdk.tls.namedGroups(" +
|
||||
property + ") contains no supported named groups");
|
||||
}
|
||||
} else { // default groups
|
||||
NamedGroup[] groups = new NamedGroup[] {
|
||||
|
||||
// Primary XDH (RFC 7748) curves
|
||||
X25519,
|
||||
|
||||
// Primary NIST Suite B curves
|
||||
SECP256_R1,
|
||||
SECP384_R1,
|
||||
SECP521_R1,
|
||||
|
||||
// Secondary XDH curves
|
||||
X448,
|
||||
|
||||
// FFDHE (RFC 7919)
|
||||
FFDHE_2048,
|
||||
FFDHE_3072,
|
||||
FFDHE_4096,
|
||||
FFDHE_6144,
|
||||
FFDHE_8192,
|
||||
};
|
||||
|
||||
groupList = new ArrayList<>(groups.length);
|
||||
for (NamedGroup group : groups) {
|
||||
if (group.isAvailable) {
|
||||
groupList.add(group.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (groupList.isEmpty() &&
|
||||
SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.warning("No default named groups");
|
||||
}
|
||||
}
|
||||
|
||||
namedGroups = groupList.toArray(new String[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -64,6 +64,9 @@ final class SSLConfiguration implements Cloneable {
|
||||
// "signature_algorithms_cert" extensions
|
||||
String[] signatureSchemes;
|
||||
|
||||
// the configured named groups for the "supported_groups" extensions
|
||||
String[] namedGroups;
|
||||
|
||||
// the maximum protocol version of enabled protocols
|
||||
ProtocolVersion maximumProtocolVersion;
|
||||
|
||||
@ -109,6 +112,10 @@ final class SSLConfiguration implements Cloneable {
|
||||
static final int maxCertificateChainLength = GetIntegerAction.privilegedGetProperty(
|
||||
"jdk.tls.maxCertificateChainLength", 10);
|
||||
|
||||
// To switch off the supported_groups extension for DHE cipher suite.
|
||||
static final boolean enableFFDHE =
|
||||
Utilities.getBooleanProperty("jsse.enableFFDHE", true);
|
||||
|
||||
// Is the extended_master_secret extension supported?
|
||||
static {
|
||||
boolean supportExtendedMasterSecret = Utilities.getBooleanProperty(
|
||||
@ -146,6 +153,7 @@ final class SSLConfiguration implements Cloneable {
|
||||
this.signatureSchemes = isClientMode ?
|
||||
CustomizedClientSignatureSchemes.signatureSchemes :
|
||||
CustomizedServerSignatureSchemes.signatureSchemes;
|
||||
this.namedGroups = NamedGroup.SupportedGroups.namedGroups;
|
||||
this.maximumProtocolVersion = ProtocolVersion.NONE;
|
||||
for (ProtocolVersion pv : enabledProtocols) {
|
||||
if (pv.compareTo(maximumProtocolVersion) > 0) {
|
||||
@ -201,6 +209,7 @@ final class SSLConfiguration implements Cloneable {
|
||||
params.setEnableRetransmissions(this.enableRetransmissions);
|
||||
params.setMaximumPacketSize(this.maximumPacketSize);
|
||||
params.setSignatureSchemes(this.signatureSchemes);
|
||||
params.setNamedGroups(this.namedGroups);
|
||||
|
||||
return params;
|
||||
}
|
||||
@ -265,6 +274,15 @@ final class SSLConfiguration implements Cloneable {
|
||||
this.signatureSchemes = ss;
|
||||
} // Otherwise, use the default values
|
||||
|
||||
String[] ngs = params.getNamedGroups();
|
||||
if (ngs != null) {
|
||||
// Note if 'ngs' is empty, then no named groups should be
|
||||
// specified over the connections.
|
||||
this.namedGroups = ngs;
|
||||
} else { // Otherwise, use the default values.
|
||||
this.namedGroups = NamedGroup.SupportedGroups.namedGroups;
|
||||
}
|
||||
|
||||
this.preferLocalCipherSuites = params.getUseCipherSuitesOrder();
|
||||
this.enableRetransmissions = params.getEnableRetransmissions();
|
||||
this.maximumPacketSize = params.getMaximumPacketSize();
|
||||
|
@ -28,8 +28,6 @@ package sun.security.ssl;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.ssl.X509Authentication.X509Possession;
|
||||
|
||||
final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||
@ -561,23 +559,13 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||
|
||||
private static final class T13KeyAgreement implements SSLKeyAgreement {
|
||||
private final NamedGroup namedGroup;
|
||||
static final Map<NamedGroup, T13KeyAgreement>
|
||||
supportedKeyShares = new HashMap<>();
|
||||
|
||||
static {
|
||||
for (NamedGroup namedGroup :
|
||||
SupportedGroups.supportedNamedGroups) {
|
||||
supportedKeyShares.put(
|
||||
namedGroup, new T13KeyAgreement(namedGroup));
|
||||
}
|
||||
}
|
||||
|
||||
private T13KeyAgreement(NamedGroup namedGroup) {
|
||||
this.namedGroup = namedGroup;
|
||||
}
|
||||
|
||||
static T13KeyAgreement valueOf(NamedGroup namedGroup) {
|
||||
return supportedKeyShares.get(namedGroup);
|
||||
return new T13KeyAgreement(namedGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +41,6 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
import sun.security.ssl.X509Authentication.X509Possession;
|
||||
import sun.security.util.KeyUtil;
|
||||
import sun.security.util.SignatureUtil;
|
||||
@ -466,6 +465,7 @@ enum SignatureScheme {
|
||||
}
|
||||
|
||||
static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm(
|
||||
SSLConfiguration sslConfig,
|
||||
AlgorithmConstraints constraints,
|
||||
List<SignatureScheme> schemes,
|
||||
X509Possession x509Possession,
|
||||
@ -519,7 +519,7 @@ enum SignatureScheme {
|
||||
if (params != null) {
|
||||
NamedGroup keyGroup = NamedGroup.valueOf(params);
|
||||
if (keyGroup != null &&
|
||||
SupportedGroups.isSupported(keyGroup)) {
|
||||
NamedGroup.isEnabled(sslConfig, keyGroup)) {
|
||||
Signature signer = ss.getSigner(signingKey);
|
||||
if (signer != null) {
|
||||
return new SimpleImmutableEntry<>(ss, signer);
|
||||
|
@ -27,11 +27,10 @@ package sun.security.ssl;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AlgorithmConstraints;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
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;
|
||||
@ -64,10 +63,6 @@ final class SupportedGroupsExtension {
|
||||
static final class SupportedGroupsSpec implements SSLExtensionSpec {
|
||||
final int[] namedGroupsIds;
|
||||
|
||||
private SupportedGroupsSpec(int[] namedGroupsIds) {
|
||||
this.namedGroupsIds = namedGroupsIds;
|
||||
}
|
||||
|
||||
private SupportedGroupsSpec(List<NamedGroup> namedGroups) {
|
||||
this.namedGroupsIds = new int[namedGroups.size()];
|
||||
int i = 0;
|
||||
@ -150,174 +145,6 @@ final class SupportedGroupsExtension {
|
||||
}
|
||||
}
|
||||
|
||||
static class SupportedGroups {
|
||||
// To switch off the supported_groups extension for DHE cipher suite.
|
||||
static final boolean enableFFDHE =
|
||||
Utilities.getBooleanProperty("jsse.enableFFDHE", true);
|
||||
|
||||
// the supported named groups
|
||||
static final NamedGroup[] supportedNamedGroups;
|
||||
|
||||
static {
|
||||
// The value of the System Property defines a list of enabled named
|
||||
// groups in preference order, separated with comma. For example:
|
||||
//
|
||||
// jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048"
|
||||
//
|
||||
// If the System Property is not defined or the value is empty, the
|
||||
// default groups and preferences will be used.
|
||||
String property = GetPropertyAction
|
||||
.privilegedGetProperty("jdk.tls.namedGroups");
|
||||
if (property != null && !property.isEmpty()) {
|
||||
// remove double quote marks from beginning/end of the property
|
||||
if (property.length() > 1 && property.charAt(0) == '"' &&
|
||||
property.charAt(property.length() - 1) == '"') {
|
||||
property = property.substring(1, property.length() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<NamedGroup> groupList;
|
||||
if (property != null && !property.isEmpty()) {
|
||||
String[] groups = property.split(",");
|
||||
groupList = new ArrayList<>(groups.length);
|
||||
for (String group : groups) {
|
||||
group = group.trim();
|
||||
if (!group.isEmpty()) {
|
||||
NamedGroup namedGroup = NamedGroup.nameOf(group);
|
||||
if (namedGroup != null) {
|
||||
if (namedGroup.isAvailable) {
|
||||
groupList.add(namedGroup);
|
||||
}
|
||||
} // ignore unknown groups
|
||||
}
|
||||
}
|
||||
|
||||
if (groupList.isEmpty()) {
|
||||
throw new IllegalArgumentException(
|
||||
"System property jdk.tls.namedGroups(" +
|
||||
property + ") contains no supported named groups");
|
||||
}
|
||||
} else { // default groups
|
||||
NamedGroup[] groups = new NamedGroup[] {
|
||||
|
||||
// Primary XDH (RFC 7748) curves
|
||||
NamedGroup.X25519,
|
||||
|
||||
// Primary NIST Suite B curves
|
||||
NamedGroup.SECP256_R1,
|
||||
NamedGroup.SECP384_R1,
|
||||
NamedGroup.SECP521_R1,
|
||||
|
||||
// Secondary XDH curves
|
||||
NamedGroup.X448,
|
||||
|
||||
// FFDHE (RFC 7919)
|
||||
NamedGroup.FFDHE_2048,
|
||||
NamedGroup.FFDHE_3072,
|
||||
NamedGroup.FFDHE_4096,
|
||||
NamedGroup.FFDHE_6144,
|
||||
NamedGroup.FFDHE_8192,
|
||||
};
|
||||
|
||||
groupList = new ArrayList<>(groups.length);
|
||||
for (NamedGroup group : groups) {
|
||||
if (group.isAvailable) {
|
||||
groupList.add(group);
|
||||
}
|
||||
}
|
||||
|
||||
if (groupList.isEmpty() &&
|
||||
SSLLogger.isOn && SSLLogger.isOn("ssl")) {
|
||||
SSLLogger.warning("No default named groups");
|
||||
}
|
||||
}
|
||||
|
||||
supportedNamedGroups = new NamedGroup[groupList.size()];
|
||||
int i = 0;
|
||||
for (NamedGroup namedGroup : groupList) {
|
||||
supportedNamedGroups[i++] = namedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
// Is there any supported group permitted by the constraints?
|
||||
static boolean isActivatable(
|
||||
AlgorithmConstraints constraints, NamedGroupSpec type) {
|
||||
|
||||
boolean hasFFDHEGroups = false;
|
||||
for (NamedGroup namedGroup : supportedNamedGroups) {
|
||||
if (namedGroup.isAvailable && namedGroup.spec == type) {
|
||||
if (namedGroup.isPermitted(constraints)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hasFFDHEGroups &&
|
||||
(type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||
hasFFDHEGroups = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For compatibility, if no FFDHE groups are defined, the non-FFDHE
|
||||
// compatible mode (using DHE cipher suite without FFDHE extension)
|
||||
// is allowed.
|
||||
//
|
||||
// Note that the constraints checking on DHE parameters will be
|
||||
// performed during key exchanging in a handshake.
|
||||
return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
|
||||
}
|
||||
|
||||
// Is the named group permitted by the constraints?
|
||||
static boolean isActivatable(
|
||||
AlgorithmConstraints constraints, NamedGroup namedGroup) {
|
||||
if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return namedGroup.isPermitted(constraints);
|
||||
}
|
||||
|
||||
// Is the named group supported?
|
||||
static boolean isSupported(NamedGroup namedGroup) {
|
||||
for (NamedGroup group : supportedNamedGroups) {
|
||||
if (namedGroup.id == group.id) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static NamedGroup getPreferredGroup(
|
||||
ProtocolVersion negotiatedProtocol,
|
||||
AlgorithmConstraints constraints, NamedGroupSpec[] types,
|
||||
List<NamedGroup> requestedNamedGroups) {
|
||||
for (NamedGroup namedGroup : requestedNamedGroups) {
|
||||
if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
|
||||
namedGroup.isAvailable(negotiatedProtocol) &&
|
||||
isSupported(namedGroup) &&
|
||||
namedGroup.isPermitted(constraints)) {
|
||||
return namedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static NamedGroup getPreferredGroup(
|
||||
ProtocolVersion negotiatedProtocol,
|
||||
AlgorithmConstraints constraints, NamedGroupSpec[] types) {
|
||||
for (NamedGroup namedGroup : supportedNamedGroups) {
|
||||
if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
|
||||
namedGroup.isAvailable(negotiatedProtocol) &&
|
||||
namedGroup.isPermitted(constraints)) {
|
||||
return namedGroup;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Network data producer of a "supported_groups" extension in
|
||||
* the ClientHello handshake message.
|
||||
@ -346,9 +173,18 @@ final class SupportedGroupsExtension {
|
||||
|
||||
// Produce the extension.
|
||||
ArrayList<NamedGroup> namedGroups =
|
||||
new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
|
||||
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
|
||||
if ((!SupportedGroups.enableFFDHE) &&
|
||||
new ArrayList<>(chc.sslConfig.namedGroups.length);
|
||||
for (String name : chc.sslConfig.namedGroups) {
|
||||
NamedGroup ng = NamedGroup.nameOf(name);
|
||||
if (ng == null) {
|
||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
"Ignore unspecified named group: " + name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!SSLConfiguration.enableFFDHE) &&
|
||||
(ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||
continue;
|
||||
}
|
||||
@ -495,9 +331,19 @@ final class SupportedGroupsExtension {
|
||||
// Contains all groups the server supports, regardless of whether
|
||||
// they are currently supported by the client.
|
||||
ArrayList<NamedGroup> namedGroups = new ArrayList<>(
|
||||
SupportedGroups.supportedNamedGroups.length);
|
||||
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
|
||||
if ((!SupportedGroups.enableFFDHE) &&
|
||||
shc.sslConfig.namedGroups.length);
|
||||
for (String name : shc.sslConfig.namedGroups) {
|
||||
NamedGroup ng = NamedGroup.nameOf(name);
|
||||
if (ng == null) {
|
||||
if (SSLLogger.isOn &&
|
||||
SSLLogger.isOn("ssl,handshake")) {
|
||||
SSLLogger.fine(
|
||||
"Ignore unspecified named group: " + name);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((!SSLConfiguration.enableFFDHE) &&
|
||||
(ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||
continue;
|
||||
}
|
||||
|
@ -39,8 +39,6 @@ import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import javax.net.ssl.X509ExtendedKeyManager;
|
||||
|
||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
||||
|
||||
enum X509Authentication implements SSLAuthentication {
|
||||
// Require rsaEncryption public key
|
||||
RSA ("RSA", "RSA"),
|
||||
@ -344,7 +342,7 @@ enum X509Authentication implements SSLAuthentication {
|
||||
((ECPublicKey) serverPublicKey).getParams();
|
||||
NamedGroup namedGroup = NamedGroup.valueOf(params);
|
||||
if ((namedGroup == null) ||
|
||||
(!SupportedGroups.isSupported(namedGroup)) ||
|
||||
(!NamedGroup.isEnabled(shc.sslConfig, namedGroup)) ||
|
||||
((shc.clientRequestedNamedGroups != null) &&
|
||||
!shc.clientRequestedNamedGroups.contains(namedGroup))) {
|
||||
|
||||
|
143
test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java
Normal file
143
test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (C) 2022 THL A29 Limited, a Tencent company. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// SunJSSE does not support dynamic system properties, no way to re-use
|
||||
// system properties in samevm/agentvm mode.
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8281236
|
||||
* @summary Check DTLS connection behaviors for named groups configuration
|
||||
* @modules java.base/sun.security.util
|
||||
* @library /test/lib
|
||||
* @build DTLSOverDatagram
|
||||
* @run main/othervm DTLSNamedGroups
|
||||
*/
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import java.security.Security;
|
||||
|
||||
/**
|
||||
* Test DTLS client authentication.
|
||||
*/
|
||||
public class DTLSNamedGroups extends DTLSOverDatagram {
|
||||
// Make sure default DH(E) key exchange is not used for DTLS v1.2.
|
||||
private static String[] cipherSuites = new String[] {
|
||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"
|
||||
};
|
||||
|
||||
private final String[] serverNamedGroups;
|
||||
private final String[] clientNamedGroups;
|
||||
|
||||
public DTLSNamedGroups(String[] serverNamedGroups,
|
||||
String[] clientNamedGroups) {
|
||||
this.serverNamedGroups = serverNamedGroups;
|
||||
this.clientNamedGroups = clientNamedGroups;
|
||||
}
|
||||
|
||||
@Override
|
||||
SSLEngine createSSLEngine(boolean isClient) throws Exception {
|
||||
SSLEngine engine = super.createSSLEngine(isClient);
|
||||
|
||||
SSLParameters sslParameters = engine.getSSLParameters();
|
||||
if (isClient) {
|
||||
sslParameters.setNamedGroups(clientNamedGroups);
|
||||
sslParameters.setCipherSuites(cipherSuites);
|
||||
} else {
|
||||
sslParameters.setNamedGroups(serverNamedGroups);
|
||||
}
|
||||
engine.setSSLParameters(sslParameters);
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "");
|
||||
|
||||
runTest(new String[] {
|
||||
"x25519",
|
||||
"secp256r1"
|
||||
},
|
||||
new String[] {
|
||||
"x25519",
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(null,
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
null,
|
||||
false);
|
||||
runTest(new String[0],
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
true);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
new String[0],
|
||||
true);
|
||||
runTest(new String[] {
|
||||
"secp256NA"
|
||||
},
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
private static void runTest(String[] serverNamedGroups,
|
||||
String[] clientNamedGroups,
|
||||
boolean exceptionExpected) throws Exception {
|
||||
DTLSNamedGroups testCase = new DTLSNamedGroups(
|
||||
serverNamedGroups, clientNamedGroups);
|
||||
try {
|
||||
testCase.runTest(testCase);
|
||||
} catch (Exception e) {
|
||||
if (!exceptionExpected) {
|
||||
throw e;
|
||||
} else { // Otherwise, swallow the expected exception and return.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionExpected) {
|
||||
throw new RuntimeException("Unexpected success!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
147
test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java
Normal file
147
test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (C) 2022 THL A29 Limited, a Tencent company. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// SunJSSE does not support dynamic system properties, no way to re-use
|
||||
// system properties in samevm/agentvm mode.
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8281236
|
||||
* @summary Check TLS connection behaviors for named groups configuration
|
||||
* @library /javax/net/ssl/templates
|
||||
* @run main/othervm NamedGroups
|
||||
*/
|
||||
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import javax.net.ssl.SSLServerSocket;
|
||||
import javax.net.ssl.SSLSocket;
|
||||
import java.security.Security;
|
||||
|
||||
public class NamedGroups extends SSLSocketTemplate {
|
||||
private final String[] serverNamedGroups;
|
||||
private final String[] clientNamedGroups;
|
||||
private final boolean exceptionExpected;
|
||||
|
||||
public NamedGroups(String[] serverNamedGroups,
|
||||
String[] clientNamedGroups,
|
||||
boolean exceptionExpected) {
|
||||
this.serverNamedGroups = serverNamedGroups;
|
||||
this.clientNamedGroups = clientNamedGroups;
|
||||
this.exceptionExpected = exceptionExpected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureServerSocket(SSLServerSocket sslServerSocket) {
|
||||
SSLParameters sslParameters = sslServerSocket.getSSLParameters();
|
||||
sslParameters.setNamedGroups(serverNamedGroups);
|
||||
sslServerSocket.setSSLParameters(sslParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configureClientSocket(SSLSocket socket) {
|
||||
SSLParameters sslParameters = socket.getSSLParameters();
|
||||
sslParameters.setNamedGroups(clientNamedGroups);
|
||||
socket.setSSLParameters(sslParameters);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runServerApplication(SSLSocket socket) {
|
||||
try {
|
||||
super.runServerApplication(socket);
|
||||
} catch (Exception ex) {
|
||||
// Just ignore, let the client handle the failure information.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void runClientApplication(SSLSocket sslSocket) throws Exception {
|
||||
try {
|
||||
super.runClientApplication(sslSocket);
|
||||
} catch (Exception ex) {
|
||||
if (!exceptionExpected) {
|
||||
throw ex;
|
||||
} else { // Otherwise, swallow the exception and return.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionExpected) {
|
||||
throw new RuntimeException("Unexpected success!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Security.setProperty("jdk.tls.disabledAlgorithms", "");
|
||||
|
||||
runTest(new String[] {
|
||||
"x25519",
|
||||
"secp256r1"
|
||||
},
|
||||
new String[] {
|
||||
"x25519",
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(null,
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
null,
|
||||
false);
|
||||
runTest(new String[0],
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
true);
|
||||
runTest(new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
new String[0],
|
||||
true);
|
||||
runTest(new String[] {
|
||||
"secp256NA"
|
||||
},
|
||||
new String[] {
|
||||
"secp256r1"
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
private static void runTest(String[] serverNamedGroups,
|
||||
String[] clientNamedGroups,
|
||||
boolean exceptionExpected) throws Exception {
|
||||
new NamedGroups(serverNamedGroups,
|
||||
clientNamedGroups, exceptionExpected).run();
|
||||
}
|
||||
}
|
97
test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java
Normal file
97
test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2022 THL A29 Limited, a Tencent company. 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.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8281236
|
||||
* @summary check SSLParameters.setNamedGroups() implementation
|
||||
*/
|
||||
|
||||
import javax.net.ssl.SSLParameters;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NamedGroupsSpec {
|
||||
public static void main(String[] args) throws Exception {
|
||||
runTest(null, // null array should be allowed.
|
||||
false);
|
||||
runTest(new String[] { // empty array should be allowed
|
||||
// blank line
|
||||
},
|
||||
false);
|
||||
runTest(new String[] { // multiple elements should be fine
|
||||
"x25519",
|
||||
"secp256r1"
|
||||
},
|
||||
false);
|
||||
runTest(new String[] { // no duplicate element should be allowed
|
||||
"x25519",
|
||||
"x25519"
|
||||
},
|
||||
true);
|
||||
runTest(new String[] { // no null element should be allowed
|
||||
null
|
||||
},
|
||||
true);
|
||||
runTest(new String[] { // no blank element should be allowed
|
||||
""
|
||||
},
|
||||
true);
|
||||
runTest(new String[] { // no blank element should be allowed
|
||||
"x25519",
|
||||
""
|
||||
},
|
||||
true);
|
||||
runTest(new String[] { // no null element should be allowed.
|
||||
"x25519",
|
||||
null
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
private static void runTest(String[] namedGroups,
|
||||
boolean exceptionExpected) throws Exception {
|
||||
SSLParameters sslParams = new SSLParameters();
|
||||
try {
|
||||
sslParams.setNamedGroups(namedGroups);
|
||||
} catch (Exception ex) {
|
||||
if (!exceptionExpected ||
|
||||
!(ex instanceof IllegalArgumentException)) {
|
||||
throw ex;
|
||||
} else { // Otherwise, swallow the exception and return.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (exceptionExpected) {
|
||||
throw new RuntimeException("Unexpected success!");
|
||||
}
|
||||
|
||||
// Check if the getNamedGroups() method returns the same elements.
|
||||
String[] configuredNamedGroups = sslParams.getNamedGroups();
|
||||
if (!Arrays.equals(namedGroups, configuredNamedGroups)) {
|
||||
throw new RuntimeException(
|
||||
"SSLParameters.getNamedGroups() method does not return "
|
||||
+ "the same elements as set with setNamedGroups()");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user