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();
+    }
+}

Reply via email to