Hello,

when dealing with accessing tokens from a Java application via OpenSC, I
noticed that the Sun/ORACLE PKCS11-Java implementation is not always
able to retrieve the certificate chain (stored on the token) for a key.

The objects on my token (Feitian PKI card) are:
> Private RSA Key [Private Key]
>       Object Flags   : [0x3], private, modifiable
>       Usage          : [0x12E], decrypt, sign, signRecover, unwrap, derive
>       Access Flags   : [0x0]
>       ModLength      : 2048
>       Key ref        : 1 (0x1)
>       Native         : yes
>       Path           : 3f005015
>       Auth ID        : 01
>       ID             : 692b93bfd7d6f6dd86832f81d1b44adbe266f74d
>       GUID           : {692b93bf-d7d6-f6dd-8683-2f81d1b44adb}
> 
> X.509 Certificate [/C=DE/L=Entenhausen/O=Dagobert Duck 
> Enterprises/OU=Geldspeicher/CN=Dagobert Duck]
>       Object Flags   : [0x2], modifiable
>       Authority      : no
>       Path           : 3f0050153100
>       ID             : 692b93bfd7d6f6dd86832f81d1b44adbe266f74d
>       GUID           : {692b93bf-d7d6-f6dd-8683-2f81d1b44adb}
>       Encoded serial : 02 01 03
> 
> X.509 Certificate [/C=DE/O=Deutsche Zertifizierungsstelle/OU=PKI der 
> Deutschen Zertifizierungsstelle/CN=Deutsche Zertifizierungsstelle Root CA]
>       Object Flags   : [0x2], modifiable
>       Authority      : yes
>       Path           : 3f0050153101
>       ID             : aff0e45b54ec084fdb987e76b655100963ca0be1
>       GUID           : {aff0e45b-54ec-084f-db98-7e76b6551009}
>       Encoded serial : 02 01 01

The certificate chain is:
>   0: /C=DE/L=Entenhausen/O=Dagobert Duck 
> Enterprises/OU=Geldspeicher/CN=Dagobert Duck
>   1: /C=DE/O=Deutsche Zertifizierungsstelle/OU=PKI der Deutschen 
> Zertifizierungsstelle/CN=Deutsche Zertifizierungsstelle Root CA

Accessing the keystore on this token with the Java keytool utility yields:
> Keystore type: PKCS11
> Keystore provider: SunPKCS11-OpenSC
> 
> Your keystore contains 2 entries
> 
> Alias name: /C=DE/L=Entenhausen/O=Dagobert Duck 
> Enterprises/OU=Geldspeicher/CN=Dagobert Duck
> Entry type: PrivateKeyEntry
> Certificate chain length: 1
> Certificate[1]:
> Owner: CN=Dagobert Duck, OU=Geldspeicher, O=Dagobert Duck Enterprises, 
> L=Entenhausen, C=DE
> Issuer: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Serial number: 3
> Valid from: Tue Jan 31 08:18:17 CET 2012 until: Tue Jan 31 08:18:17 CET 2017
> 
> Alias name: /C=DE/O=Deutsche Zertifizierungsstelle/OU=PKI der Deutschen 
> Zertifizierungsstelle/CN=Deutsche Zertifizierungsstelle Root CA
> Entry type: trustedCertEntry
> 
> Owner: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Issuer: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Serial number: 1
> Valid from: Mon Jan 30 11:03:09 CET 2012 until: Fri Jan 30 11:03:09 CET 2032

Note the length of certificate chain (1), since the root certificate is
not included in the chain (but should be).

I tracked down this problem to the function C_FindObjectsInit which
should find a certificate with a given subject but does not always succeed.

Finally I ended in framework-pkcs15.c where in function
pkcs15_cert_cmp_attribute the search condition for CKA_ISSUER is dealt
with specially. I expanded this code slightly to do also the same
special check for CKA_SUBJECT.

The patched code solves this problem: Now in Java the certificate chain
gets identified correctly. Output of Java keytool utility:

> Keystore type: PKCS11
> Keystore provider: SunPKCS11-OpenSC
> 
> Your keystore contains 2 entries
> 
> Alias name: /C=DE/L=Entenhausen/O=Dagobert Duck 
> Enterprises/OU=Geldspeicher/CN=Dagobert Duck
> Entry type: PrivateKeyEntry
> Certificate chain length: 2
> Certificate[1]:
> Owner: CN=Dagobert Duck, OU=Geldspeicher, O=Dagobert Duck Enterprises, 
> L=Entenhausen, C=DE
> Issuer: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Serial number: 3
> Valid from: Tue Jan 31 08:18:17 CET 2012 until: Tue Jan 31 08:18:17 CET 2017
> Certificate[2]:
> Owner: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Issuer: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Serial number: 1
> Valid from: Mon Jan 30 11:03:09 CET 2012 until: Fri Jan 30 11:03:09 CET 2032
> 
> Alias name: /C=DE/O=Deutsche Zertifizierungsstelle/OU=PKI der Deutschen 
> Zertifizierungsstelle/CN=Deutsche Zertifizierungsstelle Root CA
> Entry type: trustedCertEntry
> 
> Owner: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Issuer: CN=Deutsche Zertifizierungsstelle Root CA, OU=PKI der Deutschen 
> Zertifizierungsstelle, O=Deutsche Zertifizierungsstelle, C=DE
> Serial number: 1
> Valid from: Mon Jan 30 11:03:09 CET 2012 until: Fri Jan 30 11:03:09 CET 2032

Patch file is attached (works with current git version but also version
0.12.2 and 0.12.1). I would be glad if this could be included in the
next OpenSC release.

Best regards,
        Christian

-- 
Dr. Christian Rank
Rechenzentrum Universität Passau
Bereich Netzwerk und Telekommunikation
Innstr. 33
D-94032 Passau
GERMANY
Tel.: 0851/509-1838
Fax:  0851/509-1802
PGP public key see http://www.rz.uni-passau.de/mitarbeiter/rank
*** framework-pkcs15.c.orig     2012-01-31 11:13:39.000000000 +0100
--- framework-pkcs15.c  2012-01-31 11:14:48.000000000 +0100
***************
*** 2418,2423 ****
--- 2418,2446 ----
                 && !memcmp(cert->cert_data->issuer, data, len))
                        return 1;
                break;
+         case CKA_SUBJECT:
+               if (check_cert_data_read(fw_data, cert) != 0)
+                       break;
+               if (cert->cert_data->subject_len == 0)
+                       break;
+               data = (u8 *) attr->pValue;
+               len = attr->ulValueLen;
+               /* SEQUENCE is tag 0x30, SET is 0x31
+                * I know this code is icky, but hey... this is netscape
+                * we're dealing with :-) */
+               if (cert->cert_data->subject[0] == 0x31
+                && data[0] == 0x30 && len >= 2) {
+                       /* skip the length byte(s) */
+                       len = (data[1] & 0x80)? (data[1] & 0x7F) : 0;
+                       if (attr->ulValueLen < len + 2)
+                               break;
+                       data += len + 2;
+                       len = attr->ulValueLen - len - 2;
+               }
+               if (len == cert->cert_data->subject_len
+                && !memcmp(cert->cert_data->subject, data, len))
+                       return 1;
+               break;
        default:
                return sc_pkcs11_any_cmp_attribute(session, object, attr);
        }
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to