8242141: New System Properties to configure the TLS signature schemes

Reviewed-by: ascarpino, jnimeh, mullan
This commit is contained in:
Xue-Lei Andrew Fan 2020-04-22 10:51:16 -07:00
parent 5efa545d48
commit 72446bb0dc
12 changed files with 233 additions and 6 deletions

View file

@ -100,6 +100,7 @@ final class CertSignAlgsExtension {
if (chc.localSupportedSignAlgs == null) {
chc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
chc.sslConfig,
chc.algorithmConstraints, chc.activeProtocols);
}
@ -188,6 +189,7 @@ final class CertSignAlgsExtension {
// update the context
List<SignatureScheme> schemes =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.negotiatedProtocol,
spec.signatureSchemes);
shc.peerRequestedCertSignSchemes = schemes;
@ -240,6 +242,7 @@ final class CertSignAlgsExtension {
// Produce the extension.
List<SignatureScheme> sigAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints,
List.of(shc.negotiatedProtocol));
@ -326,6 +329,7 @@ final class CertSignAlgsExtension {
// update the context
List<SignatureScheme> schemes =
SignatureScheme.getSupportedAlgorithms(
chc.sslConfig,
chc.algorithmConstraints, chc.negotiatedProtocol,
spec.signatureSchemes);
chc.peerRequestedCertSignSchemes = schemes;

View file

@ -601,6 +601,7 @@ final class CertificateRequest {
if (shc.localSupportedSignAlgs == null) {
shc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.activeProtocols);
}

View file

@ -448,6 +448,7 @@ final class PreSharedKeyExtension {
if (shc.localSupportedSignAlgs == null) {
shc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.activeProtocols);
}

View file

@ -43,6 +43,7 @@ import javax.net.ssl.SNIServerName;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLSocket;
import sun.security.action.GetPropertyAction;
import sun.security.ssl.SSLExtension.ClientExtensions;
import sun.security.ssl.SSLExtension.ServerExtensions;
@ -63,6 +64,10 @@ final class SSLConfiguration implements Cloneable {
boolean enableRetransmissions;
int maximumPacketSize;
// The configured signature schemes for "signature_algorithms" and
// "signature_algorithms_cert" extensions
List<SignatureScheme> signatureSchemes;
// the maximum protocol version of enabled protocols
ProtocolVersion maximumProtocolVersion;
@ -133,6 +138,9 @@ final class SSLConfiguration implements Cloneable {
this.enableRetransmissions = sslContext.isDTLS();
this.maximumPacketSize = 0; // please reset it explicitly later
this.signatureSchemes = isClientMode ?
CustomizedClientSignatureSchemes.signatureSchemes :
CustomizedServerSignatureSchemes.signatureSchemes;
this.maximumProtocolVersion = ProtocolVersion.NONE;
for (ProtocolVersion pv : enabledProtocols) {
if (pv.compareTo(maximumProtocolVersion) > 0) {
@ -383,6 +391,15 @@ final class SSLConfiguration implements Cloneable {
return extensions.toArray(new SSLExtension[0]);
}
void toggleClientMode() {
this.isClientMode ^= true;
// reset the signature schemes
this.signatureSchemes = isClientMode ?
CustomizedClientSignatureSchemes.signatureSchemes :
CustomizedServerSignatureSchemes.signatureSchemes;
}
@Override
@SuppressWarnings({"unchecked", "CloneDeclaresCloneNotSupported"})
public Object clone() {
@ -402,4 +419,72 @@ final class SSLConfiguration implements Cloneable {
return null; // unlikely
}
// lazy initialization holder class idiom for static default parameters
//
// See Effective Java Second Edition: Item 71.
private static final class CustomizedClientSignatureSchemes {
private static List<SignatureScheme> signatureSchemes =
getCustomizedSignatureScheme("jdk.tls.client.SignatureSchemes");
}
// lazy initialization holder class idiom for static default parameters
//
// See Effective Java Second Edition: Item 71.
private static final class CustomizedServerSignatureSchemes {
private static List<SignatureScheme> signatureSchemes =
getCustomizedSignatureScheme("jdk.tls.server.SignatureSchemes");
}
/*
* Get the customized signature schemes specified by the given
* system property.
*/
private static List<SignatureScheme> getCustomizedSignatureScheme(
String propertyName) {
String property = GetPropertyAction.privilegedGetProperty(propertyName);
if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
SSLLogger.fine(
"System property " + propertyName + " is set to '" +
property + "'");
}
if (property != null && !property.isEmpty()) {
// remove double quote marks from beginning/end of the property
if (property.length() > 1 && property.charAt(0) == '"' &&
property.charAt(property.length() - 1) == '"') {
property = property.substring(1, property.length() - 1);
}
}
if (property != null && !property.isEmpty()) {
String[] signatureSchemeNames = property.split(",");
List<SignatureScheme> signatureSchemes =
new ArrayList<>(signatureSchemeNames.length);
for (int i = 0; i < signatureSchemeNames.length; i++) {
signatureSchemeNames[i] = signatureSchemeNames[i].trim();
if (signatureSchemeNames[i].isEmpty()) {
continue;
}
SignatureScheme scheme =
SignatureScheme.nameOf(signatureSchemeNames[i]);
if (scheme != null && scheme.isAvailable) {
signatureSchemes.add(scheme);
} else {
if (SSLLogger.isOn && SSLLogger.isOn("ssl,sslctx")) {
SSLLogger.fine(
"The current installed providers do not " +
"support signature scheme: " +
signatureSchemeNames[i]);
}
}
}
return signatureSchemes;
}
return Collections.emptyList();
}
}

View file

@ -64,7 +64,6 @@ final class SSLServerSocketImpl extends SSLServerSocket {
super();
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
SSLServerSocketImpl(SSLContextImpl sslContext,
@ -73,7 +72,6 @@ final class SSLServerSocketImpl extends SSLServerSocket {
super(port, backlog);
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
SSLServerSocketImpl(SSLContextImpl sslContext,
@ -82,7 +80,6 @@ final class SSLServerSocketImpl extends SSLServerSocket {
super(port, backlog, address);
this.sslContext = sslContext;
this.sslConfig = new SSLConfiguration(sslContext, false);
this.sslConfig.isClientMode = false;
}
@Override
@ -210,7 +207,7 @@ final class SSLServerSocketImpl extends SSLServerSocket {
sslContext.getDefaultCipherSuites(!useClientMode);
}
sslConfig.isClientMode = useClientMode;
sslConfig.toggleClientMode();
}
} finally {
serverSocketLock.unlock();

View file

@ -277,6 +277,7 @@ final class ServerHello {
if (shc.localSupportedSignAlgs == null) {
shc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.activeProtocols);
}
@ -517,6 +518,7 @@ final class ServerHello {
if (shc.localSupportedSignAlgs == null) {
shc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.activeProtocols);
}

View file

@ -412,6 +412,7 @@ final class SessionTicketExtension {
if (chc.localSupportedSignAlgs == null) {
chc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
chc.sslConfig,
chc.algorithmConstraints, chc.activeProtocols);
}

View file

@ -189,6 +189,7 @@ final class SignatureAlgorithmsExtension {
if (chc.localSupportedSignAlgs == null) {
chc.localSupportedSignAlgs =
SignatureScheme.getSupportedAlgorithms(
chc.sslConfig,
chc.algorithmConstraints, chc.activeProtocols);
}
@ -276,6 +277,7 @@ final class SignatureAlgorithmsExtension {
// update the context
List<SignatureScheme> sss =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints, shc.negotiatedProtocol,
spec.signatureSchemes);
shc.peerRequestedSignatureSchemes = sss;
@ -409,6 +411,7 @@ final class SignatureAlgorithmsExtension {
// Produce the extension.
List<SignatureScheme> sigAlgs =
SignatureScheme.getSupportedAlgorithms(
shc.sslConfig,
shc.algorithmConstraints,
List.of(shc.negotiatedProtocol));
@ -504,6 +507,7 @@ final class SignatureAlgorithmsExtension {
// update the context
List<SignatureScheme> sss =
SignatureScheme.getSupportedAlgorithms(
chc.sslConfig,
chc.algorithmConstraints, chc.negotiatedProtocol,
spec.signatureSchemes);
chc.peerRequestedSignatureSchemes = sss;

View file

@ -339,6 +339,17 @@ enum SignatureScheme {
return signName + "_" + hashName;
}
// Note: the signatureSchemeName is not case-sensitive.
static SignatureScheme nameOf(String signatureSchemeName) {
for (SignatureScheme ss: SignatureScheme.values()) {
if (ss.name.equalsIgnoreCase(signatureSchemeName)) {
return ss;
}
}
return null;
}
// Return the size of a SignatureScheme structure in TLS record
static int sizeInRecord() {
return 2;
@ -359,11 +370,19 @@ enum SignatureScheme {
// Get local supported algorithm collection complying to algorithm
// constraints.
static List<SignatureScheme> getSupportedAlgorithms(
SSLConfiguration config,
AlgorithmConstraints constraints,
List<ProtocolVersion> activeProtocols) {
List<SignatureScheme> supported = new LinkedList<>();
for (SignatureScheme ss: SignatureScheme.values()) {
if (!ss.isAvailable) {
if (!ss.isAvailable ||
(!config.signatureSchemes.isEmpty() &&
!config.signatureSchemes.contains(ss))) {
if (SSLLogger.isOn &&
SSLLogger.isOn("ssl,handshake,verbose")) {
SSLLogger.finest(
"Ignore unsupported signature scheme: " + ss.name);
}
continue;
}
@ -394,6 +413,7 @@ enum SignatureScheme {
}
static List<SignatureScheme> getSupportedAlgorithms(
SSLConfiguration config,
AlgorithmConstraints constraints,
ProtocolVersion protocolVersion, int[] algorithmIds) {
List<SignatureScheme> supported = new LinkedList<>();
@ -407,6 +427,8 @@ enum SignatureScheme {
}
} else if (ss.isAvailable &&
ss.supportedProtocols.contains(protocolVersion) &&
(config.signatureSchemes.isEmpty() ||
config.signatureSchemes.contains(ss)) &&
ss.isPermitted(constraints)) {
supported.add(ss);
} else {

View file

@ -427,7 +427,7 @@ final class TransportContext implements ConnectionContext {
sslContext.getDefaultCipherSuites(!useClientMode);
}
sslConfig.isClientMode = useClientMode;
sslConfig.toggleClientMode();
}
isUnsureMode = false;