aws / aws-encryption-sdk-java

AWS Encryption SDK
https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/introduction.html
Apache License 2.0
225 stars 123 forks source link

BouncyCastle FIPs Support #99

Closed johnwalker closed 5 years ago

johnwalker commented 5 years ago

Can the Encryption SDK for Java be used with BouncyCastle FIPs?

mattsb42-aws commented 5 years ago

Yes[1]. Something that would be great to add to our CI is to run all of our tests with different JCE backends, much like we currently do with different JDKs.

[1] 99% certain. I'm pretty sure we've had people use it with that before.

mattsb42-aws commented 5 years ago

I stand corrected. #41 is blocking this.

SalusaSecondus commented 5 years ago

I wired in BC-FIPS for test purposes by using the following diff. (ACCP is used as BC-FIPS pulls tons of entropy from /dev/random by default, and thus blocks.) There are some test failures we still need to figure out, but nothing too worrisome. All decryption test vectors successfully pass. Most of the failures are from tests using features/functionality outside of the standard FIPS 140-2 area.

diff --git a/pom.xml b/pom.xml
index 3a2f2d3..561930a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,8 +48,8 @@

         <dependency>
             <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-ext-jdk15on</artifactId>
-            <version>1.61</version>
+            <artifactId>bc-fips</artifactId>
+            <version>1.0.1</version>
         </dependency>

         <dependency>
@@ -73,6 +73,12 @@
             <scope>test</scope>
         </dependency>

+<dependency>
+  <groupId>software.amazon.cryptools</groupId>
+  <artifactId>AmazonCorrettoCryptoProvider</artifactId>
+  <version>LATEST</version>
+  <classifier>linux-x86_64</classifier>
+</dependency>

         <dependency>
             <groupId>com.google.code.findbugs</groupId>
diff --git a/src/main/java/com/amazonaws/encryptionsdk/AwsCrypto.java b/src/main/java/com/amazonaws/encryptionsdk/AwsCrypto.java
index fecd733..e51e8dd 100644
--- a/src/main/java/com/amazonaws/encryptionsdk/AwsCrypto.java
+++ b/src/main/java/com/amazonaws/encryptionsdk/AwsCrypto.java
@@ -84,8 +84,56 @@ import com.amazonaws.encryptionsdk.model.EncryptionMaterialsRequest;
  * safety to advanced developers. The great majority of users should be able to just use the
  * provided type parameters or the {@code ?} wildcard.
  */
