--- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Thu Oct 17 20:27:44 2019 +0100
+++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java Thu Oct 17 20:53:35 2019 +0100
@@ -26,7 +26,6 @@
package sun.security.ssl;
import java.security.*;
-import java.security.interfaces.ECPrivateKey;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECParameterSpec;
import java.security.spec.MGF1ParameterSpec;
@@ -39,8 +38,8 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroup;
-import sun.security.ssl.SupportedGroupsExtension.NamedGroupType;
+import sun.security.ssl.NamedGroup.NamedGroupSpec;
+import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
import sun.security.util.SignatureUtil;
@@ -150,7 +149,7 @@
final String name; // literal name
private final String algorithm; // signature algorithm
final String keyAlgorithm; // signature key algorithm
- private final AlgorithmParameterSpec signAlgParameter;
+ private final SigAlgParamSpec signAlgParams; // signature parameters
private final NamedGroup namedGroup; // associated named group
// The minimal required key size in bits.
@@ -185,21 +184,25 @@
RSA_PSS_SHA384 ("SHA-384", 48),
RSA_PSS_SHA512 ("SHA-512", 64);
- final private AlgorithmParameterSpec parameterSpec;
- final boolean isAvailable;
+ private final AlgorithmParameterSpec parameterSpec;
+ private final AlgorithmParameters parameters;
+ private final boolean isAvailable;
SigAlgParamSpec(String hash, int saltLength) {
// See RFC 8017
PSSParameterSpec pssParamSpec =
new PSSParameterSpec(hash, "MGF1",
new MGF1ParameterSpec(hash), saltLength, 1);
+ AlgorithmParameters pssParams = null;
boolean mediator = true;
try {
Signature signer = Signature.getInstance("RSASSA-PSS");
signer.setParameter(pssParamSpec);
+ pssParams = signer.getParameters();
} catch (InvalidAlgorithmParameterException |
- NoSuchAlgorithmException exp) {
+ NoSuchAlgorithmException | RuntimeException exp) {
+ // Signature.getParameters() may throw RuntimeException.
mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
@@ -210,10 +213,7 @@
this.isAvailable = mediator;
this.parameterSpec = mediator ? pssParamSpec : null;
- }
-
- AlgorithmParameterSpec getParameterSpec() {
- return parameterSpec;
+ this.parameters = mediator ? pssParams : null;
}
}
@@ -256,7 +256,7 @@
private SignatureScheme(int id, String name,
String algorithm, String keyAlgorithm,
- SigAlgParamSpec signAlgParamSpec,
+ SigAlgParamSpec signAlgParams,
NamedGroup namedGroup, int minimalKeySize,
ProtocolVersion[] supportedProtocols,
ProtocolVersion[] handshakeSupportedProtocols) {
@@ -264,8 +264,7 @@
this.name = name;
this.algorithm = algorithm;
this.keyAlgorithm = keyAlgorithm;
- this.signAlgParameter =
- signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
+ this.signAlgParams = signAlgParams;
this.namedGroup = namedGroup;
this.minimalKeySize = minimalKeySize;
this.supportedProtocols = Arrays.asList(supportedProtocols);
@@ -273,8 +272,8 @@
Arrays.asList(handshakeSupportedProtocols);
boolean mediator = true;
- if (signAlgParamSpec != null) {
- mediator = signAlgParamSpec.isAvailable;
+ if (signAlgParams != null) {
+ mediator = signAlgParams.isAvailable;
} else {
try {
Signature.getInstance(algorithm);
@@ -332,6 +331,18 @@
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
// constraints.
static List<SignatureScheme> getSupportedAlgorithms(
@@ -352,8 +363,7 @@
}
if (isMatch) {
- if (constraints.permits(
- SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
+ if (ss.isPermitted(constraints)) {
supported.add(ss);
} else if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
@@ -384,8 +394,7 @@
}
} else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) &&
- constraints.permits(SIGNATURE_PRIMITIVE_SET,
- ss.algorithm, null)) {
+ ss.isPermitted(constraints)) {
supported.add(ss);
} else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
@@ -399,6 +408,7 @@
}
static SignatureScheme getPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
SignatureScheme certScheme,
ProtocolVersion version) {
@@ -406,8 +416,8 @@
for (SignatureScheme ss : schemes) {
if (ss.isAvailable &&
ss.handshakeSupportedProtocols.contains(version) &&
- certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
-
+ certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+ ss.isPermitted(constraints)) {
return ss;
}
}
@@ -416,6 +426,7 @@
}
static SignatureScheme getPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
X509Possession x509Possession,
ProtocolVersion version) {
@@ -432,16 +443,50 @@
}
for (SignatureScheme ss : schemes) {
if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
- ss.handshakeSupportedProtocols.contains(version) &&
- keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
- if (ss.namedGroup != null &&
- ss.namedGroup.type == NamedGroupType.NAMED_GROUP_ECDHE) {
+ ss.handshakeSupportedProtocols.contains(version) &&
+ keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
+ ss.isPermitted(constraints)) {
+ if ((ss.namedGroup != null) && (ss.namedGroup.spec ==
+ NamedGroupSpec.NAMED_GROUP_ECDHE)) {
ECParameterSpec params =
x509Possession.getECParameterSpec();
if (params != null &&
ss.namedGroup == NamedGroup.valueOf(params)) {
return ss;
}
+
+ if (SSLLogger.isOn &&
+ SSLLogger.isOn("ssl,handshake,verbose")) {
+ SSLLogger.finest(
+ "Ignore the signature algorithm (" + ss +
+ "), unsupported EC parameter spec: " + params);
+ }
+ } else if ("EC".equals(ss.keyAlgorithm)) {
+ // Must be a legacy signature algorithm, which does not
+ // specify the associated named groups. The connection
+ // cannot be established if the peer cannot recognize
+ // the named group used for the signature. RFC 8446
+ // does not define countermeasures for the corner cases.
+ // In order to mitigate the impact, we choose to check
+ // against the local supported named groups. The risk
+ // should be minimal as applications should not use
+ // unsupported named groups for its certificates.
+ ECParameterSpec params =
+ x509Possession.getECParameterSpec();
+ if (params != null) {
+ NamedGroup keyGroup = NamedGroup.valueOf(params);
+ if (keyGroup != null &&
+ SupportedGroups.isSupported(keyGroup)) {
+ return ss;
+ }
+ }
+
+ if (SSLLogger.isOn &&
+ SSLLogger.isOn("ssl,handshake,verbose")) {
+ SSLLogger.finest(
+ "Ignore the legacy signature algorithm (" + ss +
+ "), unsupported EC parameter spec: " + params);
+ }
} else {
return ss;
}
@@ -473,10 +518,13 @@
Signature signer = Signature.getInstance(algorithm);
if (key instanceof PublicKey) {
SignatureUtil.initVerifyWithParam(signer, (PublicKey)key,
- signAlgParameter);
+ (signAlgParams != null ?
+ signAlgParams.parameterSpec : null));
} else {
SignatureUtil.initSignWithParam(signer, (PrivateKey)key,
- signAlgParameter, null);
+ (signAlgParams != null ?
+ signAlgParams.parameterSpec : null),
+ null);
}
return signer;