mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8226374: Restrict TLS signature schemes and named groups
Reviewed-by: mullan
This commit is contained in:
parent
de8ce983b3
commit
316140ff92
18 changed files with 810 additions and 626 deletions
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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};
|
||||||
|
|
|
@ -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
|
@ -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;
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
105
test/jdk/sun/security/ssl/CipherSuite/RestrictNamedGroup.java
Normal file
105
test/jdk/sun/security/ssl/CipherSuite/RestrictNamedGroup.java
Normal 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue