This is an automated email from the ASF dual-hosted git repository. acosentino pushed a commit to branch task-23 in repository https://gitbox.apache.org/repos/asf/camel.git
commit d85e2a3cac36670030290623d5c28d64b20c6897 Author: Andrea Cosentino <[email protected]> AuthorDate: Fri Mar 6 10:32:07 2026 +0100 CAMEL-23154 - Post-Quantum Cryptography (PQC) readiness: Add namedGroups support to BaseSSLContextParameters Add namedGroups and namedGroupsFilter fields to BaseSSLContextParameters, following the existing cipherSuites/cipherSuitesFilter pattern. This allows users to configure TLS named groups (key exchange algorithms) including post-quantum hybrid groups such as X25519MLKEM768. Changes: - Add NamedGroupsParameters class mirroring CipherSuitesParameters - Add namedGroups (NamedGroupsParameters) and namedGroupsFilter (FilterParameters) fields with getters/setters - Update SSLEngine, SSLSocket, and SSLServerSocket configurers to call SSLParameters.setNamedGroups() with configured or filtered values - Add configureNamedGroups() helper shared by all three configurers - Add debug log messages for named groups configuration Signed-off-by: Andrea Cosentino <[email protected]> --- .../support/jsse/BaseSSLContextParameters.java | 180 +++++++++++++++++++++ .../camel/support/jsse/NamedGroupsParameters.java | 66 ++++++++ 2 files changed, 246 insertions(+) diff --git a/core/camel-api/src/main/java/org/apache/camel/support/jsse/BaseSSLContextParameters.java b/core/camel-api/src/main/java/org/apache/camel/support/jsse/BaseSSLContextParameters.java index c7fe6d8ce233..0d00bbaa3010 100644 --- a/core/camel-api/src/main/java/org/apache/camel/support/jsse/BaseSSLContextParameters.java +++ b/core/camel-api/src/main/java/org/apache/camel/support/jsse/BaseSSLContextParameters.java @@ -83,6 +83,12 @@ public abstract class BaseSSLContextParameters extends JsseParameters { private static final String SSL_SERVER_SOCKET_PROTOCOL_LOG_MSG = createProtocolLogMessage("SSLServerSocket"); + private static final String SSL_ENGINE_NAMED_GROUP_LOG_MSG = createNamedGroupLogMessage("SSLEngine"); + + private static final String SSL_SOCKET_NAMED_GROUP_LOG_MSG = createNamedGroupLogMessage("SSLSocket"); + + private static final String SSL_SERVER_SOCKET_NAMED_GROUP_LOG_MSG = createNamedGroupLogMessage("SSLServerSocket"); + /** * The optional explicitly configured cipher suites for this configuration. */ @@ -103,6 +109,18 @@ public abstract class BaseSSLContextParameters extends JsseParameters { */ private FilterParameters secureSocketProtocolsFilter; + /** + * The optional explicitly configured named groups (key exchange groups) for this configuration. Named groups + * control which key exchange algorithms are available during the TLS handshake, including post-quantum hybrid + * groups such as X25519MLKEM768. + */ + private NamedGroupsParameters namedGroups; + + /** + * The optional named groups filter configuration for this configuration. + */ + private FilterParameters namedGroupsFilter; + /** * The optional {@link SSLSessionContext} timeout time for {@link javax.net.ssl.SSLSession}s in seconds. */ @@ -210,6 +228,62 @@ public abstract class BaseSSLContextParameters extends JsseParameters { this.secureSocketProtocolsFilter = secureSocketProtocolsFilter; } + /** + * Returns the optional explicitly configured named groups for this configuration. These options are used in the + * configuration of {@link SSLEngine}, {@link SSLSocketFactory} and {@link SSLServerSocketFactory} depending on the + * context in which they are applied. + * <p/> + * Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum + * hybrid groups such as {@code X25519MLKEM768}. + * <p/> + * These values override any filters supplied in {@link #setNamedGroupsFilter(FilterParameters)} + */ + public NamedGroupsParameters getNamedGroups() { + return namedGroups; + } + + /** + * Sets the optional explicitly configured named groups for this configuration. These options are used in the + * configuration of {@link SSLEngine}, {@link SSLSocketFactory} and {@link SSLServerSocketFactory} depending on the + * context in which they are applied. + * <p/> + * Named groups control which key exchange algorithms are available during the TLS handshake, including post-quantum + * hybrid groups such as {@code X25519MLKEM768}. + * <p/> + * These values override any filters supplied in {@link #setNamedGroupsFilter(FilterParameters)} + * + * @param namedGroups the named groups configuration + */ + public void setNamedGroups(NamedGroupsParameters namedGroups) { + this.namedGroups = namedGroups; + } + + /** + * Returns the optional named groups filter for this configuration. These options are used in the configuration of + * {@link SSLEngine}, {@link SSLSocketFactory} and {@link SSLServerSocketFactory} depending on the context in which + * they are applied. + * <p/> + * These values are ignored if {@link #setNamedGroups(NamedGroupsParameters)} is called with a non {@code null} + * argument. + */ + public FilterParameters getNamedGroupsFilter() { + return namedGroupsFilter; + } + + /** + * Sets the optional named groups filter for this JSSE configuration. These options are used in the configuration of + * {@link SSLEngine}, {@link SSLSocketFactory} and {@link SSLServerSocketFactory} depending on the context in which + * they are applied. + * <p/> + * These values are ignored if {@link #setNamedGroups(NamedGroupsParameters)} is called with a non {@code null} + * argument. + * + * @param namedGroupsFilter the filter configuration + */ + public void setNamedGroupsFilter(FilterParameters namedGroupsFilter) { + this.namedGroupsFilter = namedGroupsFilter; + } + /** * Returns the optional {@link SSLSessionContext} timeout time for {@link javax.net.ssl.SSLSession}s in seconds. */ @@ -314,6 +388,17 @@ public abstract class BaseSSLContextParameters extends JsseParameters { enabledSecureSocketProtocolsPatterns = null; } + final List<String> enabledNamedGroups = this.getNamedGroups() == null + ? null : this.parsePropertyValues(this.getNamedGroups().getNamedGroup()); + + final Patterns enabledNamedGroupsPatterns; + + if (this.getNamedGroupsFilter() != null) { + enabledNamedGroupsPatterns = this.getNamedGroupsFilter().getPatterns(); + } else { + enabledNamedGroupsPatterns = null; + } + // final boolean allowPassthrough = getAllowPassthrough(); @@ -364,6 +449,9 @@ public abstract class BaseSSLContextParameters extends JsseParameters { engine.setEnabledProtocols( filteredSecureSocketProtocols.toArray(new String[0])); + configureNamedGroups(engine.getSSLParameters(), enabledNamedGroups, enabledNamedGroupsPatterns, + engine, SSL_ENGINE_NAMED_GROUP_LOG_MSG); + return engine; } }; @@ -479,6 +567,17 @@ public abstract class BaseSSLContextParameters extends JsseParameters { enabledSecureSocketProtocolsPatterns = null; } + final List<String> enabledNamedGroups = this.getNamedGroups() == null + ? null : this.parsePropertyValues(this.getNamedGroups().getNamedGroup()); + + final Patterns enabledNamedGroupsPatterns; + + if (this.getNamedGroupsFilter() != null) { + enabledNamedGroupsPatterns = this.getNamedGroupsFilter().getPatterns(); + } else { + enabledNamedGroupsPatterns = null; + } + // final boolean allowPassthrough = getAllowPassthrough(); @@ -533,6 +632,10 @@ public abstract class BaseSSLContextParameters extends JsseParameters { socket.setEnabledProtocols( filteredSecureSocketProtocols.toArray(new String[0])); + + configureNamedGroups(socket.getSSLParameters(), enabledNamedGroups, enabledNamedGroupsPatterns, + socket, SSL_SOCKET_NAMED_GROUP_LOG_MSG); + return socket; } }; @@ -578,6 +681,17 @@ public abstract class BaseSSLContextParameters extends JsseParameters { enabledSecureSocketProtocolsPatterns = null; } + final List<String> enabledNamedGroups = this.getNamedGroups() == null + ? null : this.parsePropertyValues(this.getNamedGroups().getNamedGroup()); + + final Patterns enabledNamedGroupsPatterns; + + if (this.getNamedGroupsFilter() != null) { + enabledNamedGroupsPatterns = this.getNamedGroupsFilter().getPatterns(); + } else { + enabledNamedGroupsPatterns = null; + } + // final boolean allowPassthrough = getAllowPassthrough(); @@ -627,6 +741,10 @@ public abstract class BaseSSLContextParameters extends JsseParameters { socket.setEnabledProtocols( filteredSecureSocketProtocols.toArray(new String[0])); + + configureNamedGroups(socket.getSSLParameters(), enabledNamedGroups, enabledNamedGroupsPatterns, + socket, SSL_SERVER_SOCKET_NAMED_GROUP_LOG_MSG); + return socket; } }; @@ -768,6 +886,60 @@ public abstract class BaseSSLContextParameters extends JsseParameters { return matches; } + /** + * Configures named groups on an {@link SSLParameters} instance. If explicit named groups are provided, those are + * used directly. Otherwise, if a named groups filter is configured, the available named groups from the current + * SSLParameters are filtered according to the include/exclude patterns. + * + * @param sslParameters the current SSL parameters to read available named groups from + * @param enabledNamedGroups the optional explicit named groups list + * @param enabledNamedGroupsPatterns the optional filter patterns + * @param target the SSL object (engine, socket, or server socket) to configure + * @param logMessage the log message template + */ + private void configureNamedGroups( + SSLParameters sslParameters, List<String> enabledNamedGroups, + Patterns enabledNamedGroupsPatterns, Object target, String logMessage) { + + if (enabledNamedGroups == null && enabledNamedGroupsPatterns == null) { + return; + } + + String[] currentNamedGroups = sslParameters.getNamedGroups(); + if (currentNamedGroups == null) { + currentNamedGroups = new String[0]; + } + + Collection<String> filteredNamedGroups; + if (enabledNamedGroups != null) { + filteredNamedGroups = new ArrayList<>(enabledNamedGroups); + } else { + filteredNamedGroups = this.filter( + null, Arrays.asList(currentNamedGroups), + enabledNamedGroupsPatterns.getIncludes(), enabledNamedGroupsPatterns.getExcludes()); + } + + if (LOG.isDebugEnabled()) { + LOG.debug(logMessage, + target, + enabledNamedGroups, + enabledNamedGroupsPatterns, + currentNamedGroups, + filteredNamedGroups); + } + + SSLParameters updatedParams = sslParameters; + updatedParams.setNamedGroups(filteredNamedGroups.toArray(new String[0])); + + if (target instanceof SSLEngine engine) { + engine.setSSLParameters(updatedParams); + } else if (target instanceof SSLSocket socket) { + socket.setSSLParameters(updatedParams); + } else if (target instanceof SSLServerSocket serverSocket) { + serverSocket.setSSLParameters(updatedParams); + } + } + /** * Configures a {@code T} based on the related configuration options. */ @@ -1106,4 +1278,12 @@ public abstract class BaseSSLContextParameters extends JsseParameters { + "\t and default protocol patterns [{}]." + LS + "\t Resulting enabled protocols are [{}]."; } + + private static String createNamedGroupLogMessage(String entityName) { + return "Configuring " + entityName + " [{}] with " + LS + + "\t explicitly set named groups [{}]," + LS + + "\t named group patterns [{}]," + LS + + "\t available named groups [{}]," + LS + + "\t Resulting enabled named groups are [{}]."; + } } diff --git a/core/camel-api/src/main/java/org/apache/camel/support/jsse/NamedGroupsParameters.java b/core/camel-api/src/main/java/org/apache/camel/support/jsse/NamedGroupsParameters.java new file mode 100644 index 000000000000..760778618d72 --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/support/jsse/NamedGroupsParameters.java @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.support.jsse; + +import java.util.ArrayList; +import java.util.List; + +/** + * Represents a list of TLS/SSL named groups (also known as elliptic curves or key exchange groups) for use in TLS + * handshakes. Named groups control which key exchange algorithms are available during the TLS handshake, including + * post-quantum hybrid groups such as {@code X25519MLKEM768}. + */ +public class NamedGroupsParameters { + private List<String> namedGroup; + + /** + * Returns a live reference to the list of named group names. + * + * @return a reference to the list, never {@code null} + */ + public List<String> getNamedGroup() { + if (this.namedGroup == null) { + this.namedGroup = new ArrayList<>(); + } + return this.namedGroup; + } + + public void addNamedGroup(String group) { + if (this.namedGroup == null) { + this.namedGroup = new ArrayList<>(); + } + this.namedGroup.add(group.trim()); + } + + /** + * Sets the named groups. It creates a copy of the given list. + * + * @param namedGroup named groups + */ + public void setNamedGroup(List<String> namedGroup) { + this.namedGroup = namedGroup == null ? null : new ArrayList<>(namedGroup); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("NamedGroupsParameters[namedGroup="); + builder.append(getNamedGroup()); + builder.append("]"); + return builder.toString(); + } +}
