In OpenJDK6, the elliptic curve cryptography algorithms are available
if the PKCS11 provider is configured to point to NSS. See:

http://blogs.sun.com/andreas/entry/the_java_pkcs_11_provider

If NSS is configured as specified in this blog, keytool can be used to
generate a key as follows:

$ keytool -v -genkeypair -keyalg EC -keysize 256 -keystore ectest.jks
-storepass test12 -dname "CN=ECC Test"

With NSS 3.12.3 (the current version), this fails as follows:

java.lang.RuntimeException: Could not parse key values
        at 
sun.security.pkcs11.P11Key$P11ECPublicKey.fetchValues(P11Key.java:1028)
        at 
sun.security.pkcs11.P11Key$P11ECPublicKey.getEncodedInternal(P11Key.java:1038)
        at sun.security.pkcs11.P11Key.getEncoded(P11Key.java:126)
        at 
sun.security.x509.CertificateX509Key.encode(CertificateX509Key.java:105)
        at sun.security.x509.X509CertInfo.emit(X509CertInfo.java:819)
        at sun.security.x509.X509CertInfo.encode(X509CertInfo.java:189)
        at sun.security.x509.X509CertImpl.sign(X509CertImpl.java:528)
        at sun.security.x509.X509CertImpl.sign(X509CertImpl.java:486)
        at 
sun.security.x509.CertAndKeyGen.getSelfCertificate(CertAndKeyGen.java:288)
        at sun.security.tools.KeyTool.doGenKeyPair(KeyTool.java:1223)
        at sun.security.tools.KeyTool.doCommands(KeyTool.java:827)
        at sun.security.tools.KeyTool.run(KeyTool.java:194)
        at sun.security.tools.KeyTool.main(KeyTool.java:188)
Caused by: java.io.IOException: Point does not match field size
        at sun.security.ec.ECParameters.decodePoint(ECParameters.java:95)
        at 
sun.security.pkcs11.P11ECKeyFactory.decodePoint(P11ECKeyFactory.java:78)
        at 
sun.security.pkcs11.P11Key$P11ECPublicKey.fetchValues(P11Key.java:1023)
        ... 12 more

I did a bit of debugging, and the exception is caused by the array
generated by NSS being too large (for a keysize of 256, its size is 67
rather than 65).

Looking at the NSS code, it turns out that it handles a case which the
code in ECParameters.decodePoint doesn't:

           /* special note: We can't just use the first byte to
determine
             * between these 2 cases because both
EC_POINT_FORM_UNCOMPRESSED
             * and SEC_ASN1_OCTET_STRING are 0x04 */

            /* handle the non-DER encoded case (UNCOMPRESSED only) */
            if (pubKey->u.ec.publicValue.data[0] == EC_POINT_FORM_UNCOMPRESSED
                && pubKey->u.ec.publicValue.len == keyLen) {
                break; /* key was not DER encoded, no need to unwrap */
            }

            /* if we ever support compressed, handle it here */

            /* handle the encoded case */
            if ((pubKey->u.ec.publicValue.data[0] == SEC_ASN1_OCTET_STRING)
                && pubKey->u.ec.publicValue.len > keyLen) {
                SECItem publicValue;
                SECStatus rv;

                rv = SEC_QuickDERDecodeItem(arena, &publicValue,
                                         SEC_ASN1_GET(SEC_OctetStringTemplate),
                                         &pubKey->u.ec.publicValue);
                /* nope, didn't decode correctly */
                if ((rv != SECSuccess)
                    || (publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED)
                    || (publicValue.len != keyLen)) {
                    crv = CKR_ATTRIBUTE_VALUE_INVALID;
                    break;
                }
                /* replace our previous with the decoded key */
                pubKey->u.ec.publicValue = publicValue;
                break;
            }

The code in decodePoint, by comparison, assumes that a block beginning
with 0x04 is uncompressed, then throws an exception because the array
is too large.  The fact is that the array returned by NSS is DER
encoded, and this encoding specifies an octet string using a header of
0x04.  Luckily enough, there is a DER encoder in sun.security.util
which can decode this and with the following webrev:

