Skip to main content

Overview

Minimus provides FIPS 140-3 validated Java images that enable cryptographic operations compliant with Federal Information Processing Standards. These images are configured with FIPS-validated cryptographic providers and enforce strict FIPS compliance at runtime.

Available Java FIPS 140-3 images

Minimus offers 4 Java FIPS 140-3 image types:
  1. openjdk-fips - OpenJDK Development Kit (JDK) with FIPS support
  2. openjre-fips - OpenJDK Runtime Environment (JRE) with FIPS support
  3. amazon-corretto-jdk-fips - Amazon Corretto JDK with FIPS support
  4. amazon-corretto-jre-fips - Amazon Corretto JRE with FIPS support
The OpenJDK FIPS images are based on eclipse-temurin (Eclipse Temurin). The Amazon Corretto FIPS images are based on amazoncorretto (Amazon Corretto).

Supported Java versions

Java FIPS images support active Java versions:
  • Java 25
  • Java 24 (Reached EOL)
  • Java 21
  • Java 17
  • Java 11

FIPS 140-3 configuration

Cryptographic providers

Java FIPS 140-3 images are configured with the following security providers (ordered by priority):
  1. SafeLogic CryptoComply FIPS Provider (CCJ) - Primary FIPS 140-3 validated provider
  2. Bouncy Castle JSSE Provider - FIPS-compliant TLS/SSL provider that delegates to CCJ
  3. Sun Provider - Loaded at low priority (required for CCJ JAR signature validation only)
  4. Infrastructure Providers - SunJGSS, SunSASL, XMLDSig, SunPCSC, JdkLDAP, JdkSASL (delegate crypto operations to CCJ/BCJSSE)

FIPS 140-3 libraries

The images include the following FIPS-validated libraries in /usr/share/fips-libs/:
  • ccj-4.0.0-fips.jar - SafeLogic CryptoComply FIPS 140-3 provider
  • sl-bcutil-2.0.3.jar - SafeLogic Bouncy Castle utilities
  • sl-bctls-2.0.21.jar - SafeLogic Bouncy Castle TLS/SSL (JSSE)
  • sl-bcpkix-2.0.8.jar - SafeLogic Bouncy Castle PKIX/X.509
  • sl-bcmail-2.0.5.jar - SafeLogic Bouncy Castle S/MIME
  • sl-bcpg-2.0.12.jar - SafeLogic Bouncy Castle OpenPGP

Security configuration

The images enforce FIPS compliance through:
  • Approved-only mode: com.safelogic.cryptocomply.fips.approved_only=true
  • Non-FIPS providers disabled: SunRsaSign, SunEC, SunJCE, and SunJSSE are omitted
  • FIPS-approved algorithms only: Non-FIPS algorithms are blocked (e.g., MD5)
  • BCFKS keystore type: Required for private keys (Bouncy Castle FIPS KeyStore is a FIPS-compliant keystore format)
  • Trust store types: JKS, PKCS12, and BCFKS supported for truststores

Environment variables

