[EXTERNAL]Re: NullPointer in JceSecurity.getVerificationResult - Affects JDK 11.07, and JDK 12 and later.
Valerie Peng
valerie.peng at oracle.com
Fri Jun 12 00:07:47 UTC 2020
Hi, John,
Thanks for the reply.
Yes, your understanding is correct. I expect the fix for JDK-8246613
will be backported into other releases.
BTW, if you have spare time for the test provider, it'd help speeding up
the fix for JDK-8246383. If not, it's ok as well. Just may take longer
to get to it.
Regards,
Valerie
On 6/10/2020 1:31 PM, John Gray wrote:
>
> Thanks Valerie!
>
> If I understand you correctly, I think you are saying the fix for
> https://bugs.openjdk.java.net/browse/JDK-8246613 will mean the first
> SecureRandom in the provider will be used as the default (which will
> make it equivalent to JDK 11.06 and previous versions). If that is
> the case, I agree it should mitigate the issue and would be ok with
> lowering the priority of 8246383.
>
> Will this new fix be back-ported into 11 LTS versions as well?
>
> Thanks so much for your amazing fast response. I have been trying to
> set aside some time to put together a simple sample you can use to
> verify 8246383 (that doesn’t require our full toolkit), but haven’t
> been able to find the time to do that yet.
>
> Cheers,
>
> John Gray
>
> *From:*Valerie Peng [mailto:valerie.peng at oracle.com]
> *Sent:* Wednesday, June 10, 2020 4:14 PM
> *To:* John Gray <John.Gray at entrustdatacard.com>;
> security-dev at openjdk.java.net
> *Cc:* Muthu Kannappan <muthu at entrustdatacard.com>; Raj Arora
> <Raj.Arora at entrustdatacard.com>
> *Subject:* [EXTERNAL]Re: NullPointer in
> JceSecurity.getVerificationResult - Affects JDK 11.07, and JDK 12 and
> later.
>
> *WARNING:* This email originated outside of Entrust Datacard.
> *DO NOT CLICK* links or attachments unless you trust the sender and
> know the content is safe.
>
> ------------------------------------------------------------------------
>
> Hi John,
>
> As you may have noticed, we are progressing a fix for
> https://bugs.openjdk.java.net/browse/JDK-8246613
> <https://bugs.openjdk.java.net/browse/JDK-8246613> for returning the
> same default SecureRandom algo for 3rd party providers as in
> pre-JDK7092821 releases. Thus, the chance of observing JDK-8246613
> should be lowered significantly. Given this, I plan to lower the
> priority of JDK-8246383 and it may not be fixed in JDK 15 as earlier
> communicated.
>
> If this will be an issue, please let me know.
>
> Thanks,
> Valerie
>
> On 6/2/2020 4:37 PM, Valerie Peng wrote:
>
> Thanks for reporting the bug and the detailed analysis.
>
> I have filed https://bugs.openjdk.java.net/browse/JDK-8246383 to
> keep track of this. Will aim to fix this for 15 and have it
> backported accordingly.
>
> Is it possible to get hold of an test provider to reproduce and
> verifying the fix?
>
> Regards,
>
> Valerie
>
> On 6/2/2020 1:18 PM, John Gray wrote:
>
> Hello,
>
> At Entrust Datacard, we produce a Java based toolkit that
> contains our own Security Provider. This toolkit and
> provider has been around for about 19 years.
>
> In JDK version 11.07 (and I also think Java 12 and beyond),
> our toolkit reports the following error:
>
> java.lang.RuntimeException:
> java.security.NoSuchAlgorithmException: Error constructing
> implementation (algorithm: X9_31usingAES256, provider:
> Entrust, class:
> com.entrust.toolkit.security.crypto.random.X9_31usingAES256)
> at
> java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:281)
> at
> java.base/java.security.SecureRandom.<init>(SecureRandom.java:219)
> at
> java.base/javax.crypto.JceSecurity.<clinit>(JceSecurity.java:80)
> ... 41 more
> Caused by: java.security.NoSuchAlgorithmException: Error
> constructing implementation (algorithm: X9_31usingAES256,
> provider: Entrust, class:
> com.entrust.toolkit.security.crypto.random.X9_31usingAES256)
> at
> java.base/java.security.Provider$Service.newInstance(Provider.java:1825)
> at
> java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
> at
> java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
> at
> java.base/java.security.SecureRandom.getInstance(SecureRandom.java:365)
> at
> java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:273)
> ... 43 more
> Caused by: java.lang.NullPointerException
> at
> java.base/javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:203)
> at java.base/javax.crypto.Cipher.getInstance(Cipher.java:690)
> at java.base/javax.crypto.Cipher.getInstance(Cipher.java:625)
> at
> com.entrust.toolkit.security.crypto.random.X9_31usingAES256.initialize(X9_31usingAES256.java:524)
> at
> com.entrust.toolkit.security.crypto.random.X9_31usingAES256.<init>(X9_31usingAES256.java:102)
> at
> java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
> Method)
> at
> java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
> at
> java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
> at
> java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
> at
> java.base/java.security.Provider.newInstanceUtil(Provider.java:176)
> at
> java.base/java.security.Provider$Service.newInstance(Provider.java:1818)
>
> I investigated this error, and found it was made possible
> because of the following change in Java 11.07 which unmasked a
> bug in the JVM that has probably been around for years.
>
> https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8228613
>
> It is a problem inside the JceSecurity class. When the class
> is being loaded, the call to setup a default SecureRandom()
> instance is invoked. That seems to invoke the JVM to find
> the first available SecureRandom() instance. This error
> happens when our Entrust provider is in first position. In
> previous versions of the JDK it honoured the order of
> algorithms specified in the providers. In our Entrust
> Security provider, we have a number of SecureRandom
> implementations. Now because of the above change, it picks a
> different SecureRandom instance (the X9_31usingAES256). That
> should be fine, however the problem is that the SecureRandom()
> setup calls Cipher.getInstance() and as you can see below,
> that calls JceSecurity.getVerificationResult() which is
> static, and uses the verificationResuts Map that has not yet
> been initialized (becasuse it’s declaration is after the
> SecureRandom setup). That is why there is a
> NullPointerException.
>
> *public* *static* *final* Cipher getInstance(String
> transformation,
>
> Provider provider)
>
> *throws* NoSuchAlgorithmException, NoSuchPaddingException
>
> {
>
> *if* ((transformation == *null*) || transformation.equals("")) {
>
> *throw* *new* NoSuchAlgorithmException("Null or empty
> transformation");
>
> }
>
> *if* (provider == *null*) {
>
> *throw* *new* IllegalArgumentException("Missing provider");
>
> }
>
> Exception failure = *null*;
>
> List<Transform> transforms =
> getTransforms(transformation);
>
> *boolean* providerChecked = *false*;
>
> String paddingError = *null*;
>
> *for* (Transform tr : transforms) {
>
> Service s = provider.getService("Cipher",
> tr.transform);
>
> *if* (s == *null*) {
>
> *continue*;
>
> }
>
> *if* (providerChecked == *false*) {
>
> // for compatibility, first do the lookup and
> then verify
>
> // the provider. this makes the difference
> between a NSAE
>
> // and a SecurityException if the
>
> // provider does not support the algorithm.
>
> Exception ve =
> JceSecurity.getVerificationResult(provider);
>
> *if* (ve != *null*) {
>
> String msg = "JCE cannot authenticate the
> provider "
>
> + provider.getName();
>
> *throw* *new* SecurityException(msg, ve);
>
> }
>
> providerChecked = *true*;
>
> }
>
> The JceSecurity.getVerificationResult(provider) method is used
> when initializing the SecureRandom (first highlighted line
> below) when the classLoader is loading the JceSecurity class
> itself.
>
> From the JceSecurity class:
>
> *static* *final* SecureRandom RANDOM = *new* SecureRandom();
>
> // The defaultPolicy and exemptPolicy will be set up
>
> // in the static initializer.
>
> *private* *static* CryptoPermissions defaultPolicy = *null*;
>
> *private* *static* CryptoPermissions exemptPolicy = *null*;
>
> // Map<Provider,?> of the providers we already have verified
>
> // value == PROVIDER_VERIFIED is successfully verified
>
> // value is failure cause Exception in error case
>
> *private* *static* *final* Map<Provider, Object>
> verificationResults =
>
> *new* IdentityHashMap<>();
>
> It fails when it calls the following code in JceSecurity.java
> because the verificationResults Map<Provider, Object> has not
> been initialized because the SecureRandom() constructor ends
> up calling the JceSecurity.getVerificationResult() static
> method that makes use of the Map! That explains the
> NullPointerException.
>
> The fix to the issue should be simple, just move the
> initialization of the verificationResults Map BEFORE the
> SecureRandom initialization in JceSecurity.java
>
> Because verificationResults is not initialized, the line
> highlighted below fails (Because the Map has not been
> initialized).
>
> /*
>
> * Verify that the provider JAR files are signed properly,
> which
>
> * means the signer's certificate can be traced back to a
>
> * JCE trusted CA.
>
> * Return null if ok, failure Exception if verification
> failed.
>
> */
>
> *static* *synchronized* Exception
> getVerificationResult(Provider p) {
>
> Object o = verificationResults.get(p);
>
> *if* (o == PROVIDER_VERIFIED) {
>
> *return* *null*;
>
> } *else* *if* (o != *null*) {
>
> *return* (Exception)o;
>
> }
>
> *if* (verifyingProviders.get(p) != *null*) {
>
> // this method is static synchronized, must be
> recursion
>
> // return failure now but do not save the result
>
> *return* *new* NoSuchProviderException("Recursion during
> verification");
>
> }
>
> *try* {
>
> verifyingProviders.put(p, Boolean.FALSE);
>
> URL providerURL = getCodeBase(p.getClass());
>
> verifyProvider(providerURL, p);
>
> // Verified ok, cache result
>
> verificationResults.put(p, PROVIDER_VERIFIED);
>
> *return* *null*;
>
> } *catch* (Exception e) {
>
> verificationResults.put(p, e);
>
> *return* e;
>
> } *finally* {
>
> verifyingProviders.remove(p);
>
> }
>
> }
>
> Cheers,
>
> John Gray
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20200611/e9e43b8b/attachment.htm>
More information about the security-dev
mailing list