<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
</head>
<body>
<p>Hi, John,</p>
<p>Thanks for the reply.</p>
<p>Yes, your understanding is correct. I expect the fix for
JDK-8246613 will be backported into other releases.</p>
<p>BTW, if you have spare time for the test provider, it'd help
speeding up the fix for JDK-<span>8246383. If not, it's ok as
well. Just may take longer to get to it.</span></p>
<span>Regards,<br>
</span><br>
Valerie<br>
<div class="moz-cite-prefix">On 6/10/2020 1:31 PM, John Gray wrote:<br>
</div>
<blockquote type="cite"
cite="mid:DM6PR11MB2585C911E863BEEC21F05CA5EE830@DM6PR11MB2585.namprd11.prod.outlook.com">
<meta name="Generator" content="Microsoft Word 15 (filtered
medium)">
<div class="WordSection1">
<p class="MsoNormal"><span>Thanks Valerie!</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>If I understand you correctly, I
think you are saying the fix for
</span><span><a
href="https://bugs.openjdk.java.net/browse/JDK-8246613"
moz-do-not-send="true"><span>https://bugs.openjdk.java.net/browse/JDK-8246613</span></a>
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.
</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>Will this new fix be back-ported into
11 LTS versions as well?
</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>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.</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>Cheers,</span></p>
<p class="MsoNormal"><span> </span></p>
<p class="MsoNormal"><span>John Gray</span></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><span> </span></p>
<div>
<div>
<p class="MsoNormal"><b><span>From:</span></b><span> Valerie
Peng [<a class="moz-txt-link-freetext" href="mailto:valerie.peng@oracle.com">mailto:valerie.peng@oracle.com</a>]
<br>
<b>Sent:</b> Wednesday, June 10, 2020 4:14 PM<br>
<b>To:</b> John Gray
<a class="moz-txt-link-rfc2396E" href="mailto:John.Gray@entrustdatacard.com"><John.Gray@entrustdatacard.com></a>;
<a class="moz-txt-link-abbreviated" href="mailto:security-dev@openjdk.java.net">security-dev@openjdk.java.net</a><br>
<b>Cc:</b> Muthu Kannappan
<a class="moz-txt-link-rfc2396E" href="mailto:muthu@entrustdatacard.com"><muthu@entrustdatacard.com></a>; Raj Arora
<a class="moz-txt-link-rfc2396E" href="mailto:Raj.Arora@entrustdatacard.com"><Raj.Arora@entrustdatacard.com></a><br>
<b>Subject:</b> [EXTERNAL]Re: NullPointer in
JceSecurity.getVerificationResult - Affects JDK 11.07,
and JDK 12 and later.</span></p>
</div>
</div>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><strong><span>WARNING:</span></strong> This
email originated outside of Entrust Datacard.<br>
<strong><span>DO NOT CLICK</span></strong> links or
attachments unless you trust the sender and know the content
is safe.</p>
<div class="MsoNormal">
<hr width="100%">
</div>
<p>Hi John,</p>
<p>As you may have noticed, we are progressing a fix for <a
href="https://bugs.openjdk.java.net/browse/JDK-8246613"
moz-do-not-send="true">
https://bugs.openjdk.java.net/browse/JDK-8246613</a> 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.
</p>
<p>If this will be an issue, please let me know.</p>
<p class="MsoNormal">Thanks,<br>
Valerie</p>
<div>
<p class="MsoNormal">On 6/2/2020 4:37 PM, Valerie Peng wrote:</p>
</div>
<blockquote>
<p>Thanks for reporting the bug and the detailed analysis.</p>
<p>I have filed <a
href="https://bugs.openjdk.java.net/browse/JDK-8246383"
moz-do-not-send="true">https://bugs.openjdk.java.net/browse/JDK-8246383</a>
to keep track of this. Will aim to fix this for 15 and have
it backported accordingly.</p>
<p>Is it possible to get hold of an test provider to reproduce
and verifying the fix?</p>
<p>Regards,</p>
<p class="MsoNormal">Valerie</p>
<div>
<p class="MsoNormal">On 6/2/2020 1:18 PM, John Gray wrote:</p>
</div>
<blockquote>
<div>
<p class="MsoNormal">Hello,</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">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.
</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">In JDK version 11.07 (and I also
think Java 12 and beyond), our toolkit reports the
following error:</p>
<p class="MsoNormal">java.lang.RuntimeException:
java.security.NoSuchAlgorithmException: Error
constructing implementation (algorithm:
X9_31usingAES256, provider: Entrust, class:
com.entrust.toolkit.security.crypto.random.X9_31usingAES256)<br>
at
java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:281)<br>
at
java.base/java.security.SecureRandom.<init>(SecureRandom.java:219)<br>
at
java.base/javax.crypto.JceSecurity.<clinit>(JceSecurity.java:80)<br>
... 41 more<br>
Caused by: java.security.NoSuchAlgorithmException: Error
constructing implementation (algorithm:
X9_31usingAES256, provider: Entrust, class:
com.entrust.toolkit.security.crypto.random.X9_31usingAES256)<br>
at
java.base/java.security.Provider$Service.newInstance(Provider.java:1825)<br>
at
java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:236)<br>
at
java.base/sun.security.jca.GetInstance.getInstance(GetInstance.java:164)<br>
at
java.base/java.security.SecureRandom.getInstance(SecureRandom.java:365)<br>
at
java.base/java.security.SecureRandom.getDefaultPRNG(SecureRandom.java:273)<br>
... 43 more<br>
Caused by: java.lang.NullPointerException<br>
at
java.base/javax.crypto.JceSecurity.getVerificationResult(JceSecurity.java:203)<br>
at
java.base/javax.crypto.Cipher.getInstance(Cipher.java:690)<br>
at
java.base/javax.crypto.Cipher.getInstance(Cipher.java:625)<br>
at
com.entrust.toolkit.security.crypto.random.X9_31usingAES256.initialize(X9_31usingAES256.java:524)<br>
at
com.entrust.toolkit.security.crypto.random.X9_31usingAES256.<init>(X9_31usingAES256.java:102)<br>
at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native
Method)<br>
at
java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)<br>
at
java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)<br>
at
java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)<br>
at
java.base/java.security.Provider.newInstanceUtil(Provider.java:176)<br>
at
java.base/java.security.Provider$Service.newInstance(Provider.java:1818)</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">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.</p>
<p class="MsoNormal"><a
href="https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8228613"
target="_blank" moz-do-not-send="true">https://bugs.java.com/bugdatabase/view_bug.do?bug_id=JDK-8228613</a></p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">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.</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><b>public</b>
<b>static</b> <b>final</b> Cipher getInstance(String
transformation,</p>
<p class="MsoNormal">
Provider provider)</p>
<p class="MsoNormal">
<b>throws</b> NoSuchAlgorithmException,
NoSuchPaddingException</p>
<p class="MsoNormal"> {</p>
<p class="MsoNormal">
<b>if</b> ((transformation == <b>null</b>) ||
transformation.equals("")) {</p>
<p class="MsoNormal">
<b>throw</b> <b>new</b> NoSuchAlgorithmException("Null
or empty transformation");</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal">
<b>if</b> (provider == <b>null</b>) {</p>
<p class="MsoNormal">
<b>throw</b> <b>new</b>
IllegalArgumentException("Missing provider");</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal"> Exception failure =
<b>null</b>;</p>
<p class="MsoNormal"> List<Transform>
transforms = getTransforms(transformation);</p>
<p class="MsoNormal">
<b>boolean</b> providerChecked = <b>false</b>;</p>
<p class="MsoNormal"> String paddingError =
<b>null</b>;</p>
<p class="MsoNormal">
<b>for</b> (Transform tr : transforms) {</p>
<p class="MsoNormal"> Service s =
provider.getService("Cipher", tr.transform);</p>
<p class="MsoNormal">
<b>if</b> (s == <b>null</b>) {</p>
<p class="MsoNormal">
<b>continue</b>;</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal">
<b>if</b> (providerChecked == <b>false</b>) {</p>
<p class="MsoNormal"> // for compatibility,
first do the lookup and then verify</p>
<p class="MsoNormal"> // the provider. this
makes the difference between a NSAE</p>
<p class="MsoNormal"> // and a
SecurityException if the</p>
<p class="MsoNormal"> // provider does not
support the algorithm.</p>
<p class="MsoNormal"> Exception ve =
JceSecurity.getVerificationResult(provider);</p>
<p class="MsoNormal"> <b>if</b> (ve !=
<b>null</b>) {</p>
<p class="MsoNormal"> String msg = "JCE
cannot authenticate the provider "</p>
<p class="MsoNormal"> +
provider.getName();</p>
<p class="MsoNormal">
<b>throw</b> <b>new</b> SecurityException(msg, ve);</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal"> providerChecked =
<b>true</b>;</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">The
JceSecurity.getVerificationResult(provider) method is
used when initializing the SecureRandom (first
highlighted line below) when the classLoader is loading
the JceSecurity class itself. </p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">From the JceSecurity class:</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"><b>static</b>
<b>final</b> SecureRandom RANDOM = <b>new</b>
SecureRandom();</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> // The defaultPolicy and
exemptPolicy will be set up</p>
<p class="MsoNormal"> // in the static initializer.</p>
<p class="MsoNormal">
<b>private</b> <b>static</b> CryptoPermissions
defaultPolicy = <b>null</b>;</p>
<p class="MsoNormal">
<b>private</b> <b>static</b> CryptoPermissions
exemptPolicy = <b>null</b>;</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> // Map<Provider,?> of the
providers we already have verified</p>
<p class="MsoNormal"> // value == PROVIDER_VERIFIED is
successfully verified</p>
<p class="MsoNormal"> // value is failure cause
Exception in error case</p>
<p class="MsoNormal">
<b>private</b> <b>static</b> <b>final</b>
Map<Provider, Object> verificationResults =</p>
<p class="MsoNormal">
<b>new</b> IdentityHashMap<>();</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">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.
</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">The fix to the issue should be
simple, just move the initialization of the
verificationResults Map BEFORE the SecureRandom
initialization in JceSecurity.java</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">Because verificationResults is not
initialized, the line highlighted below fails (Because
the Map has not been initialized).</p>
<p class="MsoNormal">/*</p>
<p class="MsoNormal"> * Verify that the provider JAR
files are signed properly, which</p>
<p class="MsoNormal"> * means the signer's certificate
can be traced back to a</p>
<p class="MsoNormal"> * JCE trusted CA.</p>
<p class="MsoNormal"> * Return null if ok, failure
Exception if verification failed.</p>
<p class="MsoNormal"> */</p>
<p class="MsoNormal">
<b>static</b> <b>synchronized</b> Exception
getVerificationResult(Provider p) {</p>
<p class="MsoNormal"> Object o =
verificationResults.get(p);</p>
<p class="MsoNormal">
<b>if</b> (o == PROVIDER_VERIFIED) {</p>
<p class="MsoNormal">
<b>return</b> <b>null</b>;</p>
<p class="MsoNormal"> }
<b>else</b> <b>if</b> (o != <b>null</b>) {</p>
<p class="MsoNormal">
<b>return</b> (Exception)o;</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal">
<b>if</b> (verifyingProviders.get(p) != <b>null</b>) {</p>
<p class="MsoNormal"> // this method is static
synchronized, must be recursion</p>
<p class="MsoNormal"> // return failure now but
do not save the result</p>
<p class="MsoNormal">
<b>return</b> <b>new</b>
NoSuchProviderException("Recursion during
verification");</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal">
<b>try</b> {</p>
<p class="MsoNormal"> verifyingProviders.put(p,
Boolean.FALSE);</p>
<p class="MsoNormal"> URL providerURL =
getCodeBase(p.getClass());</p>
<p class="MsoNormal">
verifyProvider(providerURL, p);</p>
<p class="MsoNormal"> // Verified ok, cache
result</p>
<p class="MsoNormal">
verificationResults.put(p, PROVIDER_VERIFIED);</p>
<p class="MsoNormal">
<b>return</b> <b>null</b>;</p>
<p class="MsoNormal"> }
<b>catch</b> (Exception e) {</p>
<p class="MsoNormal">
verificationResults.put(p, e);</p>
<p class="MsoNormal">
<b>return</b> e;</p>
<p class="MsoNormal"> }
<b>finally</b> {</p>
<p class="MsoNormal">
verifyingProviders.remove(p);</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal"> }</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">Cheers,</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal">John Gray</p>
<p class="MsoNormal">
</p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> </p>
<p class="MsoNormal"> </p>
</div>
</blockquote>
</blockquote>
</div>
</blockquote>
</body>
</html>