Minimus Java FIPS images set the following environment variables by default:
  • JAVA_HOME: Points to the default JVM installation
  • CLASSPATH: Includes FIPS libraries from /usr/share/fips-libs/*
  • JAVA_FIPS_CLASSPATH: Explicit FIPS classpath reference
  • JDK_JAVA_OPTIONS: Includes the required exports and FIPS trust store configuration:
    --add-exports=java.base/sun.security.internal.spec=ALL-UNNAMED
    --add-exports=java.base/sun.security.provider=ALL-UNNAMED
    -Djavax.net.ssl.trustStoreType=FIPS
    

Verifying the Java FIPS 140-3 module

Each Java FIPS image includes automated tests that verify:
  1. Java version - Confirms that the correct Java version is installed
  2. FIPS provider availability - Verifies that SafeLogic CryptoComply and Bouncy Castle JSSE providers are loaded
  3. Provider priority - Ensures providers are in the correct order (CCJ at position 1, BCJSSE at position 2)
  4. FIPS-approved algorithms - Tests that FIPS-approved algorithms (AES, SHA-256, RSA) are available
  5. Non-FIPS algorithm blocking - Confirms non-FIPS algorithms (e.g., MD5) are correctly blocked

Basic verification

# Run a Java application with FIPS compliance
docker run --rm reg.mini.dev/openjdk-fips:21 java -version

# Compile and run Java code
docker run --rm -v $(pwd):/home/build reg.mini.dev/openjdk-fips:21 \
  javac MyApp.java && java MyApp

FIPS compliance test

You can verify FIPS compliance by creating a test program. For example, save the following code as the file TestFIPS.java:
import java.security.Provider;
import java.security.Security;

public class TestFIPS {
    public static void main(String[] args) {
        System.out.println("=== FIPS Compliance Test ===");

        // Check that FIPS approved only mode is enabled
        String approvedOnly = Security.getProperty("com.safelogic.cryptocomply.fips.approved_only");
        boolean isApprovedOnly = approvedOnly != null && approvedOnly.equals("true");

        if (!isApprovedOnly) {
            System.err.println("[ERROR] SafeLogic CryptoComply FIPS Approved Only Mode is disabled!");
            System.exit(1);
        }

        // Check that providers are loaded
        Provider[] providers = Security.getProviders();
        boolean foundCryptoComply = false;
        boolean foundBCJSSE = false;
        int cryptoComplyPosition = -1;
        int bcjssePosition = -1;

        for (int i = 0; i < providers.length; i++) {
            Provider provider = providers[i];
            String name = provider.getName();
            if (name.contains("CCJ") || name.contains("CryptoComply")) {
                foundCryptoComply = true;
                cryptoComplyPosition = i + 1;
                System.out.println("[OK] SafeLogic CryptoComply provider found at position " + cryptoComplyPosition);
            }
            if (name.contains("BouncyCastleJsse") || name.contains("BCJSSE")) {
                foundBCJSSE = true;
                bcjssePosition = i + 1;
                System.out.println("[OK] Bouncy Castle JSSE provider found at position " + bcjssePosition);
            }
        }

        if (!foundCryptoComply) {
            System.err.println("[ERROR] SafeLogic CryptoComply provider NOT found!");
            System.exit(1);
        }
        if (!foundBCJSSE) {
            System.err.println("[ERROR] Bouncy Castle JSSE provider NOT found!");
            System.exit(1);
        }

        // Check provider positions
        if (cryptoComplyPosition != 1) {
            System.err.println("[WARNING] SafeLogic CryptoComply provider is at position " + cryptoComplyPosition + ", expected position 1");
        } else {
            System.out.println("[OK] SafeLogic CryptoComply provider is at correct position (1)");
        }

        if (bcjssePosition != 2) {
            System.err.println("[WARNING] Bouncy Castle JSSE provider is at position " + bcjssePosition + ", expected position 2");
        } else {
            System.out.println("[OK] Bouncy Castle JSSE provider is at correct position (2)");
        }

        // Test FIPS-approved algorithms
        try {
            // Test AES (FIPS-approved)
            javax.crypto.Cipher.getInstance("AES/CBC/PKCS5Padding", "CCJ");
            System.out.println("[OK] AES algorithm available");

            // Test SHA-256 (FIPS-approved)
            java.security.MessageDigest.getInstance("SHA-256", "CCJ");
            System.out.println("[OK] SHA-256 algorithm available");

            // Test RSA (FIPS-approved)
            java.security.KeyPairGenerator.getInstance("RSA", "CCJ");
            System.out.println("[OK] RSA algorithm available");

            // Test that MD5 is correctly blocked (non-FIPS)
            try {
                java.security.MessageDigest md5 = java.security.MessageDigest.getInstance("MD5", "CCJ");
                System.err.println("[ERROR] MD5 is available (provider: " + md5.getProvider().getName() + ")");
                System.err.println("[ERROR] FIPS mode is not fully enforced - MD5 should be blocked!");
                System.exit(1);
            } catch (Exception e) {
                System.out.println("[OK] MD5 correctly blocked by FIPS compliance: " + e.getMessage());
            }

            System.out.println("=== FIPS Compliance Test PASSED ===");

        } catch (Exception e) {
            System.err.println("[ERROR] FIPS algorithm test failed: " + e.getMessage());
            e.printStackTrace();
            System.exit(1);
        }
    }
}
Compile and run the FIPS test:
docker run --rm -v $(pwd):/home/build minimus/openjdk-fips:21 sh -c \
  "javac TestFIPS.java && java TestFIPS"
Expected output:
=== FIPS Compliance Test ===
[OK] SafeLogic CryptoComply provider found at position 1
[OK] Bouncy Castle JSSE provider found at position 2
[OK] SafeLogic CryptoComply provider is at correct position (1)
[OK] Bouncy Castle JSSE provider is at correct position (2)
[OK] AES algorithm available
[OK] SHA-256 algorithm available
[OK] RSA algorithm available
[OK] MD5 correctly blocked by FIPS compliance: ...
=== FIPS Compliance Test PASSED ===

Notes

  • FIPS compliance is enforced at runtime via Java security configurations
  • Applications must use FIPS-approved algorithms and keystore formats (BCFKS)
  • The Sun provider is included only for JAR signature validation and does not perform cryptographic operations
  • All cryptographic operations are routed through FIPS-validated providers (CCJ and BCJSSE)
  • The Java FIPS module requires specialized hardware. Learn more