< 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 >