http://cr.openjdk.java.net/~andrew/ec/webrev.01/jdk.patch

we can quite easily support this format.

With the patch applied:

$ keytool -v -genkeypair -keyalg EC -keysize 256 -keystore ectest.jks
-storepass test12 -dname "CN=ECC Test"
Generating 256 bit EC key pair and self-signed certificate
(SHA1withECDSA) with a validity of 90 days
        for: CN=ECC Test
Enter key password for <mykey>
        (RETURN if same as keystore password):
[Storing ectest.jks]

$ keytool -v -list -keystore ectest.jks -storepass test12 -dname "CN=ECC Test"

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

Alias name: mykey
Creation date: 27-Aug-2009
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=ECC Test
Issuer: CN=ECC Test
Serial number: 4a97068b
Valid from: Thu Aug 27 23:19:55 BST 2009 until: Wed Nov 25 22:19:55 GMT 2009
Certificate fingerprints:
         MD5:  10:39:9E:CA:11:50:CD:BF:61:BC:16:1F:B2:43:52:E6
         SHA1: F7:8F:80:77:48:51:C6:3B:49:89:28:A8:5E:5F:7C:ED:D1:BD:CF:BE
         Signature algorithm name: SHA1withECDSA
         Version: 3


*******************************************
*******************************************

key creation works fine.

The code has been refactored in 7 and the NSS source code included
(ugh) so this bug isn't triggered there:

keytool -v -genkeypair -keyalg EC -keysize 256 -keystore ectest.jks
-storepass test12 -dname "CN=ECC Test"
Generating 256 bit EC key pair and self-signed certificate
(SHA1withECDSA) with a validity of 90 days
        for: CN=ECC Test
Enter key password for <mykey>
        (RETURN if same as keystore password):
New certificate (self-signed):
[
[
  Version: V3
  Subject: CN=ECC Test
  Signature Algorithm: SHA1withECDSA, OID = 1.2.840.10045.4.1

  Key:  Sun EC public key, 256 bits
  public x coord:
111384255692518988314535813062807496116713232200028578473047050707653587930695
  public y coord:
64522353781112987171728292648151233343880335217175194500175071174794420240032
  parameters: secp256r1 [NIST P-256, X9.62 prime256v1] (1.2.840.10045.3.1.7)
  Validity: [From: Fri Aug 28 00:17:30 BST 2009,
               To: Wed Nov 25 23:17:30 GMT 2009]
  Issuer: CN=ECC Test
  SerialNumber: [    67f1afea]

Certificate Extensions: 1
[1]: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: C0 12 A6 B9 61 A7 78 C3   F9 B2 A4 E6 76 69 12 A0  ....a.x.....vi..
0010: 10 59 C8 90                                        .Y..
]
]

]
  Algorithm: [SHA1withECDSA]
  Signature:
0000: 30 44 02 20 2B 9A D6 8A   3E F4 37 2D D8 43 67 F6  0D. +...>.7-.Cg.
0010: DF 51 EC 9D DC EF 0A 88   86 F5 2F 25 84 3E E6 92  .Q......../%.>..
0020: 0D DA D5 51 02 20 0F 34   9D 55 E5 C2 74 14 72 DA  ...Q. .4.U..t.r.
0030: 53 95 9B 60 01 9A 0D D0   64 89 B6 28 7F 96 22 83  S..`....d..(..".
0040: DC 7F EF 10 EF 21                                  .....!

]
[Storing ectest.jks]

However, the same block of code is still there in ECParameters.java so
I presume the version of NSS imported from OpenSolaris is just older.
-- 
Andrew :-)

Free Java Software Engineer
Red Hat, Inc. (http://www.redhat.com)

Support Free Java!
Contribute to GNU Classpath and the OpenJDK
http://www.gnu.org/software/classpath
http://openjdk.java.net

PGP Key: 94EFD9D8 (http://subkeys.pgp.net)
Fingerprint: F8EF F1EA 401E 2E60 15FA  7927 142C 2591 94EF D9D8

Reply via email to