{"record":{"id":"2c4b6489b4f46c1c","repo":"apache/pulsar","slug":"the-bcfips-provider-is-registered-but-its-default","errorCode":null,"errorMessage":"The BCFIPS provider is registered but its DEFAULT SP 800-90A DRBG could not be obtained; refusing to fall back to a non-FIPS SecureRandom for data-key and IV generation.","messagePattern":"The BCFIPS provider is registered but its DEFAULT SP 800-90A DRBG could not be obtained; refusing to fall back to a non-FIPS SecureRandom for data-key and IV generation\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java","lineNumber":142,"sourceCode":"    private static final SecureRandom secureRandom;\n    static {\n        SecureRandom rand;\n        Provider bcfips = Security.getProvider(\"BCFIPS\");\n        if (bcfips != null) {\n            // When the BC-FIPS provider is registered, source randomness from its SP 800-90A\n            // DRBG so data-key and IV generation stays within the FIPS-validated module.\n            // Only registered providers are consulted here to avoid triggering BouncyCastle\n            // classpath resolution during class loading (see BcProviderHolder above).\n            try {\n                rand = SecureRandom.getInstance(\"DEFAULT\", bcfips);\n            } catch (NoSuchAlgorithmException nsa) {\n                // Deliberately fatal rather than falling back: new SecureRandom() resolves by provider\n                // search order and may land outside the validated module, which is exactly what this\n                // branch exists to prevent. Registering BCFIPS is an operator asking for FIPS-approved\n                // randomness, and a data key or GCM IV drawn from anywhere else leaves no trace at run\n                // time -- SP 800-38D only permits a random 96-bit GCM IV from an approved DRBG. Failing\n                // class initialization surfaces the misconfiguration at the point it can still be fixed.\n                throw new IllegalStateException(\"The BCFIPS provider is registered but its DEFAULT SP \"\n                        + \"800-90A DRBG could not be obtained; refusing to fall back to a non-FIPS \"\n                        + \"SecureRandom for data-key and IV generation.\", nsa);\n            }\n        } else {\n            try {\n                rand = SecureRandom.getInstance(\"NativePRNGNonBlocking\");\n            } catch (NoSuchAlgorithmException nsa) {\n                // Unchanged: on a JVM without NativePRNGNonBlocking the platform default is the\n                // long-standing behaviour, and no FIPS guarantee was being claimed on this path.\n                rand = new SecureRandom();\n            }\n        }\n        secureRandom = rand;\n\n        // Initial seed\n        secureRandom.nextBytes(new byte[IV_LEN]);\n    }\n","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-client-messagecrypto-bc/src/main/java/org/apache/pulsar/client/impl/crypto/MessageCryptoBc.java#L124-L160","documentation":"MessageCryptoBc's static initializer detects that the BCFIPS (Bouncy Castle FIPS) security provider is registered, so it requires its FIPS-approved SP 800-90A DRBG (SecureRandom \"DEFAULT\" from BCFIPS) for all data-key and GCM IV generation. If SecureRandom.getInstance(\"DEFAULT\", bcfips) throws NoSuchAlgorithmException, the class refuses to fall back to a non-FIPS SecureRandom and throws this IllegalStateException, aborting class initialization. This is a deliberate fail-closed FIPS compliance guard.","triggerScenarios":"Loading the MessageCryptoBc class when Security.getProvider(\"BCFIPS\") != null but the BCFIPS provider cannot supply its DEFAULT DRBG: BCFIPS jar on classpath without the BC-FIPS approved module (bcpkix/bcfips dependencies) properly approved/initialized, BCFIPS version mismatch, or the provider not yet in an approved state (e.g. missing BouncyCastleFipsApproved status / not approved via Security.setProperty or fips settings).","commonSituations":"Deploying in FIPS mode where bc-fips jar is present but the approved-only module (bcpkix-fips / bcutil-fips) or its native approval state is missing; mixing non-FIPS BC and FIPS BCFIPS jars; registering BCFIPS programmatically without completing its approved-mode setup; version mismatch after an upgrade.","solutions":["Complete BCFIPS approved-mode setup before loading MessageCryptoBc (install and configure the BC-FIPS approved module, e.g. Security.addProvider(new BouncyCastleFipsProvider()) with approved-only status)","Align all Bouncy Castle artifacts to the FIPS variant at matching versions (bc-fips plus bcpkix-fips/bcutil-fips) and remove conflicting non-FIPS BC jars","Verify BCFIPS version supports the 'DEFAULT' SecureRandom/DRBG algorithm (upgrade bc-fips if needed)","If FIPS is not actually required, unregister BCFIPS (Security.removeProvider(\"BCFIPS\")) so the code takes the standard NativePRNGNonBlocking path","Catch/inspect the cause (NoSuchAlgorithmException) and confirm which DRBG algorithms the installed provider exposes"],"exampleFix":"// before: BCFIPS registered but approved module missing\nSecurity.addProvider(new org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider());\n// ... later MessageCryptoBc class init fails\n\n// after: register BCFIPS with approved-only mode via bcfips.provider configuration\n// (e.g. -Dorg.bouncycastle.fips.approved_only=true) and ensure bc-fips + bcpkix-fips\n// on classpath BEFORE instantiating producer/consumer\nMessageCryptoBc crypto = new MessageCryptoBc(logCtx, true);","handlingStrategy":"validation","validationCode":"// run before touching encrypted producer/consumer\nProvider bcfips = Security.getProvider(\"BCFIPS\");\nif (bcfips != null) {\n    try {\n        SecureRandom.getInstance(\"DEFAULT\", bcfips);\n    } catch (NoSuchAlgorithmException e) {\n        throw new IllegalStateException(\"BCFIPS registered but DEFAULT DRBG unavailable — \"\n            + \"install/configure the approved BC-FIPS module or remove BCFIPS\", e);\n    }\n}","typeGuard":"boolean fipsRandomReady() {\n    Provider p = Security.getProvider(\"BCFIPS\");\n    if (p == null) return true; // non-FIPS path\n    try {\n        SecureRandom.getInstance(\"DEFAULT\", p);\n        return true;\n    } catch (NoSuchAlgorithmException e) {\n        return false;\n    }\n}","tryCatchPattern":"try {\n    Producer<byte[]> producer = client.newProducer().create(); // triggers MessageCryptoBc init\n} catch (ExceptionInInitializerError | NoClassDefFoundError e) {\n    if (e.getCause() instanceof IllegalStateException\n            && e.getCause().getMessage().contains(\"BCFIPS\")) {\n        throw new IllegalStateException(\"FIPS setup broken: BCFIPS provider present but DEFAULT DRBG unavailable\", e.getCause());\n    }\n    throw e;\n}","preventionTips":["Verify SecureRandom.getInstance(\"DEFAULT\", bcfips) succeeds in a startup health-check when BCFIPS is registered","Keep bc-fips and its approved companion jars (bcpkix-fips, bcutil-fips) at compatible versions and exclude non-FIPS BC artifacts","Register BCFIPS with approved-only mode configured before client startup, not lazily at first use","If FIPS is not a requirement, do not register BCFIPS at all so the NativePRNGNonBlocking path is used","Pin and test the FIPS configuration in CI to catch version drift early"],"tags":["fips","bouncycastle","secure-random","cryptography","class-initialization"],"backgroundTag":"fips-provider-misconfigured","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}