New issue HW based providers (e.g. PKCS11) + SSL.

Jeroen Cranendonk j.p.cranendonk at gmail.com
Wed Feb 10 12:32:13 UTC 2016


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/security-dev/attachments/20160210/e21eb022/attachment.htm>


More information about the security-dev mailing list