Hi!
This issue has already been reported under review ID: JI-9029195, but I haven’t heard anything from it yet. So I thought I’d also try the mailing list. I would like to know at least if my analysis is correct :) I’ve been investigating an issue we ran into after a Java update on one of our products. I think it was introduced here: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/fe1c420a8982 or http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/rev/3e9d6880f36f The latter is the same change, re-applied. JDK 7 and 9 have the same change I think. This would be included in the JRE 'fix' #8081297: "Unable to process PreMasterSecret Tomcat issue", first seen in Java SE 7u85 b34, I think the issue is caused in RSAClientKeyExchange, because of this change: Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); - cipher.init(Cipher.UNWRAP_MODE, privateKey, - new TlsRsaPremasterSecretParameterSpec( - maxVersion.v, currentVersion.v), - generator); - preMaster = (SecretKey)cipher.unwrap(encrypted, - "TlsRsaPremasterSecret", Cipher.SECRET_KEY); + needFailover = !KeyUtil.isOracleJCEProvider( + cipher.getProvider().getName()); + if (needFailover) { + cipher.init(Cipher.DECRYPT_MODE, privateKey); If you condense it, this : Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); cipher.init(…); Has been changed to: Cipher cipher = JsseJce.getCipher(JsseJce.CIPHER_RSA_PKCS1); * cipher.getProvider();* cipher.init(…); 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. For details on delayed provider selection see the source code of Cipher: http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/file/tip/src/share/classes/javax/crypto/Cipher.java 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"). 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 :) For anyone not familiar with delayed provider selection: 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. 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. 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) ;) I can readily provide more details, a self contained example is harder because a hardware based provider is required :) Thank you for your attention! Cheers, Jeroen Cranendonk