8226374: Restrict TLS signature schemes and named groups

Reviewed-by: mullan
This commit is contained in:
Xue-Lei Andrew Fan 2019-08-12 21:36:29 -07:00
parent de8ce983b3
commit 316140ff92
18 changed files with 810 additions and 626 deletions

View file

@ -1034,6 +1034,7 @@ final class CertificateMessage {
// Don't select a signature scheme unless we will be able to // Don't select a signature scheme unless we will be able to
// produce a CertificateVerify message later // produce a CertificateVerify message later
if (SignatureScheme.getPreferableAlgorithm( if (SignatureScheme.getPreferableAlgorithm(
hc.algorithmConstraints,
hc.peerRequestedSignatureSchemes, hc.peerRequestedSignatureSchemes,
ss, hc.negotiatedProtocol) == null) { ss, hc.negotiatedProtocol) == null) {

View file

@ -736,6 +736,7 @@ final class CertificateRequest {
// Don't select a signature scheme unless we will be able to // Don't select a signature scheme unless we will be able to
// produce a CertificateVerify message later // produce a CertificateVerify message later
if (SignatureScheme.getPreferableAlgorithm( if (SignatureScheme.getPreferableAlgorithm(
hc.algorithmConstraints,
hc.peerRequestedSignatureSchemes, hc.peerRequestedSignatureSchemes,
ss, hc.negotiatedProtocol) == null) { ss, hc.negotiatedProtocol) == null) {

View file

@ -564,6 +564,7 @@ final class CertificateVerify {
// This happens in client side only. // This happens in client side only.
ClientHandshakeContext chc = (ClientHandshakeContext)context; ClientHandshakeContext chc = (ClientHandshakeContext)context;
this.signatureScheme = SignatureScheme.getPreferableAlgorithm( this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
chc.algorithmConstraints,
chc.peerRequestedSignatureSchemes, chc.peerRequestedSignatureSchemes,
x509Possession, x509Possession,
chc.negotiatedProtocol); chc.negotiatedProtocol);
@ -865,6 +866,7 @@ final class CertificateVerify {
super(context); super(context);
this.signatureScheme = SignatureScheme.getPreferableAlgorithm( this.signatureScheme = SignatureScheme.getPreferableAlgorithm(
context.algorithmConstraints,
context.peerRequestedSignatureSchemes, context.peerRequestedSignatureSchemes,
x509Possession, x509Possession,
context.negotiatedProtocol); context.negotiatedProtocol);

View file

@ -35,8 +35,8 @@ import static sun.security.ssl.CipherSuite.HashAlg.*;
import static sun.security.ssl.CipherSuite.KeyExchange.*; import static sun.security.ssl.CipherSuite.KeyExchange.*;
import static sun.security.ssl.CipherSuite.MacAlg.*; import static sun.security.ssl.CipherSuite.MacAlg.*;
import static sun.security.ssl.SSLCipher.*; import static sun.security.ssl.SSLCipher.*;
import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import static sun.security.ssl.NamedGroup.NamedGroupType.*; import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
/** /**
* Enum for SSL/(D)TLS cipher suites. * Enum for SSL/(D)TLS cipher suites.
@ -1125,12 +1125,12 @@ enum CipherSuite {
// name of the key exchange algorithm, e.g. DHE_DSS // name of the key exchange algorithm, e.g. DHE_DSS
final String name; final String name;
final boolean allowed; final boolean allowed;
final NamedGroupType[] groupTypes; final NamedGroupSpec[] groupTypes;
private final boolean alwaysAvailable; private final boolean alwaysAvailable;
private final boolean isAnonymous; private final boolean isAnonymous;
KeyExchange(String name, boolean allowed, KeyExchange(String name, boolean allowed,
boolean isAnonymous, NamedGroupType... groupTypes) { boolean isAnonymous, NamedGroupSpec... groupTypes) {
this.name = name; this.name = name;
this.groupTypes = groupTypes; this.groupTypes = groupTypes;
this.allowed = allowed; this.allowed = allowed;
@ -1144,8 +1144,8 @@ enum CipherSuite {
return true; return true;
} }
if (NamedGroupType.arrayContains( if (NamedGroupSpec.arrayContains(groupTypes,
groupTypes, NamedGroupType.NAMED_GROUP_ECDHE)) { NamedGroupSpec.NAMED_GROUP_ECDHE)) {
return (allowed && JsseJce.isEcAvailable()); return (allowed && JsseJce.isEcAvailable());
} else { } else {
return allowed; return allowed;

View file

@ -41,7 +41,7 @@ import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec; 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.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; 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;
@ -76,7 +76,7 @@ final class DHKeyExchange {
static DHECredentials valueOf(NamedGroup ng, static DHECredentials valueOf(NamedGroup ng,
byte[] encodedPublic) throws IOException, GeneralSecurityException { byte[] encodedPublic) throws IOException, GeneralSecurityException {
if (ng.type != NamedGroupType.NAMED_GROUP_FFDHE) { if (ng.spec != NamedGroupSpec.NAMED_GROUP_FFDHE) {
throw new RuntimeException( throw new RuntimeException(
"Credentials decoding: Not FFDHE named group"); "Credentials decoding: Not FFDHE named group");
} }
@ -85,11 +85,7 @@ final class DHKeyExchange {
return null; return null;
} }
DHParameterSpec params = (DHParameterSpec)ng.getParameterSpec(); DHParameterSpec params = (DHParameterSpec)ng.keAlgParamSpec;
if (params == null) {
return null;
}
KeyFactory kf = KeyFactory.getInstance("DiffieHellman"); KeyFactory kf = KeyFactory.getInstance("DiffieHellman");
DHPublicKeySpec spec = new DHPublicKeySpec( DHPublicKeySpec spec = new DHPublicKeySpec(
new BigInteger(1, encodedPublic), new BigInteger(1, encodedPublic),
@ -110,9 +106,7 @@ final class DHKeyExchange {
try { try {
KeyPairGenerator kpg = KeyPairGenerator kpg =
KeyPairGenerator.getInstance("DiffieHellman"); KeyPairGenerator.getInstance("DiffieHellman");
DHParameterSpec params = kpg.initialize(namedGroup.keAlgParamSpec, random);
(DHParameterSpec)namedGroup.getParameterSpec();
kpg.initialize(params, random);
KeyPair kp = generateDHKeyPair(kpg); KeyPair kp = generateDHKeyPair(kpg);
if (kp == null) { if (kp == null) {
throw new RuntimeException("Could not generate DH keypair"); throw new RuntimeException("Could not generate DH keypair");
@ -321,11 +315,10 @@ final class DHKeyExchange {
(context.clientRequestedNamedGroups != null) && (context.clientRequestedNamedGroups != null) &&
(!context.clientRequestedNamedGroups.isEmpty())) { (!context.clientRequestedNamedGroups.isEmpty())) {
preferableNamedGroup = preferableNamedGroup =
SupportedGroups.getPreferredGroup( SupportedGroups.getPreferredGroup(context.negotiatedProtocol,
context.negotiatedProtocol,
context.algorithmConstraints, context.algorithmConstraints,
new NamedGroupType [] { new NamedGroupSpec [] {
NamedGroupType.NAMED_GROUP_FFDHE }, NamedGroupSpec.NAMED_GROUP_FFDHE },
context.clientRequestedNamedGroups); context.clientRequestedNamedGroups);
if (preferableNamedGroup != null) { if (preferableNamedGroup != null) {
return new DHEPossession(preferableNamedGroup, return new DHEPossession(preferableNamedGroup,

View file

@ -125,6 +125,7 @@ final class DHServerKeyExchange {
Signature signer = null; Signature signer = null;
if (useExplicitSigAlgorithm) { if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm( signatureScheme = SignatureScheme.getPreferableAlgorithm(
shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes, shc.peerRequestedSignatureSchemes,
x509Possession, x509Possession,
shc.negotiatedProtocol); shc.negotiatedProtocol);

View file

@ -36,7 +36,6 @@ import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.ECParameterSpec; import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint; import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec; import java.security.spec.ECPublicKeySpec;
@ -44,7 +43,7 @@ import java.util.EnumSet;
import javax.crypto.KeyAgreement; 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.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; 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;
@ -88,7 +87,7 @@ final class ECDHKeyExchange {
static ECDHECredentials valueOf(NamedGroup namedGroup, static ECDHECredentials valueOf(NamedGroup namedGroup,
byte[] encodedPoint) throws IOException, GeneralSecurityException { byte[] encodedPoint) throws IOException, GeneralSecurityException {
if (namedGroup.type != NamedGroupType.NAMED_GROUP_ECDHE) { if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_ECDHE) {
throw new RuntimeException( throw new RuntimeException(
"Credentials decoding: Not ECDHE named group"); "Credentials decoding: Not ECDHE named group");
} }
@ -98,11 +97,7 @@ final class ECDHKeyExchange {
} }
ECParameterSpec parameters = ECParameterSpec parameters =
ECUtil.getECParameterSpec(null, namedGroup.oid); (ECParameterSpec)namedGroup.keAlgParamSpec;
if (parameters == null) {
return null;
}
ECPoint point = ECUtil.decodePoint( ECPoint point = ECUtil.decodePoint(
encodedPoint, parameters.getCurve()); encodedPoint, parameters.getCurve());
KeyFactory factory = KeyFactory.getInstance("EC"); KeyFactory factory = KeyFactory.getInstance("EC");
@ -120,9 +115,7 @@ final class ECDHKeyExchange {
ECDHEPossession(NamedGroup namedGroup, SecureRandom random) { ECDHEPossession(NamedGroup namedGroup, SecureRandom random) {
try { try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC"); KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC");
ECGenParameterSpec params = kpg.initialize(namedGroup.keAlgParamSpec, random);
(ECGenParameterSpec)namedGroup.getParameterSpec();
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair(); KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate(); privateKey = kp.getPrivate();
publicKey = (ECPublicKey)kp.getPublic(); publicKey = (ECPublicKey)kp.getPublic();
@ -248,17 +241,17 @@ final class ECDHKeyExchange {
preferableNamedGroup = SupportedGroups.getPreferredGroup( preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol, context.negotiatedProtocol,
context.algorithmConstraints, context.algorithmConstraints,
new NamedGroupType[] { new NamedGroupSpec[] {
NamedGroupType.NAMED_GROUP_ECDHE, NamedGroupSpec.NAMED_GROUP_ECDHE,
NamedGroupType.NAMED_GROUP_XDH }, NamedGroupSpec.NAMED_GROUP_XDH },
context.clientRequestedNamedGroups); context.clientRequestedNamedGroups);
} else { } else {
preferableNamedGroup = SupportedGroups.getPreferredGroup( preferableNamedGroup = SupportedGroups.getPreferredGroup(
context.negotiatedProtocol, context.negotiatedProtocol,
context.algorithmConstraints, context.algorithmConstraints,
new NamedGroupType[] { new NamedGroupSpec[] {
NamedGroupType.NAMED_GROUP_ECDHE, NamedGroupSpec.NAMED_GROUP_ECDHE,
NamedGroupType.NAMED_GROUP_XDH }); NamedGroupSpec.NAMED_GROUP_XDH });
} }
if (preferableNamedGroup != null) { if (preferableNamedGroup != null) {
@ -308,7 +301,8 @@ final class ECDHKeyExchange {
NamedGroup ng = NamedGroup.valueOf(params); NamedGroup ng = NamedGroup.valueOf(params);
if (ng == null) { if (ng == null) {
// unlikely, have been checked during cipher suite negotiation. // unlikely, have been checked during cipher suite
// negotiation.
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER, throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Unsupported EC server cert for ECDH key exchange"); "Unsupported EC server cert for ECDH key exchange");
} }
@ -480,7 +474,7 @@ final class ECDHKeyExchange {
} }
String alg; String alg;
switch (namedGroup.type) { switch (namedGroup.spec) {
case NAMED_GROUP_ECDHE: case NAMED_GROUP_ECDHE:
alg = "ECDH"; alg = "ECDH";
break; break;

View file

@ -38,6 +38,7 @@ import java.security.Signature;
import java.security.SignatureException; import java.security.SignatureException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.Locale; import java.util.Locale;
import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SSLHandshake.HandshakeMessage; import sun.security.ssl.SSLHandshake.HandshakeMessage;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Credentials;
@ -110,13 +111,18 @@ final class ECDHServerKeyExchange {
// Find the NamedGroup used for the ephemeral keys. // Find the NamedGroup used for the ephemeral keys.
namedGroup = namedGroupPossession.getNamedGroup(); namedGroup = namedGroupPossession.getNamedGroup();
publicPoint = namedGroup.encodePossessionPublicKey( if ((namedGroup == null) || (!namedGroup.isAvailable)) {
namedGroupPossession);
if ((namedGroup == null) || (namedGroup.oid == null) ) {
// unlikely // unlikely
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER, throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Missing Named Group"); "Missing or improper named group: " + namedGroup);
}
publicPoint = namedGroup.encodePossessionPublicKey(
namedGroupPossession);
if (publicPoint == null) {
// unlikely
throw shc.conContext.fatal(Alert.ILLEGAL_PARAMETER,
"Missing public point for named group: " + namedGroup);
} }
if (x509Possession == null) { if (x509Possession == null) {
@ -130,6 +136,7 @@ final class ECDHServerKeyExchange {
Signature signer = null; Signature signer = null;
if (useExplicitSigAlgorithm) { if (useExplicitSigAlgorithm) {
signatureScheme = SignatureScheme.getPreferableAlgorithm( signatureScheme = SignatureScheme.getPreferableAlgorithm(
shc.algorithmConstraints,
shc.peerRequestedSignatureSchemes, shc.peerRequestedSignatureSchemes,
x509Possession, x509Possession,
shc.negotiatedProtocol); shc.negotiatedProtocol);

View file

@ -34,7 +34,7 @@ import static sun.security.ssl.SSLExtension.CH_EC_POINT_FORMATS;
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.NamedGroup.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
/** /**
* Pack of the "ec_point_formats" extensions [RFC 4492]. * Pack of the "ec_point_formats" extensions [RFC 4492].
@ -179,7 +179,7 @@ final class ECPointFormatsExtension {
// Produce the extension. // Produce the extension.
// //
// produce the extension only if EC cipher suite is activated. // produce the extension only if EC cipher suite is activated.
if (NamedGroupType.NAMED_GROUP_ECDHE.isSupported( if (NamedGroupSpec.NAMED_GROUP_ECDHE.isSupported(
chc.activeCipherSuites)) { chc.activeCipherSuites)) {
// We are using uncompressed ECPointFormat only at present. // We are using uncompressed ECPointFormat only at present.
byte[] extData = new byte[] {0x01, 0x00}; byte[] extData = new byte[] {0x01, 0x00};

View file

@ -46,8 +46,8 @@ import javax.crypto.SecretKey;
import javax.net.ssl.SNIServerName; import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLHandshakeException; import javax.net.ssl.SSLHandshakeException;
import javax.security.auth.x500.X500Principal; import javax.security.auth.x500.X500Principal;
import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import static sun.security.ssl.NamedGroup.NamedGroupType.*; import static sun.security.ssl.NamedGroup.NamedGroupSpec.*;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
abstract class HandshakeContext implements ConnectionContext { abstract class HandshakeContext implements ConnectionContext {
@ -283,8 +283,8 @@ abstract class HandshakeContext implements ConnectionContext {
} }
boolean found = false; boolean found = false;
Map<NamedGroupType, Boolean> cachedStatus = Map<NamedGroupSpec, Boolean> cachedStatus =
new EnumMap<>(NamedGroupType.class); new EnumMap<>(NamedGroupSpec.class);
for (CipherSuite suite : enabledCipherSuites) { for (CipherSuite suite : enabledCipherSuites) {
if (suite.isAvailable() && suite.supports(protocol)) { if (suite.isAvailable() && suite.supports(protocol)) {
if (isActivatable(suite, if (isActivatable(suite,
@ -323,8 +323,8 @@ abstract class HandshakeContext implements ConnectionContext {
List<CipherSuite> suites = new LinkedList<>(); List<CipherSuite> suites = new LinkedList<>();
if (enabledProtocols != null && !enabledProtocols.isEmpty()) { if (enabledProtocols != null && !enabledProtocols.isEmpty()) {
Map<NamedGroupType, Boolean> cachedStatus = Map<NamedGroupSpec, Boolean> cachedStatus =
new EnumMap<>(NamedGroupType.class); new EnumMap<>(NamedGroupSpec.class);
for (CipherSuite suite : enabledCipherSuites) { for (CipherSuite suite : enabledCipherSuites) {
if (!suite.isAvailable()) { if (!suite.isAvailable()) {
continue; continue;
@ -509,7 +509,7 @@ abstract class HandshakeContext implements ConnectionContext {
private static boolean isActivatable(CipherSuite suite, private static boolean isActivatable(CipherSuite suite,
AlgorithmConstraints algorithmConstraints, AlgorithmConstraints algorithmConstraints,
Map<NamedGroupType, Boolean> cachedStatus) { Map<NamedGroupSpec, Boolean> cachedStatus) {
if (algorithmConstraints.permits( if (algorithmConstraints.permits(
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) { EnumSet.of(CryptoPrimitive.KEY_AGREEMENT), suite.name, null)) {
@ -520,8 +520,8 @@ abstract class HandshakeContext implements ConnectionContext {
// Is at least one of the group types available? // Is at least one of the group types available?
boolean groupAvailable, retval = false; boolean groupAvailable, retval = false;
NamedGroupType[] groupTypes = suite.keyExchange.groupTypes; NamedGroupSpec[] groupTypes = suite.keyExchange.groupTypes;
for (NamedGroupType groupType : groupTypes) { for (NamedGroupSpec groupType : groupTypes) {
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) {

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,7 @@ import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; 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;
@ -149,7 +149,7 @@ enum SignatureScheme {
final String name; // literal name final String name; // literal name
private final String algorithm; // signature algorithm private final String algorithm; // signature algorithm
final String keyAlgorithm; // signature key algorithm final String keyAlgorithm; // signature key algorithm
private final AlgorithmParameterSpec signAlgParameter; private final SigAlgParamSpec signAlgParams; // signature parameters
private final NamedGroup namedGroup; // associated named group private final NamedGroup namedGroup; // associated named group
// The minimal required key size in bits. // The minimal required key size in bits.
@ -184,21 +184,25 @@ enum SignatureScheme {
RSA_PSS_SHA384 ("SHA-384", 48), RSA_PSS_SHA384 ("SHA-384", 48),
RSA_PSS_SHA512 ("SHA-512", 64); RSA_PSS_SHA512 ("SHA-512", 64);
final private AlgorithmParameterSpec parameterSpec; private final AlgorithmParameterSpec parameterSpec;
final boolean isAvailable; private final AlgorithmParameters parameters;
private final boolean isAvailable;
SigAlgParamSpec(String hash, int saltLength) { SigAlgParamSpec(String hash, int saltLength) {
// See RFC 8017 // See RFC 8017
PSSParameterSpec pssParamSpec = PSSParameterSpec pssParamSpec =
new PSSParameterSpec(hash, "MGF1", new PSSParameterSpec(hash, "MGF1",
new MGF1ParameterSpec(hash), saltLength, 1); new MGF1ParameterSpec(hash), saltLength, 1);
AlgorithmParameters pssParams = null;
boolean mediator = true; boolean mediator = true;
try { try {
Signature signer = Signature.getInstance("RSASSA-PSS"); Signature signer = Signature.getInstance("RSASSA-PSS");
signer.setParameter(pssParamSpec); signer.setParameter(pssParamSpec);
pssParams = signer.getParameters();
} catch (InvalidAlgorithmParameterException | } catch (InvalidAlgorithmParameterException |
NoSuchAlgorithmException exp) { NoSuchAlgorithmException | RuntimeException exp) {
// Signature.getParameters() may throw RuntimeException.
mediator = false; mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning( SSLLogger.warning(
@ -209,10 +213,7 @@ enum SignatureScheme {
this.isAvailable = mediator; this.isAvailable = mediator;
this.parameterSpec = mediator ? pssParamSpec : null; this.parameterSpec = mediator ? pssParamSpec : null;
} this.parameters = mediator ? pssParams : null;
AlgorithmParameterSpec getParameterSpec() {
return parameterSpec;
} }
} }
@ -255,7 +256,7 @@ enum SignatureScheme {
private SignatureScheme(int id, String name, private SignatureScheme(int id, String name,
String algorithm, String keyAlgorithm, String algorithm, String keyAlgorithm,
SigAlgParamSpec signAlgParamSpec, SigAlgParamSpec signAlgParams,
NamedGroup namedGroup, int minimalKeySize, NamedGroup namedGroup, int minimalKeySize,
ProtocolVersion[] supportedProtocols, ProtocolVersion[] supportedProtocols,
ProtocolVersion[] handshakeSupportedProtocols) { ProtocolVersion[] handshakeSupportedProtocols) {
@ -263,8 +264,7 @@ enum SignatureScheme {
this.name = name; this.name = name;
this.algorithm = algorithm; this.algorithm = algorithm;
this.keyAlgorithm = keyAlgorithm; this.keyAlgorithm = keyAlgorithm;
this.signAlgParameter = this.signAlgParams = signAlgParams;
signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
this.namedGroup = namedGroup; this.namedGroup = namedGroup;
this.minimalKeySize = minimalKeySize; this.minimalKeySize = minimalKeySize;
this.supportedProtocols = Arrays.asList(supportedProtocols); this.supportedProtocols = Arrays.asList(supportedProtocols);
@ -272,8 +272,8 @@ enum SignatureScheme {
Arrays.asList(handshakeSupportedProtocols); Arrays.asList(handshakeSupportedProtocols);
boolean mediator = true; boolean mediator = true;
if (signAlgParamSpec != null) { if (signAlgParams != null) {
mediator = signAlgParamSpec.isAvailable; mediator = signAlgParams.isAvailable;
} else { } else {
try { try {
Signature.getInstance(algorithm); Signature.getInstance(algorithm);
@ -331,6 +331,18 @@ enum SignatureScheme {
return 2; return 2;
} }
private boolean isPermitted(AlgorithmConstraints constraints) {
return constraints.permits(SIGNATURE_PRIMITIVE_SET,
this.name, null) &&
constraints.permits(SIGNATURE_PRIMITIVE_SET,
this.keyAlgorithm, null) &&
constraints.permits(SIGNATURE_PRIMITIVE_SET,
this.algorithm, (signAlgParams != null ?
signAlgParams.parameters : null)) &&
(namedGroup != null ?
namedGroup.isPermitted(constraints) : true);
}
// Get local supported algorithm collection complying to algorithm // Get local supported algorithm collection complying to algorithm
// constraints. // constraints.
static List<SignatureScheme> getSupportedAlgorithms( static List<SignatureScheme> getSupportedAlgorithms(
@ -351,8 +363,7 @@ enum SignatureScheme {
} }
if (isMatch) { if (isMatch) {
if (constraints.permits( if (ss.isPermitted(constraints)) {
SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
supported.add(ss); supported.add(ss);
} else if (SSLLogger.isOn && } else if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) { SSLLogger.isOn("ssl,handshake,verbose")) {
@ -383,8 +394,7 @@ enum SignatureScheme {
} }
} else if (ss.isAvailable && } else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) && ss.supportedProtocols.contains(protocolVersion) &&
constraints.permits(SIGNATURE_PRIMITIVE_SET, ss.isPermitted(constraints)) {
ss.algorithm, null)) {
supported.add(ss); supported.add(ss);
} else { } else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@ -398,6 +408,7 @@ enum SignatureScheme {
} }
static SignatureScheme getPreferableAlgorithm( static SignatureScheme getPreferableAlgorithm(
AlgorithmConstraints constraints,
List<SignatureScheme> schemes, List<SignatureScheme> schemes,
SignatureScheme certScheme, SignatureScheme certScheme,
ProtocolVersion version) { ProtocolVersion version) {
@ -405,8 +416,8 @@ enum SignatureScheme {
for (SignatureScheme ss : schemes) { for (SignatureScheme ss : schemes) {
if (ss.isAvailable && if (ss.isAvailable &&
ss.handshakeSupportedProtocols.contains(version) && ss.handshakeSupportedProtocols.contains(version) &&
certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
ss.isPermitted(constraints)) {
return ss; return ss;
} }
} }
@ -415,6 +426,7 @@ enum SignatureScheme {
} }
static SignatureScheme getPreferableAlgorithm( static SignatureScheme getPreferableAlgorithm(
AlgorithmConstraints constraints,
List<SignatureScheme> schemes, List<SignatureScheme> schemes,
X509Possession x509Possession, X509Possession x509Possession,
ProtocolVersion version) { ProtocolVersion version) {
@ -432,9 +444,10 @@ enum SignatureScheme {
for (SignatureScheme ss : schemes) { for (SignatureScheme ss : schemes) {
if (ss.isAvailable && (keySize >= ss.minimalKeySize) && if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
ss.handshakeSupportedProtocols.contains(version) && ss.handshakeSupportedProtocols.contains(version) &&
keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) { keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
if ((ss.namedGroup != null) && (ss.namedGroup.type == ss.isPermitted(constraints)) {
NamedGroupType.NAMED_GROUP_ECDHE)) { if ((ss.namedGroup != null) && (ss.namedGroup.spec ==
NamedGroupSpec.NAMED_GROUP_ECDHE)) {
ECParameterSpec params = ECParameterSpec params =
x509Possession.getECParameterSpec(); x509Possession.getECParameterSpec();
if (params != null && if (params != null &&
@ -505,10 +518,13 @@ enum SignatureScheme {
Signature signer = Signature.getInstance(algorithm); Signature signer = Signature.getInstance(algorithm);
if (key instanceof PublicKey) { if (key instanceof PublicKey) {
SignatureUtil.initVerifyWithParam(signer, (PublicKey)key, SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
signAlgParameter); (signAlgParams != null ?
signAlgParams.parameterSpec : null));
} else { } else {
SignatureUtil.initSignWithParam(signer, (PrivateKey)key, SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
signAlgParameter, null); (signAlgParams != null ?
signAlgParams.parameterSpec : null),
null);
} }
return signer; return signer;

View file

@ -28,20 +28,15 @@ 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.security.AlgorithmConstraints;
import java.security.AlgorithmParameters;
import java.security.CryptoPrimitive;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import javax.net.ssl.SSLProtocolException; import javax.net.ssl.SSLProtocolException;
import sun.security.action.GetPropertyAction; import sun.security.action.GetPropertyAction;
import sun.security.ssl.NamedGroup.NamedGroupType; 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;
import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.ExtensionConsumer;
@ -188,7 +183,7 @@ final class SupportedGroupsExtension {
if (!group.isEmpty()) { if (!group.isEmpty()) {
NamedGroup namedGroup = NamedGroup.nameOf(group); NamedGroup namedGroup = NamedGroup.nameOf(group);
if (namedGroup != null) { if (namedGroup != null) {
if (isAvailableGroup(namedGroup)) { if (namedGroup.isAvailable) {
groupList.add(namedGroup); groupList.add(namedGroup);
} }
} // ignore unknown groups } // ignore unknown groups
@ -235,7 +230,7 @@ final class SupportedGroupsExtension {
groupList = new ArrayList<>(groups.length); groupList = new ArrayList<>(groups.length);
for (NamedGroup group : groups) { for (NamedGroup group : groups) {
if (isAvailableGroup(group)) { if (group.isAvailable) {
groupList.add(group); groupList.add(group);
} }
} }
@ -253,48 +248,19 @@ final class SupportedGroupsExtension {
} }
} }
// check whether the group is supported by the underlying providers
private static boolean isAvailableGroup(NamedGroup namedGroup) {
return namedGroup.isAvailableGroup();
}
static ECGenParameterSpec getECGenParamSpec(NamedGroup ng) {
if (ng.type != NamedGroupType.NAMED_GROUP_ECDHE) {
throw new RuntimeException(
"Not a named EC group: " + ng);
}
// parameters are non-null
AlgorithmParameters params = ng.getParameters();
try {
return params.getParameterSpec(ECGenParameterSpec.class);
} catch (InvalidParameterSpecException ipse) {
// should be unlikely
return new ECGenParameterSpec(ng.oid);
}
}
static AlgorithmParameters getParameters(NamedGroup ng) {
return ng.getParameters();
}
// Is there any supported group permitted by the constraints? // Is there any supported group permitted by the constraints?
static boolean isActivatable( static boolean isActivatable(
AlgorithmConstraints constraints, NamedGroupType type) { AlgorithmConstraints constraints, NamedGroupSpec type) {
boolean hasFFDHEGroups = false; boolean hasFFDHEGroups = false;
for (NamedGroup namedGroup : supportedNamedGroups) { for (NamedGroup namedGroup : supportedNamedGroups) {
if (namedGroup.type == type) { if (namedGroup.isAvailable && namedGroup.spec == type) {
if (constraints.permits( if (namedGroup.isPermitted(constraints)) {
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
getParameters(namedGroup))) {
return true; return true;
} }
if (!hasFFDHEGroups && if (!hasFFDHEGroups &&
(type == NamedGroupType.NAMED_GROUP_FFDHE)) { (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
hasFFDHEGroups = true; hasFFDHEGroups = true;
} }
} }
@ -306,20 +272,17 @@ final class SupportedGroupsExtension {
// //
// Note that the constraints checking on DHE parameters will be // Note that the constraints checking on DHE parameters will be
// performed during key exchanging in a handshake. // performed during key exchanging in a handshake.
return !hasFFDHEGroups && type == NamedGroupType.NAMED_GROUP_FFDHE; return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE;
} }
// Is the named group permitted by the constraints? // Is the named group permitted by the constraints?
static boolean isActivatable( static boolean isActivatable(
AlgorithmConstraints constraints, NamedGroup namedGroup) { AlgorithmConstraints constraints, NamedGroup namedGroup) {
if (!isSupported(namedGroup)) { if (!namedGroup.isAvailable || !isSupported(namedGroup)) {
return false; return false;
} }
return constraints.permits( return namedGroup.isPermitted(constraints);
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
getParameters(namedGroup));
} }
// Is the named group supported? // Is the named group supported?
@ -335,16 +298,13 @@ final class SupportedGroupsExtension {
static NamedGroup getPreferredGroup( static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol, ProtocolVersion negotiatedProtocol,
AlgorithmConstraints constraints, NamedGroupType[] types, AlgorithmConstraints constraints, NamedGroupSpec[] types,
List<NamedGroup> requestedNamedGroups) { List<NamedGroup> requestedNamedGroups) {
for (NamedGroup namedGroup : requestedNamedGroups) { for (NamedGroup namedGroup : requestedNamedGroups) {
if ((NamedGroupType.arrayContains(types, namedGroup.type)) && if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
namedGroup.isAvailable(negotiatedProtocol) && namedGroup.isAvailable(negotiatedProtocol) &&
isSupported(namedGroup) && isSupported(namedGroup) &&
constraints.permits( namedGroup.isPermitted(constraints)) {
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
getParameters(namedGroup))) {
return namedGroup; return namedGroup;
} }
} }
@ -354,14 +314,11 @@ final class SupportedGroupsExtension {
static NamedGroup getPreferredGroup( static NamedGroup getPreferredGroup(
ProtocolVersion negotiatedProtocol, ProtocolVersion negotiatedProtocol,
AlgorithmConstraints constraints, NamedGroupType[] types) { AlgorithmConstraints constraints, NamedGroupSpec[] types) {
for (NamedGroup namedGroup : supportedNamedGroups) { for (NamedGroup namedGroup : supportedNamedGroups) {
if ((NamedGroupType.arrayContains(types, namedGroup.type)) && if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) &&
namedGroup.isAvailable(negotiatedProtocol) && namedGroup.isAvailable(negotiatedProtocol) &&
constraints.permits( namedGroup.isPermitted(constraints)) {
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
namedGroup.algorithm,
getParameters(namedGroup))) {
return namedGroup; return namedGroup;
} }
} }
@ -401,15 +358,13 @@ final class SupportedGroupsExtension {
new ArrayList<>(SupportedGroups.supportedNamedGroups.length); new ArrayList<>(SupportedGroups.supportedNamedGroups.length);
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
if ((!SupportedGroups.enableFFDHE) && if ((!SupportedGroups.enableFFDHE) &&
(ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) { (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
continue; continue;
} }
if (ng.isAvailable(chc.activeProtocols) && if (ng.isAvailable(chc.activeProtocols) &&
ng.isSupported(chc.activeCipherSuites) && ng.isSupported(chc.activeCipherSuites) &&
chc.algorithmConstraints.permits( ng.isPermitted(chc.algorithmConstraints)) {
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
ng.algorithm, getParameters(ng))) {
namedGroups.add(ng); namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine( SSLLogger.fine(
@ -528,15 +483,13 @@ final class SupportedGroupsExtension {
SupportedGroups.supportedNamedGroups.length); SupportedGroups.supportedNamedGroups.length);
for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { for (NamedGroup ng : SupportedGroups.supportedNamedGroups) {
if ((!SupportedGroups.enableFFDHE) && if ((!SupportedGroups.enableFFDHE) &&
(ng.type == NamedGroupType.NAMED_GROUP_FFDHE)) { (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) {
continue; continue;
} }
if (ng.isAvailable(shc.activeProtocols) && if (ng.isAvailable(shc.activeProtocols) &&
ng.isSupported(shc.activeCipherSuites) && ng.isSupported(shc.activeCipherSuites) &&
shc.algorithmConstraints.permits( ng.isPermitted(shc.algorithmConstraints)) {
EnumSet.of(CryptoPrimitive.KEY_AGREEMENT),
ng.algorithm, getParameters(ng))) {
namedGroups.add(ng); namedGroups.add(ng);
} else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { } else if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.fine( SSLLogger.fine(

View file

@ -29,7 +29,7 @@ import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.interfaces.XECPublicKey; import java.security.interfaces.XECPublicKey;
import java.security.spec.*; import java.security.spec.*;
import sun.security.ssl.NamedGroup.NamedGroupType; import sun.security.ssl.NamedGroup.NamedGroupSpec;
import sun.security.util.*; import sun.security.util.*;
/** /**
@ -68,7 +68,7 @@ final class XDHKeyExchange {
byte[] encodedPoint) throws IOException, byte[] encodedPoint) throws IOException,
GeneralSecurityException { GeneralSecurityException {
if (namedGroup.type != NamedGroupType.NAMED_GROUP_XDH) { if (namedGroup.spec != NamedGroupSpec.NAMED_GROUP_XDH) {
throw new RuntimeException( throw new RuntimeException(
"Credentials decoding: Not XDH named group"); "Credentials decoding: Not XDH named group");
} }
@ -101,8 +101,7 @@ final class XDHKeyExchange {
try { try {
KeyPairGenerator kpg KeyPairGenerator kpg
= KeyPairGenerator.getInstance(namedGroup.algorithm); = KeyPairGenerator.getInstance(namedGroup.algorithm);
AlgorithmParameterSpec params = namedGroup.getParameterSpec(); kpg.initialize(namedGroup.keAlgParamSpec, random);
kpg.initialize(params, random);
KeyPair kp = kpg.generateKeyPair(); KeyPair kp = kpg.generateKeyPair();
privateKey = kp.getPrivate(); privateKey = kp.getPrivate();
publicKey = (XECPublicKey) kp.getPublic(); publicKey = (XECPublicKey) kp.getPublic();

View file

@ -62,7 +62,7 @@ public class CurveDB {
} }
// Return a NamedCurve for the specified OID/name or null if unknown. // Return a NamedCurve for the specified OID/name or null if unknown.
static NamedCurve lookup(String name) { public static NamedCurve lookup(String name) {
NamedCurve spec = oidMap.get(name); NamedCurve spec = oidMap.get(name);
if (spec != null) { if (spec != null) {
return spec; return spec;
@ -83,7 +83,7 @@ public class CurveDB {
// Convert the given ECParameterSpec object to a NamedCurve object. // Convert the given ECParameterSpec object to a NamedCurve object.
// If params does not represent a known named curve, return null. // If params does not represent a known named curve, return null.
static NamedCurve lookup(ECParameterSpec params) { public static NamedCurve lookup(ECParameterSpec params) {
if ((params instanceof NamedCurve) || (params == null)) { if ((params instanceof NamedCurve) || (params == null)) {
return (NamedCurve)params; return (NamedCurve)params;
} }

View file

@ -541,9 +541,9 @@ sun.security.krb5.maxReferrals=5
# usage [TLSServer] [TLSClient] [SignedJAR] # usage [TLSServer] [TLSClient] [SignedJAR]
# #
# The "AlgorithmName" is the standard algorithm name of the disabled # The "AlgorithmName" is the standard algorithm name of the disabled
# algorithm. See "Java Cryptography Architecture Standard Algorithm Name # algorithm. See the Java Security Standard Algorithm Names Specification
# Documentation" for information about Standard Algorithm Names. Matching # for information about Standard Algorithm Names. Matching is
# is performed using a case-insensitive sub-element matching rule. (For # performed using a case-insensitive sub-element matching rule. (For
# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and # example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and
# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a # "ECDSA" for signatures.) If the assertion "AlgorithmName" is a
# sub-element of the certificate algorithm name, the algorithm will be # sub-element of the certificate algorithm name, the algorithm will be
@ -677,8 +677,9 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# In some environments, certain algorithms or key lengths may be undesirable # In some environments, certain algorithms or key lengths may be undesirable
# when using SSL/TLS/DTLS. This section describes the mechanism for disabling # when using SSL/TLS/DTLS. This section describes the mechanism for disabling
# algorithms during SSL/TLS/DTLS security parameters negotiation, including # algorithms during SSL/TLS/DTLS security parameters negotiation, including
# protocol version negotiation, cipher suites selection, peer authentication # protocol version negotiation, cipher suites selection, named groups
# and key exchange mechanisms. # selection, signature schemes selection, peer authentication and key
# exchange mechanisms.
# #
# Disabled algorithms will not be negotiated for SSL/TLS connections, even # Disabled algorithms will not be negotiated for SSL/TLS connections, even
# if they are enabled explicitly in an application. # if they are enabled explicitly in an application.
@ -699,7 +700,8 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \
# It is not guaranteed to be examined and used by other implementations. # It is not guaranteed to be examined and used by other implementations.
# #
# Example: # Example:
# jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048, \
# rsa_pkcs1_sha1, secp224r1
jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \ jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
EC keySize < 224, 3DES_EDE_CBC, anon, NULL EC keySize < 224, 3DES_EDE_CBC, anon, NULL
@ -743,8 +745,8 @@ jdk.tls.disabledAlgorithms=SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, \
# 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC # 3. JSSE cipher (encryption) algorithm name, e.g., AES_128_CBC
# 4. JSSE message digest algorithm name, e.g., SHA # 4. JSSE message digest algorithm name, e.g., SHA
# #
# See SSL/TLS specifications and "Java Cryptography Architecture Standard # See SSL/TLS specifications and the Java Security Standard Algorithm Names
# Algorithm Name Documentation" for information about the algorithm names. # Specification for information about the algorithm names.
# #
# Note: If a legacy algorithm is also restricted through the # Note: If a legacy algorithm is also restricted through the
# jdk.tls.disabledAlgorithms property or the # jdk.tls.disabledAlgorithms property or the

View file

@ -0,0 +1,105 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. 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 8226374
* @library /javax/net/ssl/templates
* @summary Restrict signature algorithms and named groups
* @run main/othervm RestrictNamedGroup x25519
* @run main/othervm RestrictNamedGroup x448
* @run main/othervm RestrictNamedGroup secp256r1
* @run main/othervm RestrictNamedGroup secp384r1
* @run main/othervm RestrictNamedGroup secp521r1
* @run main/othervm RestrictNamedGroup ffdhe2048
* @run main/othervm RestrictNamedGroup ffdhe3072
* @run main/othervm RestrictNamedGroup ffdhe4096
* @run main/othervm RestrictNamedGroup ffdhe6144
* @run main/othervm RestrictNamedGroup ffdhe8192
*/
import java.security.Security;
import java.util.Arrays;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLException;
public class RestrictNamedGroup extends SSLSocketTemplate {
private static volatile int index;
private static final String[][][] protocols = {
{{"TLSv1.3"}, {"TLSv1.3"}},
{{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
{{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
{{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
{{"TLSv1.2"}, {"TLSv1.2"}}
};
// Servers are configured before clients, increment test case after.
@Override
protected void configureClientSocket(SSLSocket socket) {
String[] ps = protocols[index][0];
System.out.print("Setting client protocol(s): ");
Arrays.stream(ps).forEachOrdered(System.out::print);
System.out.println();
socket.setEnabledProtocols(ps);
socket.setEnabledCipherSuites(new String[] {
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
}
@Override
protected void configureServerSocket(SSLServerSocket serverSocket) {
String[] ps = protocols[index][1];
System.out.print("Setting server protocol(s): ");
Arrays.stream(ps).forEachOrdered(System.out::print);
System.out.println();
serverSocket.setEnabledProtocols(ps);
serverSocket.setEnabledCipherSuites(new String[] {
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
}
/*
* Run the test case.
*/
public static void main(String[] args) throws Exception {
Security.setProperty("jdk.tls.disabledAlgorithms", args[0]);
System.setProperty("jdk.tls.namedGroups", args[0]);
for (index = 0; index < protocols.length; index++) {
try {
(new RestrictNamedGroup()).run();
} catch (SSLException | IllegalStateException ssle) {
// The named group should be restricted.
continue;
}
throw new Exception("The test case should be disabled");
}
}
}

View file

@ -0,0 +1,232 @@
/*
* Copyright (c) 2019, Oracle and/or its affiliates. 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 8226374
* @library /javax/net/ssl/templates
* @summary Restrict signature algorithms and named groups
* @run main/othervm RestrictSignatureScheme
*/
import java.io.ByteArrayInputStream;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import java.util.Base64;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.SSLException;
public class RestrictSignatureScheme extends SSLSocketTemplate {
private static volatile int index;
private static final String[][][] protocols = {
{{"TLSv1.3"}, {"TLSv1.3"}},
{{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
{{"TLSv1.3", "TLSv1.2"}, {"TLSv1.2"}},
{{"TLSv1.2"}, {"TLSv1.3", "TLSv1.2"}},
{{"TLSv1.2"}, {"TLSv1.2"}}
};
private final SSLContext context;
RestrictSignatureScheme() throws Exception {
this.context = createSSLContext();
}
@Override
protected SSLContext createClientSSLContext() throws Exception {
return context;
}
@Override
protected SSLContext createServerSSLContext() throws Exception {
return context;
}
// Servers are configured before clients, increment test case after.
@Override
protected void configureClientSocket(SSLSocket socket) {
String[] ps = protocols[index][0];
System.out.print("Setting client protocol(s): ");
Arrays.stream(ps).forEachOrdered(System.out::print);
System.out.println();
socket.setEnabledProtocols(ps);
socket.setEnabledCipherSuites(new String[] {
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
}
@Override
protected void configureServerSocket(SSLServerSocket serverSocket) {
String[] ps = protocols[index][1];
System.out.print("Setting server protocol(s): ");
Arrays.stream(ps).forEachOrdered(System.out::print);
System.out.println();
serverSocket.setEnabledProtocols(ps);
serverSocket.setEnabledCipherSuites(new String[] {
"TLS_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"});
}
/*
* Run the test case.
*/
public static void main(String[] args) throws Exception {
Security.setProperty("jdk.tls.disabledAlgorithms", "RSASSA-PSS");
for (index = 0; index < protocols.length; index++) {
try {
(new RestrictSignatureScheme()).run();
} catch (SSLException | IllegalStateException ssle) {
// The named group should be restricted.
continue;
}
throw new Exception("The test case should be disabled");
}
}
private static final String trustedCertStr =
/**
* Signature Algorithm: rsassaPss
* Issuer: CN = localhost
* Validity Not Before: Jun 6 07:11:00 2018 GMT
* Not After : Jun 1 07:11:00 2038 GMT
* Subject: CN = localhost
* Public Key Algorithm: rsassaPss
*/
"-----BEGIN CERTIFICATE-----\n"
+ "MIIDZjCCAh2gAwIBAgIUHxwPs3eAgJ057nJwiLgWZWeNqdgwPgYJKoZIhvcNAQEK\n"
+ "MDGgDTALBglghkgBZQMEAgGhGjAYBgkqhkiG9w0BAQgwCwYJYIZIAWUDBAIBogQC\n"
+ "AgDeMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xODA2MDYwNzExMDBaFw0zODA2\n"
+ "MDEwNzExMDBaMBQxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASAwCwYJKoZIhvcNAQEK\n"
+ "A4IBDwAwggEKAoIBAQCl8r4Qrg27BYUO/1Va2Ix8QPGzN/lvzmKvP5Ff26ovNW4v\n"
+ "RUx68HzAhhiWtcl+PwLSbJqJreEkTlle7PnRAypby3fO7ZAK0Y3YiHquaBg7d+7Y\n"
+ "FhhHwv8gG0lZcyA0BkXFJHqdq76qar0xHC6DVezXm0K3mcceymGtFR9BzWmAj+7D\n"
+ "YsSwvtTQ7WNoQmf0cdDMSM71IwaTwIwvT2wzX1vv5hcdDyXdr64WFqWSA9sNJ2K6\n"
+ "arxaaU1klwKSgDokF6njafWQ4UxdR67d5W1MYoiioDs2Yy3utsMpO2OUzZVBZNdT\n"
+ "gkr1jsJhIurpz/5K51lwJIRQBezEFSb+60AFVoMJAgMBAAGjUDBOMB0GA1UdDgQW\n"
+ "BBQfFit5ilWJmZgCX4QY0HsaI9iIDDAfBgNVHSMEGDAWgBQfFit5ilWJmZgCX4QY\n"
+ "0HsaI9iIDDAMBgNVHRMEBTADAQH/MD4GCSqGSIb3DQEBCjAxoA0wCwYJYIZIAWUD\n"
+ "BAIBoRowGAYJKoZIhvcNAQEIMAsGCWCGSAFlAwQCAaIEAgIA3gOCAQEAa4yUQ3gh\n"
+ "d1YWPdEa1sv2hdkhtenw6m5yxbmaQl2+nIKSpk4RfpXC7K1EYwBF8TdfFbD8hGGh\n"
+ "5n81BT0/dn1R9SRGCv7KTxx4lfQt31frlsw/tVciwyXQtcUZ6DqfnLP0/aRVLNgx\n"
+ "zaP542JUHFYLTC3EGz2zUgv70ZUTlIsPG3/p8YO1iXdnYGQyzOuQPUBpI7nS7UtR\n"
+ "Ug8VE9ACpBxxI3qChMahFZGHlXCCSjSmxpQa6UO4SQl8q5tPNnqdzWwvAW8qkCy4\n"
+ "6barRQ4sMcGayhHh/uSTx7bcl0FMJpcI1ygbw7/Pc03zKtw0gMTBMns7q4yXjb/u\n"
+ "ef47nW0t+LRAAg==\n"
+ "-----END CERTIFICATE-----\n";
private static final String keyCertStr = trustedCertStr;
private static final String privateKey =
"MIIEuwIBADALBgkqhkiG9w0BAQoEggSnMIIEowIBAAKCAQEApfK+EK4NuwWFDv9V\n"
+ "WtiMfEDxszf5b85irz+RX9uqLzVuL0VMevB8wIYYlrXJfj8C0myaia3hJE5ZXuz5\n"
+ "0QMqW8t3zu2QCtGN2Ih6rmgYO3fu2BYYR8L/IBtJWXMgNAZFxSR6nau+qmq9MRwu\n"
+ "g1Xs15tCt5nHHsphrRUfQc1pgI/uw2LEsL7U0O1jaEJn9HHQzEjO9SMGk8CML09s\n"
+ "M19b7+YXHQ8l3a+uFhalkgPbDSdiumq8WmlNZJcCkoA6JBep42n1kOFMXUeu3eVt\n"
+ "TGKIoqA7NmMt7rbDKTtjlM2VQWTXU4JK9Y7CYSLq6c/+SudZcCSEUAXsxBUm/utA\n"
+ "BVaDCQIDAQABAoIBAAc4vRS0vlw5LUUtz2UYr2Ro3xvRf8Vh0eGWfpkRUiKjzJu6\n"
+ "BE4FUSh/rWpBlvcrfs/xcfgz3OxbjIAZB/YUkS9Vd21F4VLXM7kMl2onlYZg/b/h\n"
+ "lkTpM3kONu7xl6Er9LVTlRJveuinpHwSoeONRbVMSGb9BjFM1VtW4/lVGxZBG05D\n"
+ "y9i/o4vCZqULn9cAumOwicKuCyTcS58XcMJ+puSPfRA71PYLxqFkASAoJsUwCXpo\n"
+ "gs39lLsIFgrfO8mBO1ux/SE+QaRc+9XqFSHHKD1XqF/9zSYBgWjE910EcpdYEdZx\n"
+ "GEkwea7Fn4brO5OpIrHY/45naqbUOBzv6gufMAECgYEAz7PHCdcrQvmOb8EiNbQH\n"
+ "uvSimwObWJFeN1ykp6mfRbSnkXw7p8+M4Tc8HFi8QLpoq63Ev2AwoaQCQvHbFC2Y\n"
+ "1Cz0EkC0aOp+tZP7U2AUBdkcDesZAJQTad0zV6KesyIUXdxZXDG8JJ1XSNWfTJV4\n"
+ "QD+BjLZ0jiAyCIfVYvWQqYkCgYEAzIln1nKTixLMPr5CldSmR7ZarEtPJU+hHwVg\n"
+ "dV/Lc6d2Yy9JgunOXRo4BXB1TEo8JFbK3HBQH6tS8li4qDr7WK5wyYfh8qb4WZyu\n"
+ "lc562f2WVYntcN8/Ojb+Vyrt7lk9sq/8KoVHxEAWd6mqL9VTPYuAu1Vw9fTGIZfB\n"
+ "lDeELYECgYAvdzU4UXzofGGJtohb332YwwlaBZP9xJLUcg6K5l+orWVSASMc8XiP\n"
+ "i3DoRXsYC8GZ4kdBOPlEJ1gA9oaLcPQpIPDSLwlLpLM6Scw4vI822uvnXl/DWxOo\n"
+ "sM1n7Jj59QLUhGPDhvYpI+/rjC4wcUQe4qR3hMbUKBVnD6u7RsU9iQKBgQCQ17VK\n"
+ "7bSCRfuRaxaoGADww7gOTv5rQ6qr1xjpxb7D1hFGR9Rc+smCsPB/GZZXQjK44SWj\n"
+ "WX3ED4Ubzaxmpe4cbNu+O5XMSmWQwB36RFBHUwdE5/nXdqDFzu/qNqJrqZLBmVKP\n"
+ "ofaiiWffsaytVvotmT6+atElvAMbAua42V+nAQKBgHtIn3mYMHLriYGhQzpkFEA2\n"
+ "8YcAMlKppueOMAKVy8nLu2r3MidmLAhMiKJQKG45I3Yg0/t/25tXLiOPJlwrOebh\n"
+ "xQqUBI/JUOIpGAEnr48jhOXnCS+i+z294G5U/RgjXrlR4bCPvrtCmwzWwe0h79w2\n"
+ "Q2hO5ZTW6UD9CVA85whf";
private static SSLContext createSSLContext() throws Exception {
// Generate certificate from cert string
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// Create a key store
KeyStore ts = KeyStore.getInstance("PKCS12");
KeyStore ks = KeyStore.getInstance("PKCS12");
ts.load(null, null);
ks.load(null, null);
char passphrase[] = "passphrase".toCharArray();
// Import the trusted cert
ts.setCertificateEntry("trusted-cert-RSASSA-PSS",
cf.generateCertificate(new ByteArrayInputStream(
trustedCertStr.getBytes())));
boolean hasKeyMaterials = keyCertStr != null && privateKey != null;
if (hasKeyMaterials) {
// Generate the private key.
PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec(
Base64.getMimeDecoder().decode(privateKey));
KeyFactory kf = KeyFactory.getInstance("RSASSA-PSS");
PrivateKey priKey = kf.generatePrivate(priKeySpec);
// Generate certificate chain
Certificate keyCert = cf.generateCertificate(
new ByteArrayInputStream(keyCertStr.getBytes()));
Certificate[] chain = new Certificate[]{keyCert};
// Import the key entry.
ks.setKeyEntry("cert-RSASSA-PSS", priKey, passphrase, chain);
}
// Create SSL context
TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
tmf.init(ts);
SSLContext context = SSLContext.getInstance("TLS");
if (hasKeyMaterials) {
KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
kmf.init(ks, passphrase);
context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
} else {
context.init(null, tmf.getTrustManagers(), null);
}
return context;
}
}