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
|
* the list of protocols to be allowed, the endpoint identification
|
||||||
* algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
|
* algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI),
|
||||||
* the maximum network packet size, the algorithm constraints, the signature
|
* the maximum network packet size, the algorithm constraints, the signature
|
||||||
* schemes and whether SSL/TLS/DTLS servers should request or require client
|
* schemes, the key exchange named groups and whether SSL/TLS/DTLS servers
|
||||||
* authentication, etc.
|
* should request or require client authentication, etc.
|
||||||
* <p>
|
* <p>
|
||||||
* {@code SSLParameter} objects can be created via the constructors in this
|
* {@code SSLParameter} objects can be created via the constructors in this
|
||||||
* class, and can be described as pre-populated objects. {@code SSLParameter}
|
* class, and can be described as pre-populated objects. {@code SSLParameter}
|
||||||
@ -85,6 +85,7 @@ public class SSLParameters {
|
|||||||
private int maximumPacketSize = 0;
|
private int maximumPacketSize = 0;
|
||||||
private String[] applicationProtocols = new String[0];
|
private String[] applicationProtocols = new String[0];
|
||||||
private String[] signatureSchemes = null;
|
private String[] signatureSchemes = null;
|
||||||
|
private String[] namedGroups = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs SSLParameters.
|
* Constructs SSLParameters.
|
||||||
@ -810,4 +811,130 @@ public class SSLParameters {
|
|||||||
|
|
||||||
this.signatureSchemes = tempSchemes;
|
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;
|
ClientHandshakeContext chc = (ClientHandshakeContext)context;
|
||||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||||
|
chc.sslConfig,
|
||||||
chc.algorithmConstraints,
|
chc.algorithmConstraints,
|
||||||
chc.peerRequestedSignatureSchemes,
|
chc.peerRequestedSignatureSchemes,
|
||||||
x509Possession,
|
x509Possession,
|
||||||
@ -901,6 +902,7 @@ final class CertificateVerify {
|
|||||||
|
|
||||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||||
|
context.sslConfig,
|
||||||
context.algorithmConstraints,
|
context.algorithmConstraints,
|
||||||
context.peerRequestedSignatureSchemes,
|
context.peerRequestedSignatureSchemes,
|
||||||
x509Possession,
|
x509Possession,
|
||||||
|
@ -42,7 +42,6 @@ import javax.crypto.spec.DHParameterSpec;
|
|||||||
import javax.crypto.spec.DHPublicKeySpec;
|
import javax.crypto.spec.DHPublicKeySpec;
|
||||||
import sun.security.action.GetPropertyAction;
|
import sun.security.action.GetPropertyAction;
|
||||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.ssl.X509Authentication.X509Possession;
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
import sun.security.util.KeyUtil;
|
import sun.security.util.KeyUtil;
|
||||||
|
|
||||||
@ -313,12 +312,13 @@ final class DHKeyExchange {
|
|||||||
if (!useLegacyEphemeralDHKeys &&
|
if (!useLegacyEphemeralDHKeys &&
|
||||||
(context.clientRequestedNamedGroups != null) &&
|
(context.clientRequestedNamedGroups != null) &&
|
||||||
(!context.clientRequestedNamedGroups.isEmpty())) {
|
(!context.clientRequestedNamedGroups.isEmpty())) {
|
||||||
preferableNamedGroup =
|
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||||
SupportedGroups.getPreferredGroup(context.negotiatedProtocol,
|
context.sslConfig,
|
||||||
context.algorithmConstraints,
|
context.negotiatedProtocol,
|
||||||
new NamedGroupSpec [] {
|
context.algorithmConstraints,
|
||||||
NamedGroupSpec.NAMED_GROUP_FFDHE },
|
new NamedGroupSpec [] {
|
||||||
context.clientRequestedNamedGroups);
|
NamedGroupSpec.NAMED_GROUP_FFDHE },
|
||||||
|
context.clientRequestedNamedGroups);
|
||||||
if (preferableNamedGroup != null) {
|
if (preferableNamedGroup != null) {
|
||||||
return new DHEPossession(preferableNamedGroup,
|
return new DHEPossession(preferableNamedGroup,
|
||||||
context.sslContext.getSecureRandom());
|
context.sslContext.getSecureRandom());
|
||||||
|
@ -127,6 +127,7 @@ final class DHServerKeyExchange {
|
|||||||
if (useExplicitSigAlgorithm) {
|
if (useExplicitSigAlgorithm) {
|
||||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||||
|
shc.sslConfig,
|
||||||
shc.algorithmConstraints,
|
shc.algorithmConstraints,
|
||||||
shc.peerRequestedSignatureSchemes,
|
shc.peerRequestedSignatureSchemes,
|
||||||
x509Possession,
|
x509Possession,
|
||||||
|
@ -44,7 +44,6 @@ import javax.crypto.KeyAgreement;
|
|||||||
import javax.crypto.SecretKey;
|
import javax.crypto.SecretKey;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.ssl.X509Authentication.X509Credentials;
|
import sun.security.ssl.X509Authentication.X509Credentials;
|
||||||
import sun.security.ssl.X509Authentication.X509Possession;
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
import sun.security.ssl.XDHKeyExchange.XDHECredentials;
|
import sun.security.ssl.XDHKeyExchange.XDHECredentials;
|
||||||
@ -236,7 +235,8 @@ final class ECDHKeyExchange {
|
|||||||
// Find most preferred EC or XEC groups
|
// Find most preferred EC or XEC groups
|
||||||
if ((context.clientRequestedNamedGroups != null) &&
|
if ((context.clientRequestedNamedGroups != null) &&
|
||||||
(!context.clientRequestedNamedGroups.isEmpty())) {
|
(!context.clientRequestedNamedGroups.isEmpty())) {
|
||||||
preferableNamedGroup = SupportedGroups.getPreferredGroup(
|
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||||
|
context.sslConfig,
|
||||||
context.negotiatedProtocol,
|
context.negotiatedProtocol,
|
||||||
context.algorithmConstraints,
|
context.algorithmConstraints,
|
||||||
new NamedGroupSpec[] {
|
new NamedGroupSpec[] {
|
||||||
@ -244,7 +244,8 @@ final class ECDHKeyExchange {
|
|||||||
NamedGroupSpec.NAMED_GROUP_XDH },
|
NamedGroupSpec.NAMED_GROUP_XDH },
|
||||||
context.clientRequestedNamedGroups);
|
context.clientRequestedNamedGroups);
|
||||||
} else {
|
} else {
|
||||||
preferableNamedGroup = SupportedGroups.getPreferredGroup(
|
preferableNamedGroup = NamedGroup.getPreferredGroup(
|
||||||
|
context.sslConfig,
|
||||||
context.negotiatedProtocol,
|
context.negotiatedProtocol,
|
||||||
context.algorithmConstraints,
|
context.algorithmConstraints,
|
||||||
new NamedGroupSpec[] {
|
new NamedGroupSpec[] {
|
||||||
|
@ -42,7 +42,6 @@ import java.util.EnumSet;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.ssl.X509Authentication.X509Credentials;
|
import sun.security.ssl.X509Authentication.X509Credentials;
|
||||||
import sun.security.ssl.X509Authentication.X509Possession;
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
import sun.security.util.HexDumpEncoder;
|
import sun.security.util.HexDumpEncoder;
|
||||||
@ -139,6 +138,7 @@ final class ECDHServerKeyExchange {
|
|||||||
if (useExplicitSigAlgorithm) {
|
if (useExplicitSigAlgorithm) {
|
||||||
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
|
||||||
SignatureScheme.getSignerOfPreferableAlgorithm(
|
SignatureScheme.getSignerOfPreferableAlgorithm(
|
||||||
|
shc.sslConfig,
|
||||||
shc.algorithmConstraints,
|
shc.algorithmConstraints,
|
||||||
shc.peerRequestedSignatureSchemes,
|
shc.peerRequestedSignatureSchemes,
|
||||||
x509Possession,
|
x509Possession,
|
||||||
@ -204,7 +204,7 @@ final class ECDHServerKeyExchange {
|
|||||||
"Unknown named group ID: " + namedGroupId);
|
"Unknown named group ID: " + namedGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!SupportedGroups.isSupported(namedGroup)) {
|
if (!NamedGroup.isEnabled(chc.sslConfig, namedGroup)) {
|
||||||
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
|
throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
|
||||||
"Unsupported named group: " + namedGroup);
|
"Unsupported named group: " + namedGroup);
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import javax.net.ssl.SSLHandshakeException;
|
|||||||
import javax.security.auth.x500.X500Principal;
|
import javax.security.auth.x500.X500Principal;
|
||||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||||
import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
|
import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
|
|
||||||
abstract class HandshakeContext implements ConnectionContext {
|
abstract class HandshakeContext implements ConnectionContext {
|
||||||
// System properties
|
// System properties
|
||||||
@ -157,8 +156,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
|
|
||||||
this.algorithmConstraints = SSLAlgorithmConstraints.wrap(
|
this.algorithmConstraints = SSLAlgorithmConstraints.wrap(
|
||||||
sslConfig.userSpecifiedAlgorithmConstraints);
|
sslConfig.userSpecifiedAlgorithmConstraints);
|
||||||
this.activeProtocols = getActiveProtocols(sslConfig.enabledProtocols,
|
this.activeProtocols =
|
||||||
sslConfig.enabledCipherSuites, algorithmConstraints);
|
getActiveProtocols(sslConfig, algorithmConstraints);
|
||||||
if (activeProtocols.isEmpty()) {
|
if (activeProtocols.isEmpty()) {
|
||||||
throw new SSLHandshakeException(
|
throw new SSLHandshakeException(
|
||||||
"No appropriate protocol (protocol is disabled or " +
|
"No appropriate protocol (protocol is disabled or " +
|
||||||
@ -173,8 +172,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.maximumActiveProtocol = maximumVersion;
|
this.maximumActiveProtocol = maximumVersion;
|
||||||
this.activeCipherSuites = getActiveCipherSuites(this.activeProtocols,
|
this.activeCipherSuites = getActiveCipherSuites(sslConfig,
|
||||||
sslConfig.enabledCipherSuites, algorithmConstraints);
|
this.activeProtocols, algorithmConstraints);
|
||||||
if (activeCipherSuites.isEmpty()) {
|
if (activeCipherSuites.isEmpty()) {
|
||||||
throw new SSLHandshakeException("No appropriate cipher suite");
|
throw new SSLHandshakeException("No appropriate cipher suite");
|
||||||
}
|
}
|
||||||
@ -256,12 +255,11 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static List<ProtocolVersion> getActiveProtocols(
|
private static List<ProtocolVersion> getActiveProtocols(
|
||||||
List<ProtocolVersion> enabledProtocols,
|
SSLConfiguration sslConfig,
|
||||||
List<CipherSuite> enabledCipherSuites,
|
|
||||||
AlgorithmConstraints algorithmConstraints) {
|
AlgorithmConstraints algorithmConstraints) {
|
||||||
boolean enabledSSL20Hello = false;
|
boolean enabledSSL20Hello = false;
|
||||||
ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
|
ArrayList<ProtocolVersion> protocols = new ArrayList<>(4);
|
||||||
for (ProtocolVersion protocol : enabledProtocols) {
|
for (ProtocolVersion protocol : sslConfig.enabledProtocols) {
|
||||||
if (!enabledSSL20Hello && protocol == ProtocolVersion.SSL20Hello) {
|
if (!enabledSSL20Hello && protocol == ProtocolVersion.SSL20Hello) {
|
||||||
enabledSSL20Hello = true;
|
enabledSSL20Hello = true;
|
||||||
continue;
|
continue;
|
||||||
@ -277,9 +275,9 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
boolean found = false;
|
boolean found = false;
|
||||||
Map<NamedGroupSpec, Boolean> cachedStatus =
|
Map<NamedGroupSpec, Boolean> cachedStatus =
|
||||||
new EnumMap<>(NamedGroupSpec.class);
|
new EnumMap<>(NamedGroupSpec.class);
|
||||||
for (CipherSuite suite : enabledCipherSuites) {
|
for (CipherSuite suite : sslConfig.enabledCipherSuites) {
|
||||||
if (suite.isAvailable() && suite.supports(protocol)) {
|
if (suite.isAvailable() && suite.supports(protocol)) {
|
||||||
if (isActivatable(suite,
|
if (isActivatable(sslConfig, suite,
|
||||||
algorithmConstraints, cachedStatus)) {
|
algorithmConstraints, cachedStatus)) {
|
||||||
protocols.add(protocol);
|
protocols.add(protocol);
|
||||||
found = true;
|
found = true;
|
||||||
@ -309,15 +307,15 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static List<CipherSuite> getActiveCipherSuites(
|
private static List<CipherSuite> getActiveCipherSuites(
|
||||||
|
SSLConfiguration sslConfig,
|
||||||
List<ProtocolVersion> enabledProtocols,
|
List<ProtocolVersion> enabledProtocols,
|
||||||
List<CipherSuite> enabledCipherSuites,
|
|
||||||
AlgorithmConstraints algorithmConstraints) {
|
AlgorithmConstraints algorithmConstraints) {
|
||||||
|
|
||||||
List<CipherSuite> suites = new LinkedList<>();
|
List<CipherSuite> suites = new LinkedList<>();
|
||||||
if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
|
if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
|
||||||
Map<NamedGroupSpec, Boolean> cachedStatus =
|
Map<NamedGroupSpec, Boolean> cachedStatus =
|
||||||
new EnumMap<>(NamedGroupSpec.class);
|
new EnumMap<>(NamedGroupSpec.class);
|
||||||
for (CipherSuite suite : enabledCipherSuites) {
|
for (CipherSuite suite : sslConfig.enabledCipherSuites) {
|
||||||
if (!suite.isAvailable()) {
|
if (!suite.isAvailable()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -327,7 +325,7 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
if (!suite.supports(protocol)) {
|
if (!suite.supports(protocol)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (isActivatable(suite,
|
if (isActivatable(sslConfig, suite,
|
||||||
algorithmConstraints, cachedStatus)) {
|
algorithmConstraints, cachedStatus)) {
|
||||||
suites.add(suite);
|
suites.add(suite);
|
||||||
isSupported = true;
|
isSupported = true;
|
||||||
@ -525,7 +523,9 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
return activeProtocols.contains(protocolVersion);
|
return activeProtocols.contains(protocolVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isActivatable(CipherSuite suite,
|
private static boolean isActivatable(
|
||||||
|
SSLConfiguration sslConfig,
|
||||||
|
CipherSuite suite,
|
||||||
AlgorithmConstraints algorithmConstraints,
|
AlgorithmConstraints algorithmConstraints,
|
||||||
Map<NamedGroupSpec, Boolean> cachedStatus) {
|
Map<NamedGroupSpec, Boolean> cachedStatus) {
|
||||||
|
|
||||||
@ -543,8 +543,8 @@ abstract class HandshakeContext implements ConnectionContext {
|
|||||||
if (groupType != NAMED_GROUP_NONE) {
|
if (groupType != NAMED_GROUP_NONE) {
|
||||||
Boolean checkedStatus = cachedStatus.get(groupType);
|
Boolean checkedStatus = cachedStatus.get(groupType);
|
||||||
if (checkedStatus == null) {
|
if (checkedStatus == null) {
|
||||||
groupAvailable = SupportedGroups.isActivatable(
|
groupAvailable = NamedGroup.isActivatable(
|
||||||
algorithmConstraints, groupType);
|
sslConfig, algorithmConstraints, groupType);
|
||||||
cachedStatus.put(groupType, groupAvailable);
|
cachedStatus.put(groupType, groupAvailable);
|
||||||
|
|
||||||
if (!groupAvailable &&
|
if (!groupAvailable &&
|
||||||
|
@ -36,7 +36,6 @@ import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
|||||||
import sun.security.ssl.SSLExtension.ExtensionConsumer;
|
import sun.security.ssl.SSLExtension.ExtensionConsumer;
|
||||||
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
|
import sun.security.ssl.SSLExtension.SSLExtensionSpec;
|
||||||
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
import sun.security.ssl.SSLHandshake.HandshakeMessage;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.util.HexDumpEncoder;
|
import sun.security.util.HexDumpEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,7 +344,7 @@ final class KeyShareExtension {
|
|||||||
List<SSLCredentials> credentials = new LinkedList<>();
|
List<SSLCredentials> credentials = new LinkedList<>();
|
||||||
for (KeyShareEntry entry : spec.clientShares) {
|
for (KeyShareEntry entry : spec.clientShares) {
|
||||||
NamedGroup ng = NamedGroup.valueOf(entry.namedGroupId);
|
NamedGroup ng = NamedGroup.valueOf(entry.namedGroupId);
|
||||||
if (ng == null || !SupportedGroups.isActivatable(
|
if (ng == null || !NamedGroup.isActivatable(shc.sslConfig,
|
||||||
shc.algorithmConstraints, ng)) {
|
shc.algorithmConstraints, ng)) {
|
||||||
if (SSLLogger.isOn &&
|
if (SSLLogger.isOn &&
|
||||||
SSLLogger.isOn("ssl,handshake")) {
|
SSLLogger.isOn("ssl,handshake")) {
|
||||||
@ -647,7 +646,7 @@ final class KeyShareExtension {
|
|||||||
SHKeyShareSpec spec = new SHKeyShareSpec(chc, buffer);
|
SHKeyShareSpec spec = new SHKeyShareSpec(chc, buffer);
|
||||||
KeyShareEntry keyShare = spec.serverShare;
|
KeyShareEntry keyShare = spec.serverShare;
|
||||||
NamedGroup ng = NamedGroup.valueOf(keyShare.namedGroupId);
|
NamedGroup ng = NamedGroup.valueOf(keyShare.namedGroupId);
|
||||||
if (ng == null || !SupportedGroups.isActivatable(
|
if (ng == null || !NamedGroup.isActivatable(chc.sslConfig,
|
||||||
chc.algorithmConstraints, ng)) {
|
chc.algorithmConstraints, ng)) {
|
||||||
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE,
|
||||||
"Unsupported named group: " +
|
"Unsupported named group: " +
|
||||||
@ -800,7 +799,7 @@ final class KeyShareExtension {
|
|||||||
|
|
||||||
NamedGroup selectedGroup = null;
|
NamedGroup selectedGroup = null;
|
||||||
for (NamedGroup ng : shc.clientRequestedNamedGroups) {
|
for (NamedGroup ng : shc.clientRequestedNamedGroups) {
|
||||||
if (SupportedGroups.isActivatable(
|
if (NamedGroup.isActivatable(shc.sslConfig,
|
||||||
shc.algorithmConstraints, ng)) {
|
shc.algorithmConstraints, ng)) {
|
||||||
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
|
||||||
SSLLogger.fine(
|
SSLLogger.fine(
|
||||||
|
@ -33,12 +33,13 @@ import java.security.spec.NamedParameterSpec;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.crypto.KeyAgreement;
|
import javax.crypto.KeyAgreement;
|
||||||
import javax.crypto.spec.DHParameterSpec;
|
import javax.crypto.spec.DHParameterSpec;
|
||||||
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
|
import sun.security.ssl.ECDHKeyExchange.ECDHEPossession;
|
||||||
import sun.security.util.CurveDB;
|
import sun.security.util.CurveDB;
|
||||||
|
import sun.security.action.GetPropertyAction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum containing all known named groups for use in TLS.
|
* An enum containing all known named groups for use in TLS.
|
||||||
@ -241,9 +242,9 @@ enum NamedGroup {
|
|||||||
|
|
||||||
// Constructor used for all NamedGroup types
|
// Constructor used for all NamedGroup types
|
||||||
NamedGroup(int id, String name,
|
NamedGroup(int id, String name,
|
||||||
NamedGroupSpec namedGroupSpec,
|
NamedGroupSpec namedGroupSpec,
|
||||||
ProtocolVersion[] supportedProtocols,
|
ProtocolVersion[] supportedProtocols,
|
||||||
AlgorithmParameterSpec keAlgParamSpec) {
|
AlgorithmParameterSpec keAlgParamSpec) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.spec = namedGroupSpec;
|
this.spec = namedGroupSpec;
|
||||||
@ -369,6 +370,126 @@ enum NamedGroup {
|
|||||||
return "UNDEFINED-NAMED-GROUP(" + id + ")";
|
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?
|
// Is the NamedGroup available for the protocols desired?
|
||||||
boolean isAvailable(List<ProtocolVersion> protocolVersions) {
|
boolean isAvailable(List<ProtocolVersion> protocolVersions) {
|
||||||
if (this.isAvailable) {
|
if (this.isAvailable) {
|
||||||
@ -618,4 +739,86 @@ enum NamedGroup {
|
|||||||
return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc);
|
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
|
// "signature_algorithms_cert" extensions
|
||||||
String[] signatureSchemes;
|
String[] signatureSchemes;
|
||||||
|
|
||||||
|
// the configured named groups for the "supported_groups" extensions
|
||||||
|
String[] namedGroups;
|
||||||
|
|
||||||
// the maximum protocol version of enabled protocols
|
// the maximum protocol version of enabled protocols
|
||||||
ProtocolVersion maximumProtocolVersion;
|
ProtocolVersion maximumProtocolVersion;
|
||||||
|
|
||||||
@ -109,6 +112,10 @@ final class SSLConfiguration implements Cloneable {
|
|||||||
static final int maxCertificateChainLength = GetIntegerAction.privilegedGetProperty(
|
static final int maxCertificateChainLength = GetIntegerAction.privilegedGetProperty(
|
||||||
"jdk.tls.maxCertificateChainLength", 10);
|
"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?
|
// Is the extended_master_secret extension supported?
|
||||||
static {
|
static {
|
||||||
boolean supportExtendedMasterSecret = Utilities.getBooleanProperty(
|
boolean supportExtendedMasterSecret = Utilities.getBooleanProperty(
|
||||||
@ -146,6 +153,7 @@ final class SSLConfiguration implements Cloneable {
|
|||||||
this.signatureSchemes = isClientMode ?
|
this.signatureSchemes = isClientMode ?
|
||||||
CustomizedClientSignatureSchemes.signatureSchemes :
|
CustomizedClientSignatureSchemes.signatureSchemes :
|
||||||
CustomizedServerSignatureSchemes.signatureSchemes;
|
CustomizedServerSignatureSchemes.signatureSchemes;
|
||||||
|
this.namedGroups = NamedGroup.SupportedGroups.namedGroups;
|
||||||
this.maximumProtocolVersion = ProtocolVersion.NONE;
|
this.maximumProtocolVersion = ProtocolVersion.NONE;
|
||||||
for (ProtocolVersion pv : enabledProtocols) {
|
for (ProtocolVersion pv : enabledProtocols) {
|
||||||
if (pv.compareTo(maximumProtocolVersion) > 0) {
|
if (pv.compareTo(maximumProtocolVersion) > 0) {
|
||||||
@ -201,6 +209,7 @@ final class SSLConfiguration implements Cloneable {
|
|||||||
params.setEnableRetransmissions(this.enableRetransmissions);
|
params.setEnableRetransmissions(this.enableRetransmissions);
|
||||||
params.setMaximumPacketSize(this.maximumPacketSize);
|
params.setMaximumPacketSize(this.maximumPacketSize);
|
||||||
params.setSignatureSchemes(this.signatureSchemes);
|
params.setSignatureSchemes(this.signatureSchemes);
|
||||||
|
params.setNamedGroups(this.namedGroups);
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
@ -265,6 +274,15 @@ final class SSLConfiguration implements Cloneable {
|
|||||||
this.signatureSchemes = ss;
|
this.signatureSchemes = ss;
|
||||||
} // Otherwise, use the default values
|
} // 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.preferLocalCipherSuites = params.getUseCipherSuitesOrder();
|
||||||
this.enableRetransmissions = params.getEnableRetransmissions();
|
this.enableRetransmissions = params.getEnableRetransmissions();
|
||||||
this.maximumPacketSize = params.getMaximumPacketSize();
|
this.maximumPacketSize = params.getMaximumPacketSize();
|
||||||
|
@ -28,8 +28,6 @@ package sun.security.ssl;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.AbstractMap.SimpleImmutableEntry;
|
import java.util.AbstractMap.SimpleImmutableEntry;
|
||||||
|
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.ssl.X509Authentication.X509Possession;
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
|
|
||||||
final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
||||||
@ -561,23 +559,13 @@ final class SSLKeyExchange implements SSLKeyAgreementGenerator,
|
|||||||
|
|
||||||
private static final class T13KeyAgreement implements SSLKeyAgreement {
|
private static final class T13KeyAgreement implements SSLKeyAgreement {
|
||||||
private final NamedGroup namedGroup;
|
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) {
|
private T13KeyAgreement(NamedGroup namedGroup) {
|
||||||
this.namedGroup = namedGroup;
|
this.namedGroup = namedGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static T13KeyAgreement valueOf(NamedGroup namedGroup) {
|
static T13KeyAgreement valueOf(NamedGroup namedGroup) {
|
||||||
return supportedKeyShares.get(namedGroup);
|
return new T13KeyAgreement(namedGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -41,7 +41,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
import sun.security.ssl.X509Authentication.X509Possession;
|
import sun.security.ssl.X509Authentication.X509Possession;
|
||||||
import sun.security.util.KeyUtil;
|
import sun.security.util.KeyUtil;
|
||||||
import sun.security.util.SignatureUtil;
|
import sun.security.util.SignatureUtil;
|
||||||
@ -466,6 +465,7 @@ enum SignatureScheme {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm(
|
static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm(
|
||||||
|
SSLConfiguration sslConfig,
|
||||||
AlgorithmConstraints constraints,
|
AlgorithmConstraints constraints,
|
||||||
List<SignatureScheme> schemes,
|
List<SignatureScheme> schemes,
|
||||||
X509Possession x509Possession,
|
X509Possession x509Possession,
|
||||||
@ -519,7 +519,7 @@ enum SignatureScheme {
|
|||||||
if (params != null) {
|
if (params != null) {
|
||||||
NamedGroup keyGroup = NamedGroup.valueOf(params);
|
NamedGroup keyGroup = NamedGroup.valueOf(params);
|
||||||
if (keyGroup != null &&
|
if (keyGroup != null &&
|
||||||
SupportedGroups.isSupported(keyGroup)) {
|
NamedGroup.isEnabled(sslConfig, keyGroup)) {
|
||||||
Signature signer = ss.getSigner(signingKey);
|
Signature signer = ss.getSigner(signingKey);
|
||||||
if (signer != null) {
|
if (signer != null) {
|
||||||
return new SimpleImmutableEntry<>(ss, signer);
|
return new SimpleImmutableEntry<>(ss, signer);
|
||||||
|
@ -27,11 +27,10 @@ package sun.security.ssl;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.security.AlgorithmConstraints;
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import javax.net.ssl.SSLProtocolException;
|
import javax.net.ssl.SSLProtocolException;
|
||||||
import sun.security.action.GetPropertyAction;
|
|
||||||
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
import sun.security.ssl.NamedGroup.NamedGroupSpec;
|
||||||
import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
|
import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS;
|
||||||
import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
|
import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS;
|
||||||
@ -64,10 +63,6 @@ final class SupportedGroupsExtension {
|
|||||||
static final class SupportedGroupsSpec implements SSLExtensionSpec {
|
static final class SupportedGroupsSpec implements SSLExtensionSpec {
|
||||||
final int[] namedGroupsIds;
|
final int[] namedGroupsIds;
|
||||||
|
|
||||||
private SupportedGroupsSpec(int[] namedGroupsIds) {
|
|
||||||
this.namedGroupsIds = namedGroupsIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
private SupportedGroupsSpec(List<NamedGroup> namedGroups) {
|
private SupportedGroupsSpec(List<NamedGroup> namedGroups) {
|
||||||
this.namedGroupsIds = new int[namedGroups.size()];
|
this.namedGroupsIds = new int[namedGroups.size()];
|
||||||
int i = 0;
|
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
|
* Network data producer of a "supported_groups" extension in
|
||||||
* the ClientHello handshake message.
|
* the ClientHello handshake message.
|
||||||
@ -346,9 +173,18 @@ final class SupportedGroupsExtension {
|
|||||||
|
|
||||||
// Produce the extension.
|
// Produce the extension.
|
||||||
ArrayList<NamedGroup> namedGroups =
|
ArrayList<NamedGroup> namedGroups =
|
||||||
new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
|
new ArrayList<>(chc.sslConfig.namedGroups.length);
|
||||||
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
|
for (String name : chc.sslConfig.namedGroups) {
|
||||||
if ((!SupportedGroups.enableFFDHE) &&
|
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)) {
|
(ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -495,9 +331,19 @@ final class SupportedGroupsExtension {
|
|||||||
// Contains all groups the server supports, regardless of whether
|
// Contains all groups the server supports, regardless of whether
|
||||||
// they are currently supported by the client.
|
// they are currently supported by the client.
|
||||||
ArrayList<NamedGroup> namedGroups = new ArrayList<>(
|
ArrayList<NamedGroup> namedGroups = new ArrayList<>(
|
||||||
SupportedGroups.supportedNamedGroups.length);
|
shc.sslConfig.namedGroups.length);
|
||||||
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
|
for (String name : shc.sslConfig.namedGroups) {
|
||||||
if ((!SupportedGroups.enableFFDHE) &&
|
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)) {
|
(ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -39,8 +39,6 @@ import java.util.Arrays;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.net.ssl.X509ExtendedKeyManager;
|
import javax.net.ssl.X509ExtendedKeyManager;
|
||||||
|
|
||||||
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
|
|
||||||
|
|
||||||
enum X509Authentication implements SSLAuthentication {
|
enum X509Authentication implements SSLAuthentication {
|
||||||
// Require rsaEncryption public key
|
// Require rsaEncryption public key
|
||||||
RSA ("RSA", "RSA"),
|
RSA ("RSA", "RSA"),
|
||||||
@ -344,7 +342,7 @@ enum X509Authentication implements SSLAuthentication {
|
|||||||
((ECPublicKey) serverPublicKey).getParams();
|
((ECPublicKey) serverPublicKey).getParams();
|
||||||
NamedGroup namedGroup = NamedGroup.valueOf(params);
|
NamedGroup namedGroup = NamedGroup.valueOf(params);
|
||||||
if ((namedGroup == null) ||
|
if ((namedGroup == null) ||
|
||||||
(!SupportedGroups.isSupported(namedGroup)) ||
|
(!NamedGroup.isEnabled(shc.sslConfig, namedGroup)) ||
|
||||||
((shc.clientRequestedNamedGroups != null) &&
|
((shc.clientRequestedNamedGroups != null) &&
|
||||||
!shc.clientRequestedNamedGroups.contains(namedGroup))) {
|
!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