Subject: Re: [Curdle] AlgorithmIdentifier parameters in draft-ietf-curdle-pkix-03

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 19 Feb 2017 00:26:46 +0200

On Sat, Feb 18, 2017 at 01:15:18PM +0000, str4d wrote:
> Hi all,
> 
> The problem is that the Sun AlgorithmId class always adds a NULL when
> encoding if there are no parameters, for compatibility with Solaris [4].
> So AFAICT it is presently impossible for me to write an implementation
> that simultaneously:
> 
> - follows draft-ietf-curdle-pkix-03 correctly
> - can retrieve EdDSA keys from a default Java keystore
> 
> Is anyone in the WG aware of a workaround for this, or have links to
> past WG discussion on this point? I would think that Oracle should at
> least be made aware of this issue, but even if they changes this in Java
> 10, that doesn't help my implementation run on earlier Java versions.
> The only alternatives I see at this point are:

AlgorithmId.encodeAbsentParametersAsNull(boolean)?

(The first javadoc for AlgorithmId I found has that method).

-Ilari

---

From: str4d <[email-masked]>
Date: Sun, 19 Feb 2017 17:25:59 +0000 (UTC)

> (The first javadoc for AlgorithmId I found has that method).

If I'm looking at the same JavaDoc as you [0], that method is for
iaik.asn1.structures.AlgorithmID, which is part of the proprietary
IAIK-JCE Provider. I am referring to sun.security.x509.AlgorithmId from
the Sun Provider bundled with Oracle Java, which does not have this method.

Having investigated further, it does not look possible to swap out the
Sun Provider's PKCS#8 implementation with another one, because the
default Java keystore directly calls its own classes:

sun.security.provider.JavaKeyStore.engineGetKey() [1]
  \
sun.security.provider.KeyProtector.recover() [2]
    \
sun.security.pkcs.PKCS8Key.parseKey() [3]

However, what *does* look possible is using the JceKeyStore ("jceks"),
which doesn't appear to have the PKCS8Key encode/decode cycle that the
default keystore has (instead it passes the plain key data straight into
the looked-up KeyFactory) [4]. The "jceks" keystore can additionally
read from the default "jks" keystore, so it has a workable migration
strategy. I will test this and see if it is a sufficient workaround. My
concern is that it still uses the same AlgorithmId class that doesn't
support absent parameters, which makes me suspect that while it may read
correctly-formatted keys properly, it might still write them out with
NULL parameters, subverting this entire discussion.

Either way, if the draft is not amended, then Java implementations of
draft-ietf-curdle-pkix-03 will only work with compatible non-default
keystores. The "jceks" is fortunately bundled with Oracle Java, but
still requires configuration. At first glance, it looks like
BouncyCastle might have also a workable alternative keystore (its
AlgorithmId appears to correctly support absent parameters), but that's
not a desirable dependency for at least one of my users.

I'm also still at a loss as to how I can enforce usage of non-default
keystores from inside my library or at a JCA level, in a way that
doesn't result in obscure runtime error messages. The keystore type can
be set or overridden in several places, so I doubt there is a global
value I can reliably check.

- str4d

[0]
http://javadoc.iaik.tugraz.at/iaik_jce/current/iaik/asn1/structures/AlgorithmID.html#encodeAbsentParametersAsNull(boolean)

[1]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/provider/JavaKeyStore.java#115

[2]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/provider/KeyProtector.java#252

[3]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/security/pkcs/PKCS8Key.java#115

[4]
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/com/sun/crypto/provider/KeyProtector.java#148

---

From: Ilari Liusvaara <[email-masked]>
Date: Mon, 20 Feb 2017 00:14:00 +0200

> the Sun Provider bundled with Oracle Java, which does not have this method.

Ah, I found what I presume is code for the correct class.

The problematic method (derEncode) looks like it can take an override
from subclass.

-Ilari

---

From: str4d <[email-masked]>
Date: Mon, 20 Feb 2017 09:46:30 +0000 (UTC)

> The problematic method (derEncode) looks like it can take an override

While that may help for implementing custom keystores outside my
library, it does not solve the incompatibility problem with the default
keystore: PKCS8Key's static methods instantiate the AlgorithmId class
directly, rather than taking an AlgorithmId parameter that could be
subclassed.