Hi Ioannis,
Thanks for reporting this issue and the detailed info.
I've filed https://bugs.openjdk.java.net/browse/JDK-8248505 for this. It
seems that this is mostly due to the mixing of both legacy and
service-based registration in the BC provider not working well with the
fix in JDK-8246613. Another possible fix may be to prefer the
SecureRandom service object from the putService call. Anyway, I will
take a look.
Regards,
Valerie
On 6/28/2020 10:14 PM, Ioannis Kakavas wrote:
Hi folks,
Since the latest changes to SecureRandom[0], using certain ( I can reproduce
with one but others might have the same issue, see below ) security providers,
it is impossible to get an instance of SecurityRandom. The following is
reproducible with the BouncyCastle FIPS 140-2 provider [1]:
public class TestSecureRandom {
public static void main(String[] args){
assert Security.getProviders()[0].getName().equals("BCFIPS");
SecureRandom random = new SecureRandom();
}
}
will fail with
Exception in thread "main" java.lang.RuntimeException:
java.security.NoSuchAlgorithmException: Service not registered with Provider BCFIPS: BCFIPS:
SecureRandom.DEFAULT -> org.bouncycastle.jcajce.provider.random.DefSecureRandom
attributes: {ImplementedIn=Software}
at
java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:294)
at java.base/java.security.SecureRandom.<init>(SecureRandom.java:219)
at TestSecureRandomBug.main(TestSecureRandomBug.java:8)
Caused by: java.security.NoSuchAlgorithmException: Service not registered with
Provider BCFIPS: BCFIPS: SecureRandom.DEFAULT ->
org.bouncycastle.jcajce.provider.random.DefSecureRandom
attributes: {ImplementedIn=Software}
at
java.base/java.security.Provider$Service.newInstance(Provider.java:1857)
at
java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:290)
... 2 more
I reported this to the authors of the security provider [2] and I will share
part of the analysis on why this fails here for the sake of completeness of the
report.
The BCFIPS security provider overrides getService() and getServices() of
Provider and it has its own extension of the Provider.Service which
getService() returns.
However, getDefaultSecureRandomService() will always return a
java.security.Provider.Service and since we are calling newInstance [3] on it,
this fails as the
if (provider.getService(type, algorithm) != this) {
throw new NoSuchAlgorithmException("Service not registered with Provider " +
provider.getName() + ": " + this);
}
can not be true. getService will return a
org.bouncycastle.jcajce.provider.BouncyCastleFipsProvider.BcService and `this`
is a java.security.Provider.Service.
I am not aware of other providers being affected by this ( the non FIPS
BouncyCastle Provider is not, since it's a legacy style security provider ) but
given the reason for the issue, I think there might be others affected. With
[0] being backported to all supported versions and BCFIPS being one of the few
available security providers that is FIPS 140-2 approved, this introduces a
significant issue for folks with fips compliance requirements.
One potential fix that was proposed in [2] was to replace
if (prngServices != null && !prngServices.isEmpty()) {
return prngServices.iterator().next();
}
with:
if (prngServices != null && !prngServices.isEmpty()) {
Service rng = prngServices.iterator().next();
return getService(rng.getType(), rng.getAlgorithm());
}
so that any provider extending Service, could work fine.
Best Regards
Ioannis
[0] https://hg.openjdk.java.net/jdk/jdk15/rev/6eeaa40131ff
[1] https://www.bouncycastle.org/fips-java/
[2]
http://bouncy-castle.1462172.n4.nabble.com/Default-SecureRandom-issue-in-BCFIPS-and-latest-JDK15-td4659964.html
[3] https://hg.openjdk.java.net/jdk/jdk15/rev/6eeaa40131ff#l2.55