From 94aa129582aeb37ea6bcfc92d0cc3589ca5c5dcd Mon Sep 17 00:00:00 2001 From: Sergey Beryozkin Date: Mon, 29 Mar 2021 18:42:48 +0100 Subject: [PATCH] Substitute BouncyCastle self-tests which rely on SecureRandom --- .../main/asciidoc/security-customization.adoc | 17 +++ .../deployment/SecurityProcessor.java | 12 ++ .../graal/BouncyCastleSubstitutions.java | 108 ++++++++++++++++++ .../src/main/resources/application.properties | 2 + 4 files changed, 139 insertions(+) create mode 100644 extensions/security/runtime/src/main/java/io/quarkus/security/runtime/graal/BouncyCastleSubstitutions.java diff --git a/docs/src/main/asciidoc/security-customization.adoc b/docs/src/main/asciidoc/security-customization.adoc index adbe3cc353f59..f3a19fdeaeab5 100644 --- a/docs/src/main/asciidoc/security-customization.adoc +++ b/docs/src/main/asciidoc/security-customization.adoc @@ -319,6 +319,18 @@ and add the BouncyCastle FIPS provider dependency: ---- +[NOTE] +==== +`BCFIPS` provider option is supported in native image but the algorithm self-tests which rely on `java.security.SecureRandom` to verify the generated keys have been removed for these tests to pass. The following classes have been affected: +- `org.bouncycastle.crypto.general.DSA` +- `org.bouncycastle.crypto.general.DSTU4145` +- `org.bouncycastle.crypto.general.ECGOST3410` +- `org.bouncycastle.crypto.general.GOST3410` +- `org.bouncycastle.crypto.fips.FipsDSA` +- `org.bouncycastle.crypto.fips.FipsEC` +- `org.bouncycastle.crypto.fips.FipsRSA` +==== + === BouncyCastle JSSE FIPS If you need to register an `org.bouncycastle.jsse.provider.BouncyCastleJsseProvider` JSSE provider and use it in combination with `org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider` instead of the default SunJSSE provider then please set a `BCFIPSJSSE` provider name: @@ -363,6 +375,11 @@ One can generate a keystore with this type and provider like this: keytool -genkey -alias server -keyalg RSA -keystore server-keystore.jks -keysize 2048 -keypass password -provider org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider -providerpath $PATH_TO_BC_FIPS_JAR -storetype BCFKS ---- +[NOTE] +==== +`BCFIPSJSSE` provider option is currently not supported in native image. +==== + == Reactive Security If you are going to use security in a reactive environment, you will likely need SmallRye Context Propagation: diff --git a/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java b/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java index e0a23311ca1ca..c24590d1485f9 100644 --- a/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java +++ b/extensions/security/deployment/src/main/java/io/quarkus/security/deployment/SecurityProcessor.java @@ -125,6 +125,11 @@ void prepareBouncyCastleProviders(BuildProducer reflec if (bouncyCastleJsseProvider.isPresent()) { reflection.produce( new ReflectiveClassBuildItem(true, true, SecurityProviderUtils.BOUNCYCASTLE_JSSE_PROVIDER_CLASS_NAME)); + reflection.produce(new ReflectiveClassBuildItem(true, true, true, + "org.bouncycastle.jsse.provider.DefaultSSLContextSpi$LazyManagers")); + runtimeReInitialized + .produce(new RuntimeReinitializedClassBuildItem( + "org.bouncycastle.jsse.provider.DefaultSSLContextSpi$LazyManagers")); prepareBouncyCastleProvider(reflection, runtimeReInitialized, bouncyCastleJsseProvider.get().isInFipsMode()); } else if (bouncyCastleProvider.isPresent()) { prepareBouncyCastleProvider(reflection, runtimeReInitialized, bouncyCastleProvider.get().isInFipsMode()); @@ -144,10 +149,17 @@ private static void prepareBouncyCastleProvider(BuildProducer PACKAGES = Arrays.asList(Package.getPackages()).stream() + .map(p -> p.getName()).filter(p -> p.startsWith(ORG_BOUNCYCASTLE_CRYPTO_PACKAGE)).collect(Collectors.toSet()); +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.general.DSA$1", onlyWith = BouncyCastleCryptoGeneral.class) +final class Target_org_bouncycastle_crypto_general_DSA$1 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.general.DSTU4145$2", onlyWith = BouncyCastleCryptoGeneral.class) +final class Target_org_bouncycastle_crypto_general_DSTU4145$2 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.general.ECGOST3410$2", onlyWith = BouncyCastleCryptoGeneral.class) +final class Target_org_bouncycastle_crypto_general_ECGOST3410$2 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.general.GOST3410$1", onlyWith = BouncyCastleCryptoGeneral.class) +final class Target_org_bouncycastle_crypto_general_GOST3410$1 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.fips.FipsDSA$2", onlyWith = BouncyCastleCryptoFips.class) +final class Target_org_bouncycastle_crypto_fips_FipsDSA$2 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.fips.FipsEC$1", onlyWith = BouncyCastleCryptoFips.class) +final class Target_org_bouncycastle_crypto_fips_FipsEC$1 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.fips.FipsRSA$3", onlyWith = BouncyCastleCryptoFips.class) +final class Target_org_bouncycastle_crypto_fips_FipsRSA$3 { + @com.oracle.svm.core.annotate.Substitute + public boolean hasTestPassed(Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair kp) { + return true; + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.fips.FipsRSA$EngineProvider$1", onlyWith = BouncyCastleCryptoFips.class) +final class Target_org_bouncycastle_crypto_fips_FipsRSA$EngineProvider$1 { + @com.oracle.svm.core.annotate.Substitute + public void evaluate(Target_org_bouncycastle_crypto_fips_RsaBlindedEngine rsaEngine) { + // Complete + } +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.internal.AsymmetricCipherKeyPair", onlyWith = BouncyCastleCryptoInternal.class) +final class Target_org_bouncycastle_crypto_internal_AsymmetricCipherKeyPair { +} + +@com.oracle.svm.core.annotate.TargetClass(className = "org.bouncycastle.crypto.fips.RsaBlindedEngine", onlyWith = BouncyCastleCryptoFips.class) +final class Target_org_bouncycastle_crypto_fips_RsaBlindedEngine { +} + +class BouncyCastleCryptoFips implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return BouncyCastlePackages.PACKAGES.contains(BouncyCastlePackages.ORG_BOUNCYCASTLE_CRYPTO_FIPS_PACKAGE); + } +} + +class BouncyCastleCryptoGeneral implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return BouncyCastlePackages.PACKAGES.contains(BouncyCastlePackages.ORG_BOUNCYCASTLE_CRYPTO_GENERAL_PACKAGE); + } +} + +class BouncyCastleCryptoInternal implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return BouncyCastlePackages.PACKAGES.contains(BouncyCastlePackages.ORG_BOUNCYCASTLE_CRYPTO_INTERNAL_PACKAGE); + } +} \ No newline at end of file diff --git a/integration-tests/bouncycastle-fips-jsse/src/main/resources/application.properties b/integration-tests/bouncycastle-fips-jsse/src/main/resources/application.properties index e8af67cf00971..ed49e1e4fa8b0 100644 --- a/integration-tests/bouncycastle-fips-jsse/src/main/resources/application.properties +++ b/integration-tests/bouncycastle-fips-jsse/src/main/resources/application.properties @@ -16,3 +16,5 @@ quarkus.log.category."org.bouncycastle.jsse".min-level=TRACE quarkus.log.category."org.bouncycastle.jsse".level=TRACE quarkus.log.file.enable=true quarkus.log.file.format=%C - %s%n + +#quarkus.native.additional-build-args=--trace-object-instantiation=org.bouncycastle.crypto.fips.FipsSecureRandom\\,java.security.SecureRandom