<div dir="ltr"><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Hi!<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">This issue has already been reported under review ID: JI-9029195, but I haven’t heard anything from it yet.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">So I thought I’d also try the mailing list. I would like to know at least if my analysis is correct :)<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">I’ve been investigating an issue we ran into after a Java update on one of our products.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">I think it was introduced here:<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/fe1c420a8982" target="_blank">http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/fe1c420a8982</a> or <a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3e9d6880f36f" target="_blank">http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3e9d6880f36f</a><u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">The latter is the same change, re-applied. JDK 7 and 9 have the same change I think.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">This would be included in the JRE 'fix' #8081297: "Unable to process PreMasterSecret Tomcat issue", first seen in Java SE 7u85 b34,<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">I think the issue is caused in RSAClientKeyExchange, because of this change:<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">             Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span lang="FR" style="font-size:10pt;font-family:'Courier New'">-            cipher.init(Cipher.UNWRAP_MODE, privateKey,<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">-                    new TlsRsaPremasterSecretParameterSpec(<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">-                            maxVersion.v, currentVersion.v),<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">-                    generator);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">-            preMaster = (SecretKey)cipher.unwrap(encrypted,<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">-                                "TlsRsaPremasterSecret", Cipher.SECRET_KEY);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">+            needFailover = !KeyUtil.isOracleJCEProvider(<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">+                                        cipher.getProvider().getName());<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">+            if (needFailover) {<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span lang="FR" style="font-size:10pt;font-family:'Courier New'">+                cipher.init(Cipher.DECRYPT_MODE, privateKey);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span lang="FR"><u></u> <u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">If you condense it, this :<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">   Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">   cipher.init(…);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Has been changed to:<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">   Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><b><span style="font-size:10pt;font-family:'Courier New'">   cipher.getProvider();<u></u><u></u></span></b></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><span style="font-size:10pt;font-family:'Courier New'">   cipher.init(…);<u></u><u></u></span></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">The problem is that calling getProvider, or any method on a Cipher instance, forces it to skip the delayed provider selection which is built into Cipher.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">For details on delayed provider selection see the source code of Cipher:<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><a href="http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/share/classes/javax/crypto/Cipher.java" target="_blank">http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/share/classes/javax/crypto/Cipher.java</a><u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Especially the chooseFirstProvider() method, which also has debug logging for this specific case. (Using "-Djava.security.debug=jca" you should get the message "Cipher: Cipher.init() not first method called").<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">In many cases this won’t cause a problem, but when using a hardware token based provider (e.g. PKCS11), this can cause SSL connections to fail being set up, especially if it’s not the first provider in the list of security providers. For my current customer this is a big problem, because they use hardware tokens for everything :)<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">For anyone not familiar with delayed provider selection:<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">It means that when a Cipher instance is created, it doesn’t know yet which provider it will be using, because we haven’t provided it with the key it should use yet. Once we call it’s init method, with the key to use, it is able to select a provider. It will try every available provider implementing the selected algorithm, and will keep trying until it find one which can use the key: It doesn’t throw a InvalidKeyException.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">This is important for hardware based providers like PKCS11, because they use key’s which are a handle to the key stored in hardware, and only their own Cipher can handle this key.<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">I would really like to know if my assessment is accurate. I would also really like to know how to make sure this gets fixed in a timely manner (I understand that the most optimistic ‘timely’ would be the next JRE release, or the one after that) ;)<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u> <u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">I can readily provide more details, a self contained example is harder because a hardware based provider is required :)</p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><br></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Thank you for your attention!<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><br></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Cheers,<u></u><u></u></p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif">Jeroen Cranendonk</p><p class="MsoNormal" style="margin:0cm 0cm 0.0001pt;font-size:11pt;font-family:Calibri,sans-serif"><br></p></div>