+
+import org.bouncycastle.crypto.util.BasicEntropySourceProvider;
+import java.security.SecureRandom;
 @SuppressWarnings("WeakerAccess") // this is a public API
 public class AwsCrypto {
+    /**
+     * Provides non-blocking entropy to BouncyCastle (non-FIPS mode).
+     */
+    public static final class FastEntropySourceProvider extends BasicEntropySourceProvider {
+        private static final java.util.List<String> PREFERRED_SOURCES = java.util.Arrays.asList(
+                                                                           "NIST800-90A/AES-CTR-256", "NativePRNGNonBlocking", "Windows-PRNG");
+
+        public FastEntropySourceProvider() {
+            super(selectSecureRandom(), true);
+        }
+
+        private static SecureRandom selectSecureRandom() {
+            if (com.amazon.corretto.crypto.provider.AmazonCorrettoCryptoProvider.isRdRandSupported()) {
+               System.out.println("Using AesCtrDrbg");
+               return new com.amazon.corretto.crypto.provider.AesCtrDrbg();
+            } else {
+                for (final String algorithm : PREFERRED_SOURCES) {
+                    try {
+                        final SecureRandom rng = SecureRandom.getInstance(algorithm);
+                       System.out.println("Using " + algorithm);
+                        return rng;
+                    } catch (final Exception ex) {
+                        // Expected
+                    }
+                }
+                throw new AssertionError("No acceptable EntropySource found.");
+            }
+        }
+    }
+
+    static {
+       try {
+           System.setProperty("org.bouncycastle.drbg.entropysource", FastEntropySourceProvider.class.getName());
+           System.out.println("Default provider for GCM is* " + javax.crypto.Cipher.getInstance("AES/GCM/NoPadding").getProvider());
+           System.err.println("Default provider for GCM is* " + javax.crypto.Cipher.getInstance("AES/GCM/NoPadding").getProvider());
+
+           org.bouncycastle.crypto.CryptoServicesRegistrar.setSecureRandom(
+                                                                           org.bouncycastle.crypto.fips.FipsDRBG.SHA512_HMAC.fromEntropySource
+                                                                           (new FastEntropySourceProvider()).build(null, true));
+            java.security.Security.insertProviderAt(new org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider(), 1);
+       } catch (final Exception ex) {
+           throw new AssertionError(ex);
+       }
+    }
+
     private static final Map<String, String> EMPTY_MAP = Collections.emptyMap();

     /**
WesleyRosenblum commented 5 years ago

Tests are now passing with FIPS certified Bouncy Castle

ravinirmal10 commented 3 years ago

@WesleyRosenblum @SalusaSecondus - I am planning to use BC FIPS for aws-encryption-sdk.

I can see that pom.xml file of aws-encryption-sdk is having dependency of bcprov-ext-jdk15on jar, based on that it seems that if I want to use bc-fips then I need to copy the aws-encryption-sdk package and replace bcprov-ext-jdk15on to bc-fips in pom.xml. Basically I don't want to copy the package and want to use aws-encryption-sdk with BC-FIPS directly as a dependency in my project.

WesleyRosenblum commented 3 years ago

Hi @ravinirmal10,

The dependency on bcprov-ext-jdk15on is only needed for the AWS Encryption SDK to serialize and deserialize cryptographic objects, not for the underlying cryptography. From the Getting Started section of the README:

The AWS Encryption SDK for Java uses Bouncy Castle to serialize and deserialize cryptographic objects. It does not explicitly use Bouncy Castle (or any other JCA Provider) for the underlying cryptography. Instead, it uses the platform default, which you can configure or override as documented in the Java Cryptography Architecture (JCA) Reference Guide. ... Beginning in version 1.6.1, the AWS Encryption SDK also works with Bouncy Castle FIPS (groupId: org.bouncycastle, artifactId: bc-fips) as an alternative to non-FIPS Bouncy Castle. For help installing and configuring Bouncy Castle FIPS properly, see BC FIPS documentation, in particular, User Guides and Security Policy.

To summarize, you do not need to modify the pom.xml of the AWS Encryption SDK. You may add Bouncy Castle FIPS as a dependency of your own software, and install it as mentioned in the BC FIPS documentation. Let me know if you have any further questions.

Thanks! Wesley

ravinirmal10 commented 3 years ago

@WesleyRosenblum - Thanks for your quick response, I am able to use aws-encryption-sdk with Bouncy Castle FIPS by adding bc-fips dependency in my project.

Please note when I tried to use aws-encryption-sdk with Bouncy Castle FIPS by adding bc-fips & aws-encryption-sdk dependency in my project I saw aws-encryption-sdk-java-2.0.0.jar, bc-fips-1.0.2.jar and bcprov-ext-jdk15on-1.65.jar files were present in the class path and on server startup I could see below exception:

Caused by: java.lang.NoSuchFieldError: id_alg_AEADChaCha20Poly1305
    at org.bouncycastle.jcajce.provider.symmetric.ChaCha$Mappings.configure(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at org.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at org.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at org.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at java.security.AccessController.doPrivileged(Native Method) ~[?:1.8.0_181]
    at org.bouncycastle.jce.provider.BouncyCastleProvider.<init>(Unknown Source) ~[bcprov-ext-jdk15on-1.65.jar:1.65.00.0]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:1.8.0_181]
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[?:1.8.0_181]
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:1.8.0_181]
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[?:1.8.0_181]
    at java.lang.Class.newInstance(Class.java:442) ~[?:1.8.0_181]

Then I have to manually exclude bcprov-ext-jdk15on-1.65.jar from build.gradle file of my project in order to solve the issue, the reason was because bc-fips-1.0.2.jar and bcprov-ext-jdk15on-1.65.jar both files were present in the class path and they were colliding with each other.

Thanks, Ravi