< prev index next >
src/java.base/share/classes/sun/security/ssl/SignatureScheme.java
Print this page
rev 54061 : 8226374: Restrict TLS signature schemes and named groups
Reviewed-by: mullan
*** 38,48 ****
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
! import sun.security.ssl.NamedGroup.NamedGroupType;
import sun.security.ssl.SupportedGroupsExtension.SupportedGroups;
import sun.security.ssl.X509Authentication.X509Possession;
import sun.security.util.KeyUtil;
import sun.security.util.SignatureUtil;
--- 38,48 ----
import java.util.EnumSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
! 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;
*** 149,159 ****
final int id; // hash + signature
final String name; // literal name
private final String algorithm; // signature algorithm
final String keyAlgorithm; // signature key algorithm
! private final AlgorithmParameterSpec signAlgParameter;
private final NamedGroup namedGroup; // associated named group
// The minimal required key size in bits.
//
// Only need to check RSA algorithm at present. RSA keys of 512 bits
--- 149,159 ----
final int id; // hash + signature
final String name; // literal name
private final String algorithm; // signature algorithm
final String keyAlgorithm; // signature key algorithm
! private final SigAlgParamSpec signAlgParams; // signature parameters
private final NamedGroup namedGroup; // associated named group
// The minimal required key size in bits.
//
// Only need to check RSA algorithm at present. RSA keys of 512 bits
*** 184,222 ****
static enum SigAlgParamSpec { // support RSASSA-PSS only now
RSA_PSS_SHA256 ("SHA-256", 32),
RSA_PSS_SHA384 ("SHA-384", 48),
RSA_PSS_SHA512 ("SHA-512", 64);
! final private AlgorithmParameterSpec parameterSpec;
! final boolean isAvailable;
SigAlgParamSpec(String hash, int saltLength) {
// See RFC 8017
PSSParameterSpec pssParamSpec =
new PSSParameterSpec(hash, "MGF1",
new MGF1ParameterSpec(hash), saltLength, 1);
boolean mediator = true;
try {
Signature signer = JsseJce.getSignature("RSASSA-PSS");
signer.setParameter(pssParamSpec);
} catch (InvalidAlgorithmParameterException |
! NoSuchAlgorithmException exp) {
mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
"RSASSA-PSS signature with " + hash +
" is not supported by the underlying providers", exp);
}
}
this.isAvailable = mediator;
this.parameterSpec = mediator ? pssParamSpec : null;
! }
!
! AlgorithmParameterSpec getParameterSpec() {
! return parameterSpec;
}
}
// performance optimization
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
--- 184,223 ----
static enum SigAlgParamSpec { // support RSASSA-PSS only now
RSA_PSS_SHA256 ("SHA-256", 32),
RSA_PSS_SHA384 ("SHA-384", 48),
RSA_PSS_SHA512 ("SHA-512", 64);
! 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 = JsseJce.getSignature("RSASSA-PSS");
signer.setParameter(pssParamSpec);
+ pssParams = signer.getParameters();
} catch (InvalidAlgorithmParameterException |
! NoSuchAlgorithmException | RuntimeException exp) {
! // Signature.getParameters() may throw RuntimeException.
mediator = false;
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
"RSASSA-PSS signature with " + hash +
" is not supported by the underlying providers", exp);
}
}
this.isAvailable = mediator;
this.parameterSpec = mediator ? pssParamSpec : null;
! this.parameters = mediator ? pssParams : null;
}
}
// performance optimization
private static final Set<CryptoPrimitive> SIGNATURE_PRIMITIVE_SET =
*** 255,274 ****
supportedProtocols, supportedProtocols);
}
private SignatureScheme(int id, String name,
String algorithm, String keyAlgorithm,
! SigAlgParamSpec signAlgParamSpec,
NamedGroup namedGroup, int minimalKeySize,
ProtocolVersion[] supportedProtocols,
ProtocolVersion[] handshakeSupportedProtocols) {
this.id = id;
this.name = name;
this.algorithm = algorithm;
this.keyAlgorithm = keyAlgorithm;
! this.signAlgParameter =
! signAlgParamSpec != null ? signAlgParamSpec.parameterSpec : null;
this.namedGroup = namedGroup;
this.minimalKeySize = minimalKeySize;
this.supportedProtocols = Arrays.asList(supportedProtocols);
this.handshakeSupportedProtocols =
Arrays.asList(handshakeSupportedProtocols);
--- 256,274 ----
supportedProtocols, supportedProtocols);
}
private SignatureScheme(int id, String name,
String algorithm, String keyAlgorithm,
! SigAlgParamSpec signAlgParams,
NamedGroup namedGroup, int minimalKeySize,
ProtocolVersion[] supportedProtocols,
ProtocolVersion[] handshakeSupportedProtocols) {
this.id = id;
this.name = name;
this.algorithm = algorithm;
this.keyAlgorithm = keyAlgorithm;
! this.signAlgParams = signAlgParams;
this.namedGroup = namedGroup;
this.minimalKeySize = minimalKeySize;
this.supportedProtocols = Arrays.asList(supportedProtocols);
this.handshakeSupportedProtocols =
Arrays.asList(handshakeSupportedProtocols);
*** 282,293 ****
mediator = JsseJce.isEcAvailable();
}
// Check the specific algorithm and parameters.
if (mediator) {
! if (signAlgParamSpec != null) {
! mediator = signAlgParamSpec.isAvailable;
} else {
try {
JsseJce.getSignature(algorithm);
} catch (Exception e) {
mediator = false;
--- 282,293 ----
mediator = JsseJce.isEcAvailable();
}
// Check the specific algorithm and parameters.
if (mediator) {
! if (signAlgParams != null) {
! mediator = signAlgParams.isAvailable;
} else {
try {
JsseJce.getSignature(algorithm);
} catch (Exception e) {
mediator = false;
*** 353,362 ****
--- 353,374 ----
// Return the size of a SignatureScheme structure in TLS record
static int sizeInRecord() {
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(
SSLConfiguration config,
AlgorithmConstraints constraints,
*** 381,392 ****
break;
}
}
if (isMatch) {
! if (constraints.permits(
! SIGNATURE_PRIMITIVE_SET, ss.algorithm, null)) {
supported.add(ss);
} else if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
SSLLogger.finest(
"Ignore disabled signature scheme: " + ss.name);
--- 393,403 ----
break;
}
}
if (isMatch) {
! if (ss.isPermitted(constraints)) {
supported.add(ss);
} else if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
SSLLogger.finest(
"Ignore disabled signature scheme: " + ss.name);
*** 416,427 ****
}
} else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) &&
(config.signatureSchemes.isEmpty() ||
config.signatureSchemes.contains(ss)) &&
! constraints.permits(SIGNATURE_PRIMITIVE_SET,
! ss.algorithm, null)) {
supported.add(ss);
} else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
"Unsupported signature scheme: " + ss.name);
--- 427,437 ----
}
} else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) &&
(config.signatureSchemes.isEmpty() ||
config.signatureSchemes.contains(ss)) &&
! ss.isPermitted(constraints)) {
supported.add(ss);
} else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) {
SSLLogger.warning(
"Unsupported signature scheme: " + ss.name);
*** 431,457 ****
return supported;
}
static SignatureScheme getPreferableAlgorithm(
List<SignatureScheme> schemes,
SignatureScheme certScheme,
ProtocolVersion version) {
for (SignatureScheme ss : schemes) {
if (ss.isAvailable &&
ss.handshakeSupportedProtocols.contains(version) &&
! certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm)) {
!
return ss;
}
}
return null;
}
static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm(
List<SignatureScheme> schemes,
X509Possession x509Possession,
ProtocolVersion version) {
PrivateKey signingKey = x509Possession.popPrivateKey;
--- 441,469 ----
return supported;
}
static SignatureScheme getPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
SignatureScheme certScheme,
ProtocolVersion version) {
for (SignatureScheme ss : schemes) {
if (ss.isAvailable &&
ss.handshakeSupportedProtocols.contains(version) &&
! certScheme.keyAlgorithm.equalsIgnoreCase(ss.keyAlgorithm) &&
! ss.isPermitted(constraints)) {
return ss;
}
}
return null;
}
static Map.Entry<SignatureScheme, Signature> getSignerOfPreferableAlgorithm(
+ AlgorithmConstraints constraints,
List<SignatureScheme> schemes,
X509Possession x509Possession,
ProtocolVersion version) {
PrivateKey signingKey = x509Possession.popPrivateKey;
*** 465,477 ****
keySize = Integer.MAX_VALUE;
}
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)) {
ECParameterSpec params =
x509Possession.getECParameterSpec();
if (params != null &&
ss.namedGroup == NamedGroup.valueOf(params)) {
Signature signer = ss.getSigner(signingKey);
--- 477,490 ----
keySize = Integer.MAX_VALUE;
}
for (SignatureScheme ss : schemes) {
if (ss.isAvailable && (keySize >= ss.minimalKeySize) &&
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)) {
Signature signer = ss.getSigner(signingKey);
*** 550,560 ****
if (!isAvailable) {
return null;
}
Signature verifier = Signature.getInstance(algorithm);
! SignatureUtil.initVerifyWithParam(verifier, publicKey, signAlgParameter);
return verifier;
}
// This method is also used to choose preferable signature scheme for the
--- 563,575 ----
if (!isAvailable) {
return null;
}
Signature verifier = Signature.getInstance(algorithm);
! SignatureUtil.initVerifyWithParam(verifier, publicKey,
! (signAlgParams != null ?
! signAlgParams.parameterSpec : null));
return verifier;
}
// This method is also used to choose preferable signature scheme for the
*** 567,577 ****
}
try {
Signature signer = Signature.getInstance(algorithm);
SignatureUtil.initSignWithParam(signer, privateKey,
! signAlgParameter,
null);
return signer;
} catch (NoSuchAlgorithmException | InvalidKeyException |
InvalidAlgorithmParameterException nsae) {
if (SSLLogger.isOn &&
--- 582,593 ----
}
try {
Signature signer = Signature.getInstance(algorithm);
SignatureUtil.initSignWithParam(signer, privateKey,
! (signAlgParams != null ?
! signAlgParams.parameterSpec : null),
null);
return signer;
} catch (NoSuchAlgorithmException | InvalidKeyException |
InvalidAlgorithmParameterException nsae) {
if (SSLLogger.isOn &&
< prev index next >