This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch camel-quarkus-main in repository https://gitbox.apache.org/repos/asf/camel-quarkus-examples.git
commit 816843a61ee070d5df27a1bc28ae20c3c45114fa Author: James Netherton <[email protected]> AuthorDate: Tue Nov 3 08:37:31 2026 +0000 Fix http-pqc PqcOnlyTest for JDK builds where SunJSSE supports X25519MLKEM768 SunJSSE supports X25519MLKEM768 on JDK 25.0.5, so an unrestricted client can connect to the PQC-only server. Restrict the SunJSSE client to classical named groups so that the test still proves clients not offering PQC are rejected. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- http-pqc/README.adoc | 4 ++-- .../test/java/org/acme/http/pqc/AbstractPqcTest.java | 18 +++++++++++++++--- .../src/test/java/org/acme/http/pqc/PqcOnlyTest.java | 12 +++++++----- .../java/org/acme/http/pqc/PqcWithFallbackTest.java | 2 +- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/http-pqc/README.adoc b/http-pqc/README.adoc index 09a8b3c9..00ef4e50 100644 --- a/http-pqc/README.adoc +++ b/http-pqc/README.adoc @@ -173,12 +173,12 @@ The test suite validates: * **PqcOnlyTest**: Proves X25519MLKEM768 is enforced - BCJSSE client ✓ succeeds (supports X25519MLKEM768) - - SunJSSE client ✗ fails (no PQC support) + - SunJSSE client restricted to classical named groups ✗ fails (no PQC support offered) - This proves the server requires PQC with no classical fallback * **PqcWithFallbackTest**: Demonstrates backward compatibility - BCJSSE client ✓ succeeds (uses X25519MLKEM768) - - SunJSSE client ✓ succeeds (falls back to secp256r1) + - SunJSSE client ✓ succeeds (falls back to a classical group on JDK builds without X25519MLKEM768 support) - This proves gradual migration is possible Run individual tests: diff --git a/http-pqc/src/test/java/org/acme/http/pqc/AbstractPqcTest.java b/http-pqc/src/test/java/org/acme/http/pqc/AbstractPqcTest.java index 073274e1..42fcaaa5 100644 --- a/http-pqc/src/test/java/org/acme/http/pqc/AbstractPqcTest.java +++ b/http-pqc/src/test/java/org/acme/http/pqc/AbstractPqcTest.java @@ -22,6 +22,8 @@ import java.security.Security; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSocket; import javax.net.ssl.TrustManagerFactory; import io.restassured.RestAssured; @@ -39,7 +41,7 @@ import static org.junit.jupiter.api.Assertions.fail; /** * Abstract base class for PQC tests with explicit JSSE provider selection. - * Tests both BCJSSE (PQC-capable) and SunJSSE (classical only) providers. + * Tests both BCJSSE (PQC-capable) and SunJSSE (PQC-capable only on recent JDK builds, e.g. 25.0.5+) providers. * * Certificates are generated before tests via CertificateTestResource. */ @@ -75,14 +77,24 @@ abstract class AbstractPqcTest { .statusCode(200); } - void testHttpClientConnection(String securityProvider, boolean expectFailure) throws Exception { + void testHttpClientConnection(String securityProvider, boolean expectFailure, String... clientNamedGroups) + throws Exception { try { SSLContext sslContext = createSslContext(securityProvider); SSLSocketFactory sslSocketFactory = new SSLSocketFactory( sslContext, new String[] { "TLSv1.3" }, null, - SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); + SSLSocketFactory.STRICT_HOSTNAME_VERIFIER) { + @Override + protected void prepareSocket(SSLSocket socket) { + if (clientNamedGroups.length > 0) { + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setNamedGroups(clientNamedGroups); + socket.setSSLParameters(sslParameters); + } + } + }; LOG.info("Testing with " + securityProvider + " provider on port " + RestAssured.port); diff --git a/http-pqc/src/test/java/org/acme/http/pqc/PqcOnlyTest.java b/http-pqc/src/test/java/org/acme/http/pqc/PqcOnlyTest.java index 0587a360..65e1d9ce 100644 --- a/http-pqc/src/test/java/org/acme/http/pqc/PqcOnlyTest.java +++ b/http-pqc/src/test/java/org/acme/http/pqc/PqcOnlyTest.java @@ -27,13 +27,15 @@ import org.junit.jupiter.api.Test; * * Expected results: * - BCJSSE: SUCCESS (supports X25519MLKEM768) - * - SunJSSE: FAILURE (does not support X25519MLKEM768) + * - SunJSSE restricted to classical named groups: FAILURE (no key exchange group in common with the server) * - * This proves that X25519MLKEM768 requires BouncyCastle JSSE. + * This proves that the server rejects clients that do not offer X25519MLKEM768. The client is restricted explicitly + * because SunJSSE supports X25519MLKEM768 on recent JDK builds (e.g. 25.0.5+). * * Note: @Order(2) ensures this test runs AFTER PqcWithFallbackTest. - * SunJSSE's static initialization fails with PQC-only config and permanently marks the - * class as failed. The fallback test must run first to validate SunJSSE works with classical algorithms. + * On JDK builds where SunJSSE does not support X25519MLKEM768, its static initialization fails with PQC-only config + * and permanently marks the class as failed. The fallback test must run first to validate SunJSSE works with + * classical algorithms. * * This test doesn't have a native *IT child, because the native executable can be build only with 1 configuration. */ @@ -54,6 +56,6 @@ class PqcOnlyTest extends AbstractPqcTest { @Test void testHttpClientWithSunJSSE() throws Exception { - testHttpClientConnection("SunJSSE", true); + testHttpClientConnection("SunJSSE", true, "x25519", "secp256r1"); } } diff --git a/http-pqc/src/test/java/org/acme/http/pqc/PqcWithFallbackTest.java b/http-pqc/src/test/java/org/acme/http/pqc/PqcWithFallbackTest.java index 93647702..255ea14d 100644 --- a/http-pqc/src/test/java/org/acme/http/pqc/PqcWithFallbackTest.java +++ b/http-pqc/src/test/java/org/acme/http/pqc/PqcWithFallbackTest.java @@ -27,7 +27,7 @@ import org.junit.jupiter.api.Test; * * Expected results: * - BCJSSE: SUCCESS (supports X25519MLKEM768 and fallback) - * - SunJSSE: SUCCESS (ignores X25519MLKEM768, uses secp256r1 fallback) + * - SunJSSE: SUCCESS (uses a classical fallback on JDK builds without X25519MLKEM768 support) * * Note: @Order(1) ensures this test runs BEFORE PqcOnlyTest in JVM mode. * This test must run first because SunJSSE can successfully initialize with the fallback
