Hi,

there seem to be 2 problems:

- protect_certificates = false by default -> nasty security bug IMHO, this is fixed in profile.c PS: The flex.profile sets this value to true, but setting it to false seems to work fine for me
        (so I propose to remove it -> OK???)

- no reference to the user PIN is given with "pkcs15-init -X", which causes
 sc_pkcs15_init_fixup_file() to set the corresponding ACs to NONE (!)
It looks rather nasty but I'm afraid of shacking it up so I just added a reference
 to the first user PIN in case it's not set -> comments?

Cheers,
Stef

Jean-Pierre Szikora wrote:

Hi,

Thanks to Yannick Leplard for analyzing and reporting this problem.

In onepin mode and when the first certificate is added to a SC by itself (not through a PKCS12), the ACL of PKCS15-CDF (5015/4404) is set to NONE... If the same certificate is added through a PKCS12, the ACL is correctly set to CHV1. There is no problem with the others xDF.

This bug is present on MacOSX and on Linux (recent svn). And is not card specific (present on SetCos and CryptoFlex).

A little script to reproduce the bug:
#!/bin/bash
openssl req -new -newkey rsa:1024 -nodes -x509 -keyout test.key -subj /CN=JoTest -out test.pem openssl pkcs12 -export -out test.p12 -passout pass:test -name JoTest -inkey test.key -in test.pem

pkcs15-init -T -E
pkcs15-init -T -C -p pkcs15+onepin -l "Test" --pin 1234 --puk 1234

pkcs15-init -S test.key -l "Test" -a1 -i 50 --pin 1234
pkcs15-init -X test.pem -l "Test" -a1 -i 50 --pin 1234

#pkcs15-init -S test.p12 -f PKCS12 -a 1 --pin 1234 --passphrase test

opensc-explorer <<END
cd 5015
info 4404
quit
END

Cheers,

Jean-Pierre


Index: profile.c
===================================================================
--- profile.c   (revision 2881)
+++ profile.c   (working copy)
@@ -255,6 +255,7 @@
                return NULL;
        pro->p15_spec = p15card = sc_pkcs15_card_new();
 
+       pro->protect_certificates = 1;
        pro->pkcs15.do_last_update = 1;
 
        if (p15card) {
Index: pkcs15-lib.c
===================================================================
--- pkcs15-lib.c        (revision 2881)
+++ pkcs15-lib.c        (working copy)
@@ -1680,20 +1680,24 @@
        if ((r = select_id(p15card, SC_PKCS15_TYPE_CERT, &args->id, NULL, NULL, 
NULL)) < 0)
                return r;
 
-       /* If there is a private key corresponding to the ID given
-        * by the user, make sure $PIN references the pin protecting
-        * this key
-        */
-       if (args->id.len != 0
-        && profile->protect_certificates
-        && sc_pkcs15_find_prkey_by_id(p15card, &args->id, &object) == 0) {
-               r = set_user_pin_from_authid(p15card, profile, 
&object->auth_id);
-               if (r < 0) {
-                       sc_error(p15card->card->ctx,
-                                     "Failed to assign user pin reference "
-                                     "(copied from private key auth_id)\n");
-                       return r;
+       if (profile->protect_certificates) {
+               /* If there is a private key corresponding to the ID given
+                * by the user, make sure $PIN references the pin protecting
+                * this key
+                */
+               r = -1;
+               if (args->id.len != 0
+                && sc_pkcs15_find_prkey_by_id(p15card, &args->id, &object) == 
0) {
+                       r = set_user_pin_from_authid(p15card, profile, 
&object->auth_id);
+                       if (r < 0) {
+                               sc_error(p15card->card->ctx,
+                                             "Failed to assign user pin 
reference "
+                                             "(copied from private key 
auth_id)\n");
+                               return r;
+                       }
                }
+               if (r == -1) /* User pin ref not yet set */
+                       set_user_pin_from_authid(p15card, profile, NULL);
        }
 
        object = sc_pkcs15init_new_object(SC_PKCS15_TYPE_CERT_X509, label, 
NULL, NULL);
@@ -3098,7 +3102,9 @@
 
 /*
  * If the user specified an auth_id, select the corresponding
- * PIN entry and set the reference data
+ * PIN entry and set the reference data.
+ * If auth_id is NULL, then get the first user PIN found, this
+ * is usefull for the 'onepin' profile option.
  */
 static int
 set_user_pin_from_authid(struct sc_pkcs15_card *p15card,
@@ -3109,6 +3115,23 @@
        struct sc_pkcs15_object *objp;
        int             r;
 
+       if (auth_id == NULL) {
+               int i;
+               struct sc_pkcs15_object *p15objects[5];
+               r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, 
p15objects, 5);
+               if (r < 0)
+                       return r;
+               for (i = 0; i < r; i++) {
+                       sc_pkcs15_pin_info_t *pininfo = (sc_pkcs15_pin_info_t 
*) p15objects[i]->data;
+                       if (!(pininfo->flags & SC_PKCS15_PIN_FLAG_SO_PIN)) {
+                               auth_id = &pininfo->auth_id;
+                               break;
+                       }
+               }
+               if (i >= r)
+                       return SC_ERROR_OBJECT_NOT_FOUND;
+       }
+
        if (auth_id->len == 0)
                return 0;
 
@@ -3408,6 +3431,51 @@
        return sc_pkcs15init_fixup_acls(profile, file, &so_acl, &user_acl);
 }
 
+static const char * acl_to_str(const sc_acl_entry_t *e)
+{
+       static char line[80], buf[10];
+       unsigned int acl;
+       
+       if (e == NULL)
+               return "N/A";
+       line[0] = 0;
+       while (e != NULL) {
+               acl = e->method;
+
+               switch (acl) {
+               case SC_AC_UNKNOWN:
+                       return "N/A";
+               case SC_AC_NEVER:
+                       return "NEVR";
+               case SC_AC_NONE:
+                       return "NONE";
+               case SC_AC_CHV:
+                       strcpy(buf, "CHV");
+                       if (e->key_ref != SC_AC_KEY_REF_NONE)
+                               sprintf(buf + 3, "%d", e->key_ref);
+                       break;
+               case SC_AC_TERM:
+                       strcpy(buf, "TERM");
+                       break;
+               case SC_AC_PRO:
+                       strcpy(buf, "PROT");
+                       break;
+               case SC_AC_AUT:
+                       strcpy(buf, "AUTH");
+                       if (e->key_ref != SC_AC_KEY_REF_NONE)
+                               sprintf(buf + 4, "%d", e->key_ref);
+                       break;
+               default:
+                       strcpy(buf, "????");
+                       break;
+               }
+               strcat(line, buf);
+               strcat(line, " ");
+               e = e->next;
+       }
+       line[strlen(line)-1] = 0; /* get rid of trailing space */
+       return line;
+}
 /*
  * Fix up a file's ACLs by replacing all occurrences of a symbolic
  * PIN name with the real reference.
Index: flex.profile
===================================================================
--- flex.profile        (revision 2881)
+++ flex.profile        (working copy)
@@ -6,12 +6,6 @@
     pin-encoding       = ascii-numeric;
     pin-pad-char       = 0x00;
     pin-domains                = yes;
-
-    # This profile does not PIN-protect certificates
-    # stored on the card. If you enable this, you MUST
-    # adjust the sizes of the pin-domain and key-dir DFs
-    # accordingly.
-    protect-certificates = no;
 }
 
 # Define reasonable limits for PINs and PUK
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to