This is an automated email from the ASF dual-hosted git repository. remm pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit f1a29de7da3dd0d9053038e97cb151b000ac1887 Author: remm <[email protected]> AuthorDate: Thu Sep 11 11:58:00 2025 +0200 Rename SignatureAlgorithm enum to SignatureScheme From https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml Although many use SignatureAlgorithm for this, this one is supposed to be quite like our Authentication enum (which I am not renaming). Allow specifying a certificate for ED(25519 and 448) since apparently it is different from ECDSA, it replaces DSA. Make MLKEM groups uppercase. --- .../tomcat/util/net/AbstractJsseEndpoint.java | 15 +++--- .../tomcat/util/net/SSLHostConfigCertificate.java | 8 +-- .../apache/tomcat/util/net/SecureNioChannel.java | 10 ++-- .../tomcat/util/net/TLSClientHelloExtractor.java | 20 ++++---- .../util/net/openssl/ciphers/Authentication.java | 1 + .../tomcat/util/net/openssl/ciphers/Group.java | 6 +-- ...ignatureAlgorithm.java => SignatureScheme.java} | 57 +++++++++++++--------- 7 files changed, 64 insertions(+), 53 deletions(-) diff --git a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java index 9b1690edc8..874da515fb 100644 --- a/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java +++ b/java/org/apache/tomcat/util/net/AbstractJsseEndpoint.java @@ -32,13 +32,14 @@ import org.apache.tomcat.util.compat.JreCompat; import org.apache.tomcat.util.net.openssl.OpenSSLStatus; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; import org.apache.tomcat.util.net.openssl.ciphers.Group; -import org.apache.tomcat.util.net.openssl.ciphers.SignatureAlgorithm; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; public abstract class AbstractJsseEndpoint<S, U> extends AbstractEndpoint<S,U> { + // Thread local use to pass additional arguments to createSSLEngine without changing the protected method signature static final ThreadLocal<List<String>> clientRequestedProtocolsThreadLocal = new ThreadLocal<>(); static final ThreadLocal<List<Group>> clientSupportedGroupsThreadLocal = new ThreadLocal<>(); - static final ThreadLocal<List<SignatureAlgorithm>> clientSignatureAlgorithmsThreadLocal = new ThreadLocal<>(); + static final ThreadLocal<List<SignatureScheme>> clientSignatureSchemesThreadLocal = new ThreadLocal<>(); private String sslImplementationName = null; private int sniParseLimit = 64 * 1024; @@ -128,12 +129,12 @@ public abstract class AbstractJsseEndpoint<S, U> extends AbstractEndpoint<S,U> { List<String> clientRequestedApplicationProtocols) { List<String> clientRequestedProtocols = clientRequestedProtocolsThreadLocal.get(); List<Group> clientSupportedGroups = clientSupportedGroupsThreadLocal.get(); - List<SignatureAlgorithm> clientSignatureAlgorithms = clientSignatureAlgorithmsThreadLocal.get(); + List<SignatureScheme> clientSignatureSchemes = clientSignatureSchemesThreadLocal.get(); SSLHostConfig sslHostConfig = getSSLHostConfig(sniHostName); SSLHostConfigCertificate certificate = selectCertificate(sslHostConfig, clientRequestedCiphers, - clientRequestedProtocols, clientSignatureAlgorithms); + clientRequestedProtocols, clientSignatureSchemes); SSLContext sslContext = certificate.getSslContext(); if (sslContext == null) { @@ -197,7 +198,7 @@ public abstract class AbstractJsseEndpoint<S, U> extends AbstractEndpoint<S,U> { private SSLHostConfigCertificate selectCertificate(SSLHostConfig sslHostConfig, List<Cipher> clientCiphers, - List<String> clientRequestedProtocols, List<SignatureAlgorithm> clientSignatureAlgorithms) { + List<String> clientRequestedProtocols, List<SignatureScheme> clientSignatureSchemes) { Set<SSLHostConfigCertificate> certificates = sslHostConfig.getCertificates(true); if (certificates.size() == 1) { @@ -207,9 +208,9 @@ public abstract class AbstractJsseEndpoint<S, U> extends AbstractEndpoint<S,U> { // Use signature algorithm for cipher matching with TLS 1.3 if ((clientRequestedProtocols.contains(Constants.SSL_PROTO_TLSv1_3)) && sslHostConfig.getProtocols().contains(Constants.SSL_PROTO_TLSv1_3)) { - for (SignatureAlgorithm signatureAlgorithm : clientSignatureAlgorithms) { + for (SignatureScheme signatureScheme : clientSignatureSchemes) { for (SSLHostConfigCertificate certificate : certificates) { - if (certificate.getType().isCompatibleWith(signatureAlgorithm)) { + if (certificate.getType().isCompatibleWith(signatureScheme)) { return certificate; } } diff --git a/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java b/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java index b7606dd89b..f41fa2d017 100644 --- a/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java +++ b/java/org/apache/tomcat/util/net/SSLHostConfigCertificate.java @@ -30,7 +30,7 @@ import javax.net.ssl.X509KeyManager; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.net.openssl.ciphers.Authentication; -import org.apache.tomcat.util.net.openssl.ciphers.SignatureAlgorithm; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; public class SSLHostConfigCertificate implements Serializable { @@ -317,7 +317,7 @@ public class SSLHostConfigCertificate implements Serializable { UNDEFINED, RSA(Authentication.RSA), - DSA(Authentication.DSS), + DSA(Authentication.DSS, Authentication.EdDSA), EC(Authentication.ECDH, Authentication.ECDSA), MLDSA(Authentication.MLDSA); @@ -334,8 +334,8 @@ public class SSLHostConfigCertificate implements Serializable { return compatibleAuthentications.contains(au); } - public boolean isCompatibleWith(SignatureAlgorithm al) { - return al.toString().toUpperCase().startsWith(toString()); + public boolean isCompatibleWith(SignatureScheme scheme) { + return compatibleAuthentications.contains(scheme.getAuth()); } } diff --git a/java/org/apache/tomcat/util/net/SecureNioChannel.java b/java/org/apache/tomcat/util/net/SecureNioChannel.java index 184216e2aa..92c4da0907 100644 --- a/java/org/apache/tomcat/util/net/SecureNioChannel.java +++ b/java/org/apache/tomcat/util/net/SecureNioChannel.java @@ -43,7 +43,7 @@ import org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper; import org.apache.tomcat.util.net.TLSClientHelloExtractor.ExtractorResult; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; import org.apache.tomcat.util.net.openssl.ciphers.Group; -import org.apache.tomcat.util.net.openssl.ciphers.SignatureAlgorithm; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; /** @@ -277,7 +277,7 @@ public class SecureNioChannel extends NioChannel { List<Cipher> clientRequestedCiphers = null; List<String> clientRequestedApplicationProtocols = null; List<Group> clientSupportedGroups = null; - List<SignatureAlgorithm> clientSignatureAlgorithms = null; + List<SignatureScheme> clientSignatureSchemes = null; switch (extractor.getResult()) { case COMPLETE: hostName = extractor.getSNIValue(); @@ -286,7 +286,7 @@ public class SecureNioChannel extends NioChannel { case NOT_PRESENT: clientRequestedCiphers = extractor.getClientRequestedCiphers(); clientSupportedGroups = extractor.getClientSupportedGroups(); - clientSignatureAlgorithms = extractor.getClientSignatureAlgorithms(); + clientSignatureSchemes = extractor.getClientSignatureSchemes(); break; case NEED_READ: return SelectionKey.OP_READ; @@ -313,12 +313,12 @@ public class SecureNioChannel extends NioChannel { try { AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(extractor.getClientRequestedProtocols()); AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(clientSupportedGroups); - AbstractJsseEndpoint.clientSignatureAlgorithmsThreadLocal.set(clientSignatureAlgorithms); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(clientSignatureSchemes); sslEngine = endpoint.createSSLEngine(hostName, clientRequestedCiphers, clientRequestedApplicationProtocols); } finally { AbstractJsseEndpoint.clientRequestedProtocolsThreadLocal.set(null); AbstractJsseEndpoint.clientSupportedGroupsThreadLocal.set(null); - AbstractJsseEndpoint.clientSignatureAlgorithmsThreadLocal.set(null); + AbstractJsseEndpoint.clientSignatureSchemesThreadLocal.set(null); } // Populate additional TLS attributes obtained from the handshake that diff --git a/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java b/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java index ed153c87da..0f26b2799d 100644 --- a/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java +++ b/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java @@ -30,7 +30,7 @@ import org.apache.tomcat.util.buf.HexUtils; import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.openssl.ciphers.Cipher; import org.apache.tomcat.util.net.openssl.ciphers.Group; -import org.apache.tomcat.util.net.openssl.ciphers.SignatureAlgorithm; +import org.apache.tomcat.util.net.openssl.ciphers.SignatureScheme; import org.apache.tomcat.util.res.StringManager; /** @@ -48,7 +48,7 @@ public class TLSClientHelloExtractor { private final List<String> clientRequestedApplicationProtocols; private final List<String> clientRequestedProtocols; private final List<Group> clientSupportedGroups; - private final List<SignatureAlgorithm> clientSignatureAlgorithms; + private final List<SignatureScheme> clientSignatureSchemes; private static final int TLS_RECORD_HEADER_LEN = 5; @@ -84,7 +84,7 @@ public class TLSClientHelloExtractor { List<String> clientRequestedApplicationProtocols = new ArrayList<>(); List<String> clientRequestedProtocols = new ArrayList<>(); List<Group> clientSupportedGroups = new ArrayList<>(); - List<SignatureAlgorithm> clientSignatureAlgorithms = new ArrayList<>(); + List<SignatureScheme> clientSignatureSchemes = new ArrayList<>(); String sniValue = null; try { // Switch to read mode. @@ -170,7 +170,7 @@ public class TLSClientHelloExtractor { readSupportedGroups(netInBuffer, clientSupportedGroups); break; case TLS_EXTENSION_SIGNATURE_ALGORITHMS: - readSignatureAlgorithms(netInBuffer, clientSignatureAlgorithms); + readSignatureAlgorithms(netInBuffer, clientSignatureSchemes); break; case TLS_EXTENSION_ALPN: readAlpnExtension(netInBuffer, clientRequestedApplicationProtocols); @@ -197,12 +197,12 @@ public class TLSClientHelloExtractor { this.sniValue = sniValue; this.clientRequestedProtocols = clientRequestedProtocols; this.clientSupportedGroups = clientSupportedGroups; - this.clientSignatureAlgorithms = clientSignatureAlgorithms; + this.clientSignatureSchemes = clientSignatureSchemes; if (log.isTraceEnabled()) { log.trace("TLS Client Hello: " + clientRequestedCiphers + " Names " + clientRequestedCipherNames + " Protocols " + clientRequestedApplicationProtocols + " sniValue " + sniValue + " clientRequestedProtocols " + clientRequestedProtocols + " clientSupportedGroups " + clientSupportedGroups + - " clientSignatureAlgorithms " + clientSignatureAlgorithms); + " clientSignatureSchemes " + clientSignatureSchemes); } // Whatever happens, return the buffer to its original state netInBuffer.limit(limit); @@ -273,9 +273,9 @@ public class TLSClientHelloExtractor { } - public List<SignatureAlgorithm> getClientSignatureAlgorithms() { + public List<SignatureScheme> getClientSignatureSchemes() { if (result == ExtractorResult.COMPLETE || result == ExtractorResult.NOT_PRESENT) { - return clientSignatureAlgorithms; + return clientSignatureSchemes; } else { throw new IllegalStateException(sm.getString("sniExtractor.tooEarly")); } @@ -478,13 +478,13 @@ public class TLSClientHelloExtractor { } - private static void readSignatureAlgorithms(ByteBuffer bb, List<SignatureAlgorithm> signatureAlgorithms) { + private static void readSignatureAlgorithms(ByteBuffer bb, List<SignatureScheme> signatureAlgorithms) { // First 2 bytes are size of the signature algorithm list int toRead = bb.getChar() / 2; // Then the list of protocols for (int i = 0; i < toRead; i++) { char id = bb.getChar(); - SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.valueOf(id); + SignatureScheme signatureAlgorithm = SignatureScheme.valueOf(id); if (signatureAlgorithm != null) { signatureAlgorithms.add(signatureAlgorithm); } diff --git a/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java b/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java index 052808a36b..91a859000d 100644 --- a/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java +++ b/java/org/apache/tomcat/util/net/openssl/ciphers/Authentication.java @@ -29,6 +29,7 @@ public enum Authentication { GOST01 /* GOST R 34.10-2001 */, FZA /* Fortezza */, SRP /* Secure Remote Password */, + EdDSA /* EdDSA */, MLDSA /* ML-DSA */, ANY /* TLS 1.3 */ } diff --git a/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java b/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java index 801fe80095..a85f757be7 100644 --- a/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java +++ b/java/org/apache/tomcat/util/net/openssl/ciphers/Group.java @@ -36,9 +36,9 @@ public enum Group { ffdhe8192(0x0104), // Post-Quantum Key Exchange - mlkem512(0x0200), - mlkem768(0x0201), - mlkem1024(0x0202), + MLKEM512(0x0200), + MLKEM768(0x0201), + MLKEM1024(0x0202), // Hybrid Key Exchange SecP256r1MLKEM768(0x11EB), diff --git a/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureAlgorithm.java b/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java similarity index 53% rename from java/org/apache/tomcat/util/net/openssl/ciphers/SignatureAlgorithm.java rename to java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java index 7b2f94f3f6..d5df3f72fa 100644 --- a/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureAlgorithm.java +++ b/java/org/apache/tomcat/util/net/openssl/ciphers/SignatureScheme.java @@ -19,45 +19,47 @@ package org.apache.tomcat.util.net.openssl.ciphers; import java.util.HashMap; import java.util.Map; -public enum SignatureAlgorithm { +public enum SignatureScheme { // RSASSA-PKCS1-v1_5 algorithms - rsa_pkcs1_sha256(0x0401), - rsa_pkcs1_sha384(0x0501), - rsa_pkcs1_sha512(0x0601), + rsa_pkcs1_sha256(0x0401, Authentication.RSA), + rsa_pkcs1_sha384(0x0501, Authentication.RSA), + rsa_pkcs1_sha512(0x0601, Authentication.RSA), // ECDSA algorithms - ecdsa_secp256r1_sha256(0x0403), - ecdsa_secp384r1_sha384(0x0503), - ecdsa_secp521r1_sha512(0x0603), + ecdsa_secp256r1_sha256(0x0403, Authentication.ECDSA), + ecdsa_secp384r1_sha384(0x0503, Authentication.ECDSA), + ecdsa_secp521r1_sha512(0x0603, Authentication.ECDSA), // RSASSA-PSS algorithms with public key OID rsaEncryption - rsa_pss_rsae_sha256(0x0804), - rsa_pss_rsae_sha384(0x0805), - rsa_pss_rsae_sha512(0x0806), + rsa_pss_rsae_sha256(0x0804, Authentication.RSA), + rsa_pss_rsae_sha384(0x0805, Authentication.RSA), + rsa_pss_rsae_sha512(0x0806, Authentication.RSA), // EdDSA algorithms - ed25519(0x0807), - ed448(0x0808), + ed25519(0x0807, Authentication.EdDSA), + ed448(0x0808, Authentication.EdDSA), // RSASSA-PSS algorithms with public key OID RSASSA-PSS - rsa_pss_pss_sha256(0x0809), - rsa_pss_pss_sha384(0x080a), - rsa_pss_pss_sha512(0x080b), + rsa_pss_pss_sha256(0x0809, Authentication.RSA), + rsa_pss_pss_sha384(0x080a, Authentication.RSA), + rsa_pss_pss_sha512(0x080b, Authentication.RSA), // Legacy algorithms - rsa_pkcs1_sha1(0x0201), - ecdsa_sha1(0x0203), + rsa_pkcs1_sha1(0x0201, Authentication.RSA), + ecdsa_sha1(0x0203, Authentication.ECDSA), // ML-DSA algorithms - mldsa44(0x0904), - mldsa65(0x0905), - mldsa87(0x0906); + mldsa44(0x0904, Authentication.MLDSA), + mldsa65(0x0905, Authentication.MLDSA), + mldsa87(0x0906, Authentication.MLDSA); private final int id; + private final Authentication auth; - SignatureAlgorithm(int id) { + SignatureScheme(int id, Authentication auth) { this.id = id; + this.auth = auth; } /** @@ -67,10 +69,17 @@ public enum SignatureAlgorithm { return this.id; } - private static final Map<Integer,SignatureAlgorithm> idMap = new HashMap<>(); + /** + * @return the auth + */ + public Authentication getAuth() { + return this.auth; + } + + private static final Map<Integer,SignatureScheme> idMap = new HashMap<>(); static { - for (SignatureAlgorithm group : values()) { + for (SignatureScheme group : values()) { int id = group.getId(); if (id > 0 && id < 0xFFFF) { @@ -80,7 +89,7 @@ public enum SignatureAlgorithm { } - public static SignatureAlgorithm valueOf(int groupId) { + public static SignatureScheme valueOf(int groupId) { return idMap.get(Integer.valueOf(groupId)); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
