Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8281236: (D)TLS key exchange named groups #9776

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
124 changes: 122 additions & 2 deletions src/java.base/share/classes/javax/net/ssl/SSLParameters.java
Expand Up @@ -34,8 +34,8 @@
* 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}
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -810,4 +811,123 @@ public void setSignatureSchemes(String[] signatureSchemes) {

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 {@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();
for (String namedGroup : tempGroups) {
if (namedGroup == null || namedGroup.isBlank()) {
throw new IllegalArgumentException(
"An element of namedGroups is null or blank");
}
}
}

this.namedGroups = tempGroups;
}
}
Expand Up @@ -591,6 +591,7 @@ static final class T12CertificateVerifyMessage extends HandshakeMessage {
ClientHandshakeContext chc = (ClientHandshakeContext)context;
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
SignatureScheme.getSignerOfPreferableAlgorithm(
chc.sslConfig,
chc.algorithmConstraints,
chc.peerRequestedSignatureSchemes,
x509Possession,
Expand Down Expand Up @@ -901,6 +902,7 @@ static final class T13CertificateVerifyMessage extends HandshakeMessage {

Map.Entry<SignatureScheme, Signature> schemeAndSigner =
SignatureScheme.getSignerOfPreferableAlgorithm(
context.sslConfig,
context.algorithmConstraints,
context.peerRequestedSignatureSchemes,
x509Possession,
Expand Down
14 changes: 7 additions & 7 deletions src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java
Expand Up @@ -42,7 +42,6 @@
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;

Expand Down Expand Up @@ -314,12 +313,13 @@ public SSLPossession createPossession(HandshakeContext context) {
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());
Expand Down
Expand Up @@ -127,6 +127,7 @@ class DHServerKeyExchangeMessage extends HandshakeMessage {
if (useExplicitSigAlgorithm) {
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
SignatureScheme.getSignerOfPreferableAlgorithm(
shc.sslConfig,
shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes,
x509Possession,
Expand Down
Expand Up @@ -44,7 +44,6 @@
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;
Expand Down Expand Up @@ -236,15 +235,17 @@ public SSLPossession createPossession(HandshakeContext context) {
// 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[] {
NamedGroupSpec.NAMED_GROUP_ECDHE,
NamedGroupSpec.NAMED_GROUP_XDH },
context.clientRequestedNamedGroups);
} else {
preferableNamedGroup = SupportedGroups.getPreferredGroup(
preferableNamedGroup = NamedGroup.getPreferredGroup(
context.sslConfig,
context.negotiatedProtocol,
context.algorithmConstraints,
new NamedGroupSpec[] {
Expand Down
Expand Up @@ -42,7 +42,6 @@
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;
Expand Down Expand Up @@ -139,6 +138,7 @@ class ECDHServerKeyExchangeMessage extends HandshakeMessage {
if (useExplicitSigAlgorithm) {
Map.Entry<SignatureScheme, Signature> schemeAndSigner =
SignatureScheme.getSignerOfPreferableAlgorithm(
shc.sslConfig,
shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes,
x509Possession,
Expand Down Expand Up @@ -204,7 +204,7 @@ class ECDHServerKeyExchangeMessage extends HandshakeMessage {
"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);
}
Expand Down
32 changes: 16 additions & 16 deletions src/java.base/share/classes/sun/security/ssl/HandshakeContext.java
Expand Up @@ -48,7 +48,6 @@
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
Expand Down Expand Up @@ -166,8 +165,8 @@ protected HandshakeContext(SSLContextImpl sslContext,

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 " +
Expand All @@ -182,8 +181,8 @@ protected HandshakeContext(SSLContextImpl sslContext,
}
}
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");
}
Expand Down Expand Up @@ -265,12 +264,11 @@ private void initialize() {
}

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;
Expand All @@ -286,9 +284,9 @@ private static List<ProtocolVersion> getActiveProtocols(
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;
Expand Down Expand Up @@ -318,15 +316,15 @@ private static List<ProtocolVersion> getActiveProtocols(
}

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;
}
Expand All @@ -336,7 +334,7 @@ private static List<CipherSuite> getActiveCipherSuites(
if (!suite.supports(protocol)) {
continue;
}
if (isActivatable(suite,
if (isActivatable(sslConfig, suite,
algorithmConstraints, cachedStatus)) {
suites.add(suite);
isSupported = true;
Expand Down Expand Up @@ -534,7 +532,9 @@ boolean isNegotiable(ProtocolVersion protocolVersion) {
return activeProtocols.contains(protocolVersion);
}

private static boolean isActivatable(CipherSuite suite,
private static boolean isActivatable(
SSLConfiguration sslConfig,
CipherSuite suite,
AlgorithmConstraints algorithmConstraints,
Map<NamedGroupSpec, Boolean> cachedStatus) {

Expand All @@ -552,8 +552,8 @@ private static boolean isActivatable(CipherSuite suite,
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 &&
Expand Down
Expand Up @@ -41,7 +41,6 @@
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;

/**
Expand Down Expand Up @@ -348,7 +347,7 @@ public void consume(ConnectionContext context,
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")) {
Expand Down Expand Up @@ -650,7 +649,7 @@ public void consume(ConnectionContext context,
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: " +
Expand Down Expand Up @@ -803,7 +802,7 @@ public byte[] produce(ConnectionContext context,

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(
Expand Down