<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>