This is an automated email from the ASF dual-hosted git repository. jamesnetherton pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 843f97ff7ea01486441f170253d777e62cf68f58 Author: James Netherton <[email protected]> AuthorDate: Wed Sep 23 19:06:40 2026 +0100 Work around BouncyCastle 1.86 removals in the PQC native build BouncyCastle 1.86 removed Picnic, Frodo and several legacy PQC parameter spec classes that camel-pqc still references. Initialize the affected default key material classes at runtime and add GraalVM substitutions that avoid the removed classes. The workaround should be removed once Camel supports BouncyCastle 1.86. See #9231. Co-Authored-By: Claude Opus 5.5 <[email protected]> --- .../component/pqc/deployment/PqcProcessor.java | 14 +++ extensions/pqc/runtime/pom.xml | 5 + .../component/pqc/graal/PqcSubstitutions.java | 121 +++++++++++++++++++++ 3 files changed, 140 insertions(+) diff --git a/extensions/pqc/deployment/src/main/java/org/apache/camel/quarkus/component/pqc/deployment/PqcProcessor.java b/extensions/pqc/deployment/src/main/java/org/apache/camel/quarkus/component/pqc/deployment/PqcProcessor.java index 425d492964..a92bdf60e5 100644 --- a/extensions/pqc/deployment/src/main/java/org/apache/camel/quarkus/component/pqc/deployment/PqcProcessor.java +++ b/extensions/pqc/deployment/src/main/java/org/apache/camel/quarkus/component/pqc/deployment/PqcProcessor.java @@ -23,6 +23,10 @@ import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.IndexDependencyBuildItem; import io.quarkus.deployment.builditem.nativeimage.NativeImageSecurityProviderBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem; +import org.apache.camel.component.pqc.crypto.PQCDefaultPicnicMaterial; +import org.apache.camel.component.pqc.crypto.kem.PQCDefaultCMCEMaterial; +import org.apache.camel.component.pqc.crypto.kem.PQCDefaultFRODOMaterial; import org.apache.camel.quarkus.support.bouncycastle.BouncyCastleRecorder; import org.apache.camel.quarkus.support.bouncycastle.deployment.BouncyCastleAdditionalProviderBuildItem; import org.jboss.jandex.IndexView; @@ -78,4 +82,14 @@ class PqcProcessor { return new BouncyCastleAdditionalProviderBuildItem(BouncyCastleRecorder.BOUNCYCASTLE_PCQ_PROVIDER_NAME); } + // TODO: Remove this - https://github.com/apache/camel-quarkus/issues/9231 + @BuildStep + void runtimeInitializedClasses(BuildProducer<RuntimeInitializedClassBuildItem> runtimeInitializedClass) { + runtimeInitializedClass.produce( + new RuntimeInitializedClassBuildItem(PQCDefaultPicnicMaterial.class.getName())); + runtimeInitializedClass.produce( + new RuntimeInitializedClassBuildItem(PQCDefaultFRODOMaterial.class.getName())); + runtimeInitializedClass.produce( + new RuntimeInitializedClassBuildItem(PQCDefaultCMCEMaterial.class.getName())); + } } diff --git a/extensions/pqc/runtime/pom.xml b/extensions/pqc/runtime/pom.xml index 5e12106ca0..d1a8653413 100644 --- a/extensions/pqc/runtime/pom.xml +++ b/extensions/pqc/runtime/pom.xml @@ -49,6 +49,11 @@ <groupId>org.apache.camel.quarkus</groupId> <artifactId>camel-quarkus-support-bouncycastle</artifactId> </dependency> + <dependency> + <groupId>org.graalvm.sdk</groupId> + <artifactId>nativeimage</artifactId> + <scope>provided</scope> + </dependency> </dependencies> <build> diff --git a/extensions/pqc/runtime/src/main/java/org/apache/camel/quarkus/component/pqc/graal/PqcSubstitutions.java b/extensions/pqc/runtime/src/main/java/org/apache/camel/quarkus/component/pqc/graal/PqcSubstitutions.java new file mode 100644 index 0000000000..5d080ea93c --- /dev/null +++ b/extensions/pqc/runtime/src/main/java/org/apache/camel/quarkus/component/pqc/graal/PqcSubstitutions.java @@ -0,0 +1,121 @@ +/* + * 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.quarkus.component.pqc.graal; + +import java.security.InvalidAlgorithmParameterException; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.spec.AlgorithmParameterSpec; + +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import org.apache.camel.component.pqc.PQCKeyEncapsulationAlgorithms; +import org.apache.camel.component.pqc.PQCParameterSpecResolver; +import org.apache.camel.component.pqc.crypto.PQCDefaultPicnicMaterial; +import org.apache.camel.component.pqc.crypto.kem.PQCDefaultCMCEMaterial; +import org.apache.camel.component.pqc.crypto.kem.PQCDefaultFRODOMaterial; +import org.apache.camel.util.SecureRandomHelper; +import org.bouncycastle.jcajce.spec.CMCEParameterSpec; +import org.bouncycastle.jcajce.spec.MLDSAParameterSpec; +import org.bouncycastle.jcajce.spec.MLKEMParameterSpec; +import org.bouncycastle.jcajce.spec.SLHDSAParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.BIKEParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.FalconParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.HQCParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.NTRULPRimeParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.NTRUParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.SABERParameterSpec; +import org.bouncycastle.pqc.jcajce.spec.SNTRUPrimeParameterSpec; + +/** + * Removes references to BouncyCastle parameter specs that no longer exist in the BouncyCastle version managed by + * Quarkus. Algorithms without a replacement spec are not supported in native mode. + */ +// TODO: Remove this - https://github.com/apache/camel-quarkus/issues/9231 +final class PqcSubstitutions { +} + +@TargetClass(PQCParameterSpecResolver.class) +final class SubstitutePQCParameterSpecResolver { + @Substitute + private static AlgorithmParameterSpec doResolve(String algorithm, String parameterSpec) { + switch (algorithm) { + // Signature algorithms + case "MLDSA": + return MLDSAParameterSpec.fromName(parameterSpec); + case "SLHDSA": + return SLHDSAParameterSpec.fromName(parameterSpec); + case "FALCON": + return FalconParameterSpec.fromName(parameterSpec); + // Key encapsulation algorithms + case "MLKEM": + return MLKEMParameterSpec.fromName(parameterSpec); + case "NTRU": + return NTRUParameterSpec.fromName(parameterSpec); + case "NTRULPRime": + return NTRULPRimeParameterSpec.fromName(parameterSpec); + case "SNTRUPrime": + return SNTRUPrimeParameterSpec.fromName(parameterSpec); + case "BIKE": + return BIKEParameterSpec.fromName(parameterSpec); + case "HQC": + return HQCParameterSpec.fromName(parameterSpec); + case "CMCE": + return CMCEParameterSpec.fromName(parameterSpec); + case "SABER": + return SABERParameterSpec.fromName(parameterSpec); + case "DILITHIUM": + case "SPHINCSPLUS": + case "PICNIC": + case "KYBER": + case "FRODO": + throw new UnsupportedOperationException( + "The parameterSpec option is not supported for algorithm " + algorithm + " in native mode"); + default: + throw new IllegalStateException("Unsupported algorithm: " + algorithm); + } + } +} + +@TargetClass(PQCDefaultPicnicMaterial.class) +final class SubstitutePQCDefaultPicnicMaterial { + @Substitute + protected static KeyPairGenerator prepareKeyPair() { + throw new UnsupportedOperationException("The PICNIC algorithm is not supported in native mode"); + } +} + +@TargetClass(PQCDefaultFRODOMaterial.class) +final class SubstitutePQCDefaultFRODOMaterial { + @Substitute + protected static KeyPairGenerator prepareKeyPair() { + throw new UnsupportedOperationException("The FRODO algorithm is not supported in native mode"); + } +} + +@TargetClass(PQCDefaultCMCEMaterial.class) +final class SubstitutePQCDefaultCMCEMaterial { + @Substitute + protected static KeyPairGenerator prepareKeyPair() + throws NoSuchAlgorithmException, NoSuchProviderException, InvalidAlgorithmParameterException { + KeyPairGenerator kpg = KeyPairGenerator.getInstance(PQCKeyEncapsulationAlgorithms.CMCE.getAlgorithm(), + PQCKeyEncapsulationAlgorithms.CMCE.getBcProvider()); + kpg.initialize(CMCEParameterSpec.mceliece8192128f, SecureRandomHelper.getSecureRandom()); + return kpg; + } +}
