I am trying to create a CMS Enveloped encrypted message using BouncyCastle FIPS 1.0.0 for Java. I receive the following error indicating that it is trying to use AES for random number generation (which is not an approved algorithm for FIPS mode).
Exception in thread "main" org.bouncycastle.crypto.fips.FipsUnapprovedOperationError: Attempt to create key with unapproved RNG: AES
at org.bouncycastle.crypto.fips.Utils.validateRandom(Unknown Source)
at org.bouncycastle.crypto.fips.Utils.validateKeyGenRandom(Unknown Source)
at org.bouncycastle.crypto.fips.FipsAES$KeyGenerator.<init>(Unknown Source)
at org.bouncycastle.crypto.fips.FipsAES$KeyGenerator.<init>(Unknown Source)
at org.bouncycastle.jcajce.provider.ProvAES$39$1.createInstance(Unknown Source)
at org.bouncycastle.jcajce.provider.BaseKeyGenerator.engineInit(Unknown Source)
at javax.crypto.KeyGenerator.init(KeyGenerator.java:510)
at org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder$CMSOutputEncryptor.<init>(Unknown Source)
at org.bouncycastle.cms.jcajce.JceCMSContentEncryptorBuilder.build(Unknown Source)
First, I make sure BouncyCastle is loaded as a JCE provider and then I make sure that it is running in FIPS approved only mode.
if(!CryptoServicesRegistrar.isInApprovedOnlyMode()) {
CryptoServicesRegistrar.setApprovedOnlyMode(true);
}
After that I am basically just using code like the example in the BC FIPS in 100 mini-book. The code I have so far is as follows:
private static final String FIPS_PROVIDER = "BCFIPS";
public byte[] encrypt(X509Certificate cert, byte[] dataToEncrypt) throws CertificateEncodingException, CMSException, IOException, InvalidAlgorithmParameterException {
CMSEnvelopedDataGenerator envelopedGen = new CMSEnvelopedDataGenerator();
JcaAlgorithmParametersConverter paramsConverter = new JcaAlgorithmParametersConverter();
AlgorithmIdentifier algId = paramsConverter.getAlgorithmIdentifier(PKCSObjectIdentifiers.id_RSAES_OAEP, OAEPParameterSpec.DEFAULT);
JceKeyTransRecipientInfoGenerator recipientInfo = new JceKeyTransRecipientInfoGenerator(cert, algId);
recipientInfo.setProvider(FIPS_PROVIDER);
envelopedGen.addRecipientInfoGenerator(recipientInfo);
CMSProcessableByteArray processableArray = new CMSProcessableByteArray(dataToEncrypt);
JceCMSContentEncryptorBuilder encryptorBuilder = new JceCMSContentEncryptorBuilder(CMSAlgorithm.AES256_CBC);
encryptorBuilder.setProvider(FIPS_PROVIDER);
OutputEncryptor outputEncryptor = encryptorBuilder.build();
return envelopedGen.generate(processableArray, outputEncryptor).getEncoded();
}
If I do not put BouncyCastle into the FIPS approved only mode then this code works fine, but I need to be able to run in this mode. Is there some way to tell the CMSOutputEncryptor to use a different RNG algorithm?
Have you tried setting up a FIPS-approved SecureRandom?
CryptoServicesRegistrar.setSecureRandom(
new FipsDRBG.Builder(
new BasicEntropySourceProvider(new SecureRandom(), true))
.build(FipsDRBG.SHA512_HMAC, null, false)
);
then on your builder (and wherever else you may need it):
encryptorBuilder.setSecureRandom(CryptoServicesRegistrar.getSecureRandom());