Support for deleting pkcs15 objects

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Support for deleting pkcs15 objects

Stef Hoeben
Hi,

attached is a first proposal for deleting objects at the pkcs15 level
(missing main functionality and regularly requested).

It won't work for some cards yet because (1) it deletes only EFs
while some objects (e.g. keys) on some cards are no EFs or might
be inside the CDF, DODF, ...and (2) some cards (like cryptoflex)
allow deletion of EFs only in reverse order of creation.

So this is mainly for gathering a first reaction and a discussion on
how to handle the above mentioned problems.

Personally, I'd like to replace the call to sc_pkcs15init_rmdir() to
a call to a card-specific function (in sc_pkcs15init_operations).

Whatdayathink?

Stef


Index: pkcs15init/pkcs15-init.h
===================================================================
--- pkcs15init/pkcs15-init.h (revision 2455)
+++ pkcs15init/pkcs15-init.h (working copy)
@@ -168,6 +168,12 @@
 #define SC_PKCS15INIT_USER_PUK 3
 #define SC_PKCS15INIT_NPINS 4
 
+/* Flags for sc_pkcs15init_erase_objects() */
+#define SC_PKCS15INIT_DEL_PRKEY 1
+#define SC_PKCS15INIT_DEL_PUBKEY 2
+#define SC_PKCS15INIT_DEL_CERT 4
+#define SC_PKCS15INIT_DEL_CHAIN (8 | 4)
+
 struct sc_pkcs15init_callbacks {
  /*
  * Get a PIN from the front-end. The first argument is
@@ -317,6 +323,19 @@
  int new_attrib_type,
  void *new_value,
  int new_len);
+/* Delete object(s) by ID. The 'which' param can be any combination of
+ * SC_PKCS15INIT_DEL_PRKEY, SC_PKCS15INIT_DEL_PUBKEY, SC_PKCS15INIT_DEL_CERT
+ * and SC_PKCS15INIT_DEL_CHAIN. In the last case, every cert in the chain is
+ * deleted, starting with the cert with ID 'id' and untill a CA cert is
+ * reached that certified other remaining certs on the card.
+ */
+extern int sc_pkcs15init_delete_objects(sc_pkcs15_card_t *p15card,
+ sc_profile_t *profile,
+ const sc_pkcs15_id_t id,
+ unsigned int which);
+extern int sc_pkcs15init_delete_data_object(sc_pkcs15_card_t *p15card,
+ sc_profile_t *profile,
+ const struct sc_object_id oid);
 
 extern int sc_pkcs15init_create_file(struct sc_profile *,
  struct sc_card *, struct sc_file *);
Index: pkcs15init/pkcs15-lib.c
===================================================================
--- pkcs15init/pkcs15-lib.c (revision 2455)
+++ pkcs15init/pkcs15-lib.c (working copy)
@@ -129,7 +129,10 @@
 static int sc_pkcs15init_parse_info(sc_card_t *, const u8 *, size_t, sc_profile_t *);
 static int sc_pkcs15init_write_info(sc_card_t *card, sc_profile_t *,
  sc_pkcs15_object_t *pin_obj);
+static int get_cert_info(sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *certobj,
+ int *has_sibling, int *stop, sc_pkcs15_object_t **issuercert);
 
+
 static struct profile_operations {
  const char *name;
  void *func;
@@ -492,13 +495,15 @@
  if (r < 0)
  return r;
 
+ r = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_ERASE);
+ if (r < 0) {
+ sc_file_free(parent);
+ return r;
+ }
  r = sc_pkcs15init_authenticate(profile, card, parent, SC_AC_OP_DELETE);
  sc_file_free(parent);
  if (r < 0)
  return r;
- r = sc_pkcs15init_authenticate(profile, card, df, SC_AC_OP_ERASE);
- if (r < 0)
- return r;
 
  memset(&path, 0, sizeof(path));
  path.type = SC_PATH_TYPE_FILE_ID;
@@ -2257,12 +2262,12 @@
 sc_pkcs15init_remove_object(sc_pkcs15_card_t *p15card,
  sc_profile_t *profile, sc_pkcs15_object_t *obj)
 {
- sc_card_t *card = p15card->card;
- struct sc_pkcs15_df *df;
- sc_path_t path;
- int r = 0;
+ sc_file_t *file;
+ struct sc_pkcs15_df *df;
+ sc_path_t path;
+ int r = 0;
 
- switch(obj->type)
+ switch(obj->type & SC_PKCS15_TYPE_CLASS_MASK)
  {
  case SC_PKCS15_TYPE_PUBKEY:
  path = ((sc_pkcs15_pubkey_info_t *)obj->data)->path;
@@ -2279,7 +2284,7 @@
  default:
  return SC_ERROR_OBJECT_NOT_FOUND;
  }
-
+
  /* Get the DF we're part of. If there's no DF, fine, we haven't
  * been added yet. */
  if ((df = obj->df) == NULL)
@@ -2293,8 +2298,15 @@
  /* XXX Dangerous - the object indicated by path may be the
  * application DF. This isn't true for the Oberthur, but
  * it may be for others. */
- r = sc_delete_file(card, &path);
 
+ r = sc_select_file(p15card->card, &path, &file);
+ if (r < 0)
+ return r;
+
+ /* Function name confusing, works for EFs as well */
+ r = sc_pkcs15init_rmdir(p15card->card, profile, file);
+ sc_file_free(file);
+
  return r;
 }
 
@@ -2411,6 +2423,146 @@
  return r < 0 ? r : 0;
 }
 
+static inline int cert_is_root(sc_pkcs15_cert_t *c)
+{
+ return (c->subject_len == c->issuer_len) &&
+ (memcmp(c->subject, c->issuer, c->subject_len) == 0);
+}
+
+
+/* Check if the cert has a 'sibling' and return it's parent cert if (1)
+ * there was no error, (2) there was not error and (3) there is a parent
+ * cert on the card.
+ * Should be made more effcicient for long chains by caching the certs.
+ */
+static int get_cert_info(sc_pkcs15_card_t *p15card, sc_pkcs15_object_t *certobj,
+ int *has_sibling, int *stop, sc_pkcs15_object_t **issuercert)
+{
+ sc_pkcs15_cert_t *cert = NULL;
+ sc_pkcs15_object_t *otherobj;
+ sc_pkcs15_cert_t *othercert = NULL;
+ int r;
+
+ *issuercert = NULL;
+ *has_sibling = 0;
+ *stop = 0;
+
+ r = sc_pkcs15_read_certificate(p15card, (sc_pkcs15_cert_info_t *) certobj->data, &cert);
+ if (r < 0)
+ return SC_ERROR_INVALID_ASN1_OBJECT;
+
+ if (cert_is_root(cert)) {
+ *stop = 1; /* root -> no parent and hence no siblings */
+ goto done;
+ }
+ for (otherobj = p15card->obj_list; otherobj != NULL; otherobj = otherobj->next) {
+ if ((otherobj == certobj) || !(otherobj->type & SC_PKCS15_TYPE_CERT))
+ continue;
+ if (othercert)
+ sc_pkcs15_free_certificate(othercert);
+ r = sc_pkcs15_read_certificate(p15card, (sc_pkcs15_cert_info_t *) otherobj->data, &othercert);
+ if (r < 0) {
+ r = SC_ERROR_INVALID_ASN1_OBJECT;
+ goto done;
+ }
+ if ((cert->issuer_len == othercert->subject_len) &&
+ (memcmp(cert->issuer, othercert->subject, cert->issuer_len) == 0)) {
+ /* parent cert found */
+ *issuercert = otherobj;
+ *stop = cert_is_root(othercert);
+ }
+ else if (!cert_is_root(othercert) && (cert->issuer_len == othercert->issuer_len) &&
+ (memcmp(cert->issuer, othercert->issuer, cert->issuer_len) == 0)) {
+ *has_sibling = 1;
+ break;
+ }
+ }
+
+done:
+ if (cert)
+ sc_pkcs15_free_certificate(cert);
+ if (othercert)
+ sc_pkcs15_free_certificate(othercert);
+
+ return r;
+}
+
+int sc_pkcs15init_delete_objects(sc_pkcs15_card_t *p15card,
+ sc_profile_t *profile,
+ const sc_pkcs15_id_t id,
+ unsigned int which)
+{
+ sc_pkcs15_object_t *objs[10]; /* 1 priv + 1 pub + chain of at most 8 certs, should be enough */
+ sc_context_t *ctx = p15card->card->ctx;
+ int i, r = 0, count = 0, del_cert = 0;
+
+ if (which & SC_PKCS15INIT_DEL_PRKEY) {
+    if (sc_pkcs15_find_prkey_by_id(p15card, &id, &objs[count]) != 0)
+ sc_debug(ctx, "NOTE: couldn't find privkey %s to delete\n", sc_pkcs15_print_id(&id));
+ else
+ count++;
+ }
+
+ if (which & SC_PKCS15INIT_DEL_PUBKEY) {
+    if (sc_pkcs15_find_pubkey_by_id(p15card, &id, &objs[count]) != 0)
+ sc_debug(ctx, "NOTE: couldn't find pubkey %s to delete\n", sc_pkcs15_print_id(&id));
+ else
+ count++;
+ }
+
+ if (which & SC_PKCS15INIT_DEL_CERT) {
+    if (sc_pkcs15_find_cert_by_id(p15card, &id, &objs[count]) != 0)
+ sc_debug(ctx, "NOTE: couldn't find cert %s to delete\n", sc_pkcs15_print_id(&id));
+ else {
+ count++;
+ del_cert = 1;
+ }
+ }
+
+ if (del_cert && ((which & SC_PKCS15INIT_DEL_CHAIN) == SC_PKCS15INIT_DEL_CHAIN)) {
+ /* Get the cert chain, stop if there's a CA that is the issuer of
+ * other certs on this card */
+ int has_sibling; /* siblings: certs having the same issuer */
+ int stop;
+ for( ; count < 10 ; count++) {
+ r = get_cert_info(p15card, objs[count - 1], &has_sibling, &stop, &objs[count]);
+ if (r < 0)
+ sc_error(ctx, "get_cert_info() failed: %s\n", sc_strerror(r));
+ else if (has_sibling)
+ sc_debug(ctx, "Chain deletion stops with cert %s\n", sc_pkcs15_print_id(
+ &((sc_pkcs15_cert_info_t *) objs[count - 1]->data)->id));
+ else if ((objs[count] != NULL))
+ count++;
+ if (stop || (objs[count] == NULL))
+ break;
+ }
+ if (r < 0)
+ count = -1; /* Something wrong -> don't delete anything */
+ }
+
+ for (i = 0; i < count; i++) {
+ r = sc_pkcs15init_remove_object(p15card, profile, objs[i]);
+ if (r < 0) {
+ sc_error(ctx, "Failed to delete object %d: %s\n", i, sc_strerror(r));
+ break;
+ }
+ }
+
+ return r < 0 ? r : count;
+}
+
+int sc_pkcs15init_delete_data_object(sc_pkcs15_card_t *p15card,
+ sc_profile_t *profile,
+ const struct sc_object_id app_oid)
+{
+ struct sc_pkcs15_object *obj;
+ int i, r;
+
+ r = sc_pkcs15_find_data_object_by_app_oid(p15card, &app_oid, &obj);
+ if (r >= 0)
+ return sc_pkcs15init_remove_object(p15card, profile, obj);
+}
+
 /*
  * PIN verification
  */

Index: tools/pkcs15-init.c
===================================================================
--- tools/pkcs15-init.c (revision 2455)
+++ tools/pkcs15-init.c (working copy)
@@ -65,6 +65,7 @@
 static int open_reader_and_card(int);
 static int do_assert_pristine(sc_card_t *);
 static int do_erase(sc_card_t *, struct sc_profile *);
+static int do_delete_objects(struct sc_profile *, unsigned int opt_delete_flags);
 static int do_init_app(struct sc_profile *);
 static int do_store_pin(struct sc_profile *);
 static int do_generate_key(struct sc_profile *, const char *);
@@ -135,6 +136,7 @@
  { "store-public-key", required_argument, 0, OPT_PUBKEY },
  { "store-certificate", required_argument, 0, 'X' },
  { "store-data", required_argument, 0, 'W' },
+ { "delete-objects", required_argument, 0, 'D' },
 
  { "reader", required_argument, 0, 'r' },
  { "pin", required_argument, 0, OPT_PIN1 },
@@ -185,6 +187,7 @@
  "Store public key",
  "Store an X.509 certificate",
  "Store a data object",
+ "Delete object(s) (use \"help\" for more information",
 
  "Specify which reader to use",
  "Specify PIN",
@@ -236,6 +239,7 @@
  ACTION_STORE_CERT,
  ACTION_STORE_DATA,
  ACTION_FINALIZE_CARD,
+ ACTION_DELETE_OBJECTS,
 
  ACTION_MAX
 };
@@ -250,7 +254,8 @@
  "store public key",
  "store certificate",
  "store data object",
- "finalizing card"
+ "finalizing card",
+ "delete object(s)"
 };
 
 #define MAX_CERTS 4
@@ -263,6 +268,8 @@
  size_t len;
 };
 
+#define SC_PKCS15INIT_DEL_DATA 0x8000
+
 static sc_context_t * ctx = NULL;
 static sc_card_t * card = NULL;
 static struct sc_pkcs15_card * p15card = NULL;
@@ -293,6 +300,7 @@
 static char * opt_outkey = 0;
 static char * opt_application_id = 0;
 static unsigned int opt_x509_usage = 0;
+static unsigned int opt_delete_flags = 0;
 static int ignore_cmdline_pins = 0;
 static struct secret opt_secrets[MAX_SECRETS];
 static unsigned int opt_secret_count;
@@ -404,6 +412,9 @@
  case ACTION_STORE_DATA:
  r = do_store_data_object(profile);
  break;
+ case ACTION_DELETE_OBJECTS:
+ r = do_delete_objects(profile, opt_delete_flags);
+ break;
  case ACTION_GENERATE_KEY:
  r = do_generate_key(profile, opt_newkey);
  break;
@@ -921,6 +932,41 @@
  return r;
 }
 
+static int
+do_delete_objects(struct sc_profile *profile, unsigned int opt_delete_flags)
+{
+ int r, count = 0;
+
+ if (opt_delete_flags & SC_PKCS15INIT_DEL_DATA) {
+ struct sc_pkcs15init_dataargs args;
+ if (opt_application_id == NULL)
+ fatal("Specify the --application-id for the data object to be deleted\n");
+ parse_application_id(&args.app_oid, opt_application_id);
+
+ r = sc_pkcs15init_delete_data_object(p15card, profile, args.app_oid);
+ if (r < 0)
+ return r;
+ else
+ count++;
+ }
+
+ if (opt_delete_flags & (SC_PKCS15INIT_DEL_PRKEY | SC_PKCS15INIT_DEL_PUBKEY | SC_PKCS15INIT_DEL_CHAIN)) {
+ sc_pkcs15_id_t id;
+ if (opt_objectid == NULL)
+ fatal("Specify the --id for key(s) or cert(s) to be deleted\n");
+ sc_pkcs15_format_id(opt_objectid, &id);
+
+ r = sc_pkcs15init_delete_objects(p15card, profile, id, opt_delete_flags);
+ }
+
+ if (r >= 0) {
+ count += r;
+ printf("Deleted %d objects\n", count);
+ }
+
+ return r;
+}
+
 /*
  * Generate a new private key
  */
@@ -1779,6 +1825,56 @@
  return 0;
 }
 
+static unsigned int
+parse_delete_flags(const char *list)
+{
+ unsigned int res = 0;
+ static struct {
+ const char *name;
+ unsigned int flag;
+ } del_flags[] = {
+ {"privkey", SC_PKCS15INIT_DEL_PRKEY},
+ {"pubkey", SC_PKCS15INIT_DEL_PUBKEY},
+ {"cert", SC_PKCS15INIT_DEL_CERT},
+ {"chain", SC_PKCS15INIT_DEL_CHAIN},
+ {"data", SC_PKCS15INIT_DEL_DATA},
+ {NULL, 0}
+ };
+
+ while (1) {
+ int len, n, match = 0;
+
+ while (*list == ',')
+ list++;
+ if (!*list)
+ break;
+ len = strcspn(list, ",");
+ if (len == 4 && !strncasecmp(list, "help", 4)) {
+ printf("\nDelete arguments: a comma-separated list containing any of the following:\n");
+ printf("  privkey,pubkey,cert,chain,data\n");
+ printf("When \"data\" is specified, an --application-id must also be specified,\n");
+ printf("  in the other cases an \"--id\" must also be specified\n");
+ printf("When \"chain\" is specified, the certificate chain starting with the cert\n");
+ printf("  with specified ID will be deleted, untill there's a CA cert that certifies\n");
+ printf("  another cert on the card\n");
+ exit(0);
+ }
+ for (n = 0; del_flags[n].name; n++) {
+ if (!strncasecmp(del_flags[n].name, list, len)) {
+ res |= del_flags[n].flag;
+ break;
+ }
+ }
+ if (del_flags[n].name == NULL) {
+ fprintf(stderr, "Unknown argument for --delete_objects: %.*s\n", len, list);
+ exit(0);
+ }
+ list += len;
+ }
+
+ return res;
+}
+
 /*
  * Parse X.509 key usage list
  */
@@ -1889,6 +1985,10 @@
  this_action = ACTION_STORE_DATA;
  opt_infile = optarg;
  break;
+ case 'D':
+ this_action = ACTION_DELETE_OBJECTS;
+ opt_delete_flags = parse_delete_flags(optarg);
+ break;
  case 'v':
  verbose++;
  break;

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Nils Larsch
Stef Hoeben wrote:
> Hi,
>
> attached is a first proposal for deleting objects at the pkcs15 level
> (missing main functionality and regularly requested).

how important is this really ? If it's used quite often I think
we need think about using a EF(unusedSpace) as suggested in pkcs15
as not all cards support file deletion. It might even be better to
store several objects in one file so that we don't depend on the
card capability to delete files (this might be better anyway as
this will prevent fragmentation of the free space on the chipcard).

>
> It won't work for some cards yet because (1) it deletes only EFs
> while some objects (e.g. keys) on some cards are no EFs or might

I guess deleting keys is difficult (impossible) on most card os
(but an alternative would be to overwrite the old key, but this
would of course not free the memory (and EF(UnusedSpace) isn't
really usable for private keys not stored in files).

> be inside the CDF, DODF, ...and (2) some cards (like cryptoflex)
> allow deletion of EFs only in reverse order of creation.
>
> So this is mainly for gathering a first reaction and a discussion on
> how to handle the above mentioned problems.
>
> Personally, I'd like to replace the call to sc_pkcs15init_rmdir() to
> a call to a card-specific function (in sc_pkcs15init_operations).

isn't that something that sc_delete_file should do ? sc_pkcs15init_rmdir
doesn't seem to be really usable anyway as it depends on sc_list_files.

Nils

PS: I think it would be better to implement such features as deletion
     of complete cert chains in the application and not in the library
     (keeping the library and it's interface simple).
     Btw: when deleting cert chain it would be nice if there's check
     that a ca cert to be deleted is not needed in a cert chain of
     another client certs ... but I guess would add to much complexity
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben
Hi Nils,

Nils Larsch wrote:

> Stef Hoeben wrote:
>
>> Hi,
>>
>> attached is a first proposal for deleting objects at the pkcs15 level
>> (missing main functionality and regularly requested).
>
>
> how important is this really ? If it's used quite often I think
> we need think about using a EF(unusedSpace) as suggested in pkcs15
> as not all cards support file deletion. It might even be better to
> store several objects in one file so that we don't depend on the
> card capability to delete files (this might be better anyway as
> this will prevent fragmentation of the free space on the chipcard).

Yes, switching to an EF(unusedSpace) would indeed be a good idea,
for some/most cards (e.g. like a Cryptoflex-. But not for all cards; for
example the Setcos 4.4.1 allows you to delete files at random and
you don't need to allocate space for DFs.
Anyway, I think the pkcs15-deletion is enough independent of the
use of EF(unusedSpace) to be implemented independently.

>
>>
>> It won't work for some cards yet because (1) it deletes only EFs
>> while some objects (e.g. keys) on some cards are no EFs or might
>
>
> I guess deleting keys is difficult (impossible) on most card os
> (but an alternative would be to overwrite the old key, but this
> would of course not free the memory (and EF(UnusedSpace) isn't
> really usable for private keys not stored in files).

For those OS-es there's indeed a problem, but it shouldn't prevent the
functionality on OS-es that can delete keys. Another idee Olaf had
was to set the label to "deleted", which is a sign for pkcs15-init to
re-use this key object again when the next key gen/write is done instead
of using a new one.
In fact: it's already partly there: search for "deleted" in pkcs15-lib.c.
(Just FYI, again I don't think doing this or not is in the way of
my deletion proposal).

>
>> be inside the CDF, DODF, ...and (2) some cards (like cryptoflex)
>> allow deletion of EFs only in reverse order of creation.
>>
>> So this is mainly for gathering a first reaction and a discussion on
>> how to handle the above mentioned problems.
>>
>> Personally, I'd like to replace the call to sc_pkcs15init_rmdir() to
>> a call to a card-specific function (in sc_pkcs15init_operations).
>
>
> isn't that something that sc_delete_file should do ? sc_pkcs15init_rmdir
> doesn't seem to be really usable anyway as it depends on sc_list_files.

It uses sc_delete_file() to acutually delete the file, and the
sc_list_files is
only used if it's a DF so for a file, only the selection of the parent
dir, the
authentication and the acutal delete is done.
But it's indeed confusing. I could split it into 2 functions, but I'd
rather go
for my suggestion: create a card-specific pkcs15init operation so it's
no longer needed to use the rmdir() -> will make new proposal.

>
> Nils
>
> PS: I think it would be better to implement such features as deletion
>     of complete cert chains in the application and not in the library
>     (keeping the library and it's interface simple).

I've been thinking about that too. But deleting a key, it's cert and
it's chain (if not used by others -- see below) is probably the thing
that's used in 90% of the case, and the most work to do.
But if you don't like it, I just copy-paste it to the pkcs15-init tool.

>     Btw: when deleting cert chain it would be nice if there's check
>     that a ca cert to be deleted is not needed in a cert chain of
>     another client certs ... but I guess would add to much complexity

That's done in the code :-) See get_cert_info() and my definition of  
"sibling".
(And it's indeed the most complex part and takes most of the time.)

Cheers,
Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Nils Larsch
Stef Hoeben wrote:
...
> Yes, switching to an EF(unusedSpace) would indeed be a good idea,
> for some/most cards (e.g. like a Cryptoflex-. But not for all cards; for
> example the Setcos 4.4.1 allows you to delete files at random and
> you don't need to allocate space for DFs.

but you might still have problems with fragmentation of the available
memory

> Anyway, I think the pkcs15-deletion is enough independent of the
> use of EF(unusedSpace) to be implemented independently.

agree, in particular as a proper implementation of the EF(UnusedSpace)
file etc. stuff would require some work

...

>> I guess deleting keys is difficult (impossible) on most card os
>> (but an alternative would be to overwrite the old key, but this
>> would of course not free the memory (and EF(UnusedSpace) isn't
>> really usable for private keys not stored in files).
>
>
> For those OS-es there's indeed a problem, but it shouldn't prevent the
> functionality on OS-es that can delete keys. Another idee Olaf had
> was to set the label to "deleted", which is a sign for pkcs15-init to
> re-use this key object again when the next key gen/write is done instead
> of using a new one.
> In fact: it's already partly there: search for "deleted" in pkcs15-lib.c.

Does this overwrite the key ? If not that's not good as I would expect
that a deleted objects isn't physically present on the key once it's
"deleted" .

> (Just FYI, again I don't think doing this or not is in the way of
> my deletion proposal).

agree

...

>> isn't that something that sc_delete_file should do ? sc_pkcs15init_rmdir
>> doesn't seem to be really usable anyway as it depends on sc_list_files.
>
>
> It uses sc_delete_file() to acutually delete the file, and the
> sc_list_files is
> only used if it's a DF so for a file, only the selection of the parent
> dir, the
> authentication and the acutal delete is done.
> But it's indeed confusing. I could split it into 2 functions, but I'd
> rather go
> for my suggestion: create a card-specific pkcs15init operation so it's
> no longer needed to use the rmdir() -> will make new proposal.

a card specific operation to do what ? delete a file ?

...
> I've been thinking about that too. But deleting a key, it's cert and
> it's chain (if not used by others -- see below) is probably the thing
> that's used in 90% of the case, and the most work to do.
> But if you don't like it, I just copy-paste it to the pkcs15-init tool.

I think it would give us more flexibility if we implement such complex
things in the application layer (we could change it easily without
changing the library api) ... just my opinion.

>
>>     Btw: when deleting cert chain it would be nice if there's check
>>     that a ca cert to be deleted is not needed in a cert chain of
>>     another client certs ... but I guess would add to much complexity
>
>
> That's done in the code :-) See get_cert_info() and my definition of  
> "sibling".
> (And it's indeed the most complex part and takes most of the time.)

ops, I missed that.

Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben
Nils Larsch wrote:

> Stef Hoeben wrote:
> ...
>
>> Yes, switching to an EF(unusedSpace) would indeed be a good idea,
>> for some/most cards (e.g. like a Cryptoflex-. But not for all cards; for
>> example the Setcos 4.4.1 allows you to delete files at random and
>> you don't need to allocate space for DFs.
>
>
> but you might still have problems with fragmentation of the available
> memory

Don't know what is done internally, perhaps do refragment during a delete
and/or create, or they work with tables or so...

>>
>> For those OS-es there's indeed a problem, but it shouldn't prevent the
>> functionality on OS-es that can delete keys. Another idee Olaf had
>> was to set the label to "deleted", which is a sign for pkcs15-init to
>> re-use this key object again when the next key gen/write is done instead
>> of using a new one.
>> In fact: it's already partly there: search for "deleted" in
>> pkcs15-lib.c.
>
>
> Does this overwrite the key ? If not that's not good as I would expect
> that a deleted objects isn't physically present on the key once it's
> "deleted" .

Yes: first overwrite the key (e.g. with zeros if possible) and then set the
label to "deleted".

>>
>> It uses sc_delete_file() to acutually delete the file, and the
>> sc_list_files is
>> only used if it's a DF so for a file, only the selection of the
>> parent dir, the
>> authentication and the acutal delete is done.
>> But it's indeed confusing. I could split it into 2 functions, but I'd
>> rather go
>> for my suggestion: create a card-specific pkcs15init operation so it's
>> no longer needed to use the rmdir() -> will make new proposal.
>
>
> a card specific operation to do what ? delete a file ?

To delete an 'object' (key, cert, data).
As input, I'd give the DF entry (e.g. PrKDF entry in case of a private key)
and the type, and let the card driver decide about it. E.g. in the case of
Setcos 4.4.1, the new function would simple call sc_delete_file() for all
objects. For other cards, the new function may call sc_delete_file() for the
certs, and overwrite_key() for public and private keys, ...

>> I've been thinking about that too. But deleting a key, it's cert and
>> it's chain (if not used by others -- see below) is probably the thing
>> that's used in 90% of the case, and the most work to do.
>> But if you don't like it, I just copy-paste it to the pkcs15-init tool.
>
>
> I think it would give us more flexibility if we implement such complex
> things in the application layer (we could change it easily without
> changing the library api) ... just my opinion.

Okay, no problem to change this.

Will send a new proposal later this week.

Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
Stef Hoeben wrote:

> Nils Larsch wrote:
>
>> Stef Hoeben wrote:
>> ...
>>
>>> Yes, switching to an EF(unusedSpace) would indeed be a good idea,
>>> for some/most cards (e.g. like a Cryptoflex-. But not for all cards;
>>> for
>>> example the Setcos 4.4.1 allows you to delete files at random and
>>> you don't need to allocate space for DFs.
>>
>>
>>
>> but you might still have problems with fragmentation of the available
>> memory
>
>
> Don't know what is done internally, perhaps do refragment during a delete
> and/or create, or they work with tables or so...
>
>>>
>>> For those OS-es there's indeed a problem, but it shouldn't prevent the
>>> functionality on OS-es that can delete keys. Another idee Olaf had
>>> was to set the label to "deleted", which is a sign for pkcs15-init to
>>> re-use this key object again when the next key gen/write is done
>>> instead
>>> of using a new one.
>>> In fact: it's already partly there: search for "deleted" in
>>> pkcs15-lib.c.
>>
>>
>>
>> Does this overwrite the key ? If not that's not good as I would expect
>> that a deleted objects isn't physically present on the key once it's
>> "deleted" .
>
>
> Yes: first overwrite the key (e.g. with zeros if possible) and then
> set the
> label to "deleted".
>
>>>
>>> It uses sc_delete_file() to acutually delete the file, and the
>>> sc_list_files is
>>> only used if it's a DF so for a file, only the selection of the
>>> parent dir, the
>>> authentication and the acutal delete is done.
>>> But it's indeed confusing. I could split it into 2 functions, but
>>> I'd rather go
>>> for my suggestion: create a card-specific pkcs15init operation so it's
>>> no longer needed to use the rmdir() -> will make new proposal.
>>
>>
>>
>> a card specific operation to do what ? delete a file ?
>
>
> To delete an 'object' (key, cert, data).
> As input, I'd give the DF entry (e.g. PrKDF entry in case of a private
> key)
> and the type, and let the card driver decide about it. E.g. in the
> case of
> Setcos 4.4.1, the new function would simple call sc_delete_file() for all
> objects. For other cards, the new function may call sc_delete_file()
> for the
> certs, and overwrite_key() for public and private keys, ...
>
>>> I've been thinking about that too. But deleting a key, it's cert and
>>> it's chain (if not used by others -- see below) is probably the thing
>>> that's used in 90% of the case, and the most work to do.
>>> But if you don't like it, I just copy-paste it to the pkcs15-init tool.
>>
>>
>>
>> I think it would give us more flexibility if we implement such complex
>> things in the application layer (we could change it easily without
>> changing the library api) ... just my opinion.
>
>
> Okay, no problem to change this.
>
> Will send a new proposal later this week.
>
> Stef

It would be nice to have the possibility of the card-specific 'remove
object' procedure.
(I mean to implement a new 'remove object' entry in the 'struct
sc_pkcs15init_operations').
We use it, for example, to update the native Oberthur's AWP objects
descriptors,
when the card has to be used with the both OpenSC's and native
Oberthur's middlewares.

Another question is a file indexing.
Now, afaik, the file index is lied to the object ID.
IMHO, it would be nice to have the possibility of the card-specific
file-indexing.
(Once more, I mean to implement a new 'get index' entry to the 'struct
sc_pkcs15init_operations').
This will permit, if neccessary, to make independent file index and
object ID.
For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
modulus as the object ID,
and we use the linear, 'first available index' schema when getting index
for the new file.

Kind wishes,
Viktor.






>
> _______________________________________________
> opensc-devel mailing list
> [hidden email]
> http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
>
>

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben

>>>I think it would give us more flexibility if we implement such complex
>>>things in the application layer (we could change it easily without
>>>changing the library api) ... just my opinion.
>>>      
>>>
>>Okay, no problem to change this.
>>
>>Will send a new proposal later this week.
>>
>>Stef
>>    
>>
>
>It would be nice to have the possibility of the card-specific 'remove
>object' procedure.
>(I mean to implement a new 'remove object' entry in the 'struct
>sc_pkcs15init_operations').
>  
>
That's my intention :-) (Sorry for the unclear communication...)

>We use it, for example, to update the native Oberthur's AWP objects
>descriptors,
>when the card has to be used with the both OpenSC's and native
>Oberthur's middlewares.
>
>Another question is a file indexing.
>Now, afaik, the file index is lied to the object ID.
>IMHO, it would be nice to have the possibility of the card-specific
>file-indexing.
>(Once more, I mean to implement a new 'get index' entry to the 'struct
>sc_pkcs15init_operations').
>This will permit, if neccessary, to make independent file index and
>object ID.
>For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>modulus as the object ID,
>and we use the linear, 'first available index' schema when getting index
>for the new file.
>
Hm, looks like a good idea, and not so hard to add. (You feel like doing
it:-)

This may also solve a problem with Mozilla keypair gen: it works for the
first key, but at the
end Mozilla renames the IDs. And the next time, the pkcs15init lib get
stuck on the difference
between the file and object id...

Best cheers,
Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
Stef Hoeben wrote:

>
>>>> I think it would give us more flexibility if we implement such complex
>>>> things in the application layer (we could change it easily without
>>>> changing the library api) ... just my opinion.
>>>>    
>>>
>>> Okay, no problem to change this.
>>>
>>> Will send a new proposal later this week.
>>>
>>> Stef
>>>  
>>
>>
>> It would be nice to have the possibility of the card-specific 'remove
>> object' procedure.
>> (I mean to implement a new 'remove object' entry in the 'struct
>> sc_pkcs15init_operations').
>>  
>>
> That's my intention :-) (Sorry for the unclear communication...)
>
>> We use it, for example, to update the native Oberthur's AWP objects
>> descriptors,
>> when the card has to be used with the both OpenSC's and native
>> Oberthur's middlewares.
>>
>> Another question is a file indexing.
>> Now, afaik, the file index is lied to the object ID.
>> IMHO, it would be nice to have the possibility of the card-specific
>> file-indexing.
>> (Once more, I mean to implement a new 'get index' entry to the 'struct
>> sc_pkcs15init_operations').
>> This will permit, if neccessary, to make independent file index and
>> object ID.
>> For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>> modulus as the object ID,
>> and we use the linear, 'first available index' schema when getting index
>> for the new file.
>>
> Hm, looks like a good idea, and not so hard to add. (You feel like
> doing it:-)
>
> This may also solve a problem with Mozilla keypair gen: it works for
> the first key, but at the
> end Mozilla renames the IDs. And the next time, the pkcs15init lib get
> stuck on the difference
> between the file and object id...

If you agree, I will prepare patch proposal.

Kind wishes,
Viktor.

>
> Best cheers,
> Stef
>
>
>

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben
Tarasov Viktor wrote:

>Stef Hoeben wrote:
>
>  
>
>>>>>I think it would give us more flexibility if we implement such complex
>>>>>things in the application layer (we could change it easily without
>>>>>changing the library api) ... just my opinion.
>>>>>    
>>>>>          
>>>>>
>>>>Okay, no problem to change this.
>>>>
>>>>Will send a new proposal later this week.
>>>>
>>>>Stef
>>>>  
>>>>        
>>>>
>>>It would be nice to have the possibility of the card-specific 'remove
>>>object' procedure.
>>>(I mean to implement a new 'remove object' entry in the 'struct
>>>sc_pkcs15init_operations').
>>>
>>>
>>>      
>>>
>>That's my intention :-) (Sorry for the unclear communication...)
>>
>>    
>>
>>>We use it, for example, to update the native Oberthur's AWP objects
>>>descriptors,
>>>when the card has to be used with the both OpenSC's and native
>>>Oberthur's middlewares.
>>>
>>>Another question is a file indexing.
>>>Now, afaik, the file index is lied to the object ID.
>>>IMHO, it would be nice to have the possibility of the card-specific
>>>file-indexing.
>>>(Once more, I mean to implement a new 'get index' entry to the 'struct
>>>sc_pkcs15init_operations').
>>>This will permit, if neccessary, to make independent file index and
>>>object ID.
>>>For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>>>modulus as the object ID,
>>>and we use the linear, 'first available index' schema when getting index
>>>for the new file.
>>>
>>>      
>>>
>>Hm, looks like a good idea, and not so hard to add. (You feel like
>>doing it:-)
>>
>>This may also solve a problem with Mozilla keypair gen: it works for
>>the first key, but at the
>>end Mozilla renames the IDs. And the next time, the pkcs15init lib get
>>stuck on the difference
>>between the file and object id...
>>    
>>
>
>If you agree, I will prepare patch proposal.
>  
>
Yes, I agree. And I'd guess no-anyone will disagree that such a tight
coupling
between the pkcs15 and the file ID is rather bad, considering they are
so different.

Best regards,
Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben
In reply to this post by Stef Hoeben

Hi Viktor,

what the Oberthur code does, is looking for the first FID (in fact, the last
byte of the FID) that isn't used for exising file yet?

In that case, wouldn't it be better to use it for all cards
(after adding a check for correct DF or so)?

Greetz,
Stef

Tarasov Viktor wrote:

>Stef Hoeben wrote:
>
>  
>
>>Tarasov Viktor wrote:
>>
>>    
>>
>>>Stef Hoeben wrote:
>>>
>>>
>>>
>>>      
>>>
>>>>>>>I think it would give us more flexibility if we implement such
>>>>>>>complex
>>>>>>>things in the application layer (we could change it easily without
>>>>>>>changing the library api) ... just my opinion.
>>>>>>>          
>>>>>>>              
>>>>>>>
>>>>>>Okay, no problem to change this.
>>>>>>
>>>>>>Will send a new proposal later this week.
>>>>>>
>>>>>>Stef
>>>>>>
>>>>>>      
>>>>>>            
>>>>>>
>>>>>It would be nice to have the possibility of the card-specific 'remove
>>>>>object' procedure.
>>>>>(I mean to implement a new 'remove object' entry in the 'struct
>>>>>sc_pkcs15init_operations').
>>>>>
>>>>>
>>>>>    
>>>>>          
>>>>>
>>>>That's my intention :-) (Sorry for the unclear communication...)
>>>>
>>>>  
>>>>
>>>>        
>>>>
>>>>>We use it, for example, to update the native Oberthur's AWP objects
>>>>>descriptors,
>>>>>when the card has to be used with the both OpenSC's and native
>>>>>Oberthur's middlewares.
>>>>>
>>>>>Another question is a file indexing.
>>>>>Now, afaik, the file index is lied to the object ID.
>>>>>IMHO, it would be nice to have the possibility of the card-specific
>>>>>file-indexing.
>>>>>(Once more, I mean to implement a new 'get index' entry to the 'struct
>>>>>sc_pkcs15init_operations').
>>>>>This will permit, if neccessary, to make independent file index and
>>>>>object ID.
>>>>>For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>>>>>modulus as the object ID,
>>>>>and we use the linear, 'first available index' schema when getting
>>>>>index
>>>>>for the new file.
>>>>>
>>>>>    
>>>>>          
>>>>>
>>>>Hm, looks like a good idea, and not so hard to add. (You feel like
>>>>doing it:-)
>>>>
>>>>This may also solve a problem with Mozilla keypair gen: it works for
>>>>the first key, but at the
>>>>end Mozilla renames the IDs. And the next time, the pkcs15init lib get
>>>>stuck on the difference
>>>>between the file and object id...
>>>>  
>>>>        
>>>>
>>>If you agree, I will prepare patch proposal.
>>>
>>>
>>>      
>>>
>>Yes, I agree. And I'd guess no-anyone will disagree that such a tight
>>coupling
>>between the pkcs15 and the file ID is rather bad, considering they are
>>so different.
>>    
>>
>
>Here it is.
>
>Kind wishes,
>Viktor.
>
>  
>
>>Best regards,
>>Stef
>>
>>
>>
>>    
>>
>
>
>  
>


_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
In reply to this post by Stef Hoeben
Stef Hoeben wrote:

> Tarasov Viktor wrote:
>
>> Stef Hoeben wrote:
>>
>>  
>>
>>>>>> I think it would give us more flexibility if we implement such
>>>>>> complex
>>>>>> things in the application layer (we could change it easily without
>>>>>> changing the library api) ... just my opinion.
>>>>>>            
>>>>>
>>>>> Okay, no problem to change this.
>>>>>
>>>>> Will send a new proposal later this week.
>>>>>
>>>>> Stef
>>>>>  
>>>>>      
>>>>
>>>> It would be nice to have the possibility of the card-specific 'remove
>>>> object' procedure.
>>>> (I mean to implement a new 'remove object' entry in the 'struct
>>>> sc_pkcs15init_operations').
>>>>
>>>>
>>>>    
>>>
>>> That's my intention :-) (Sorry for the unclear communication...)
>>>
>>>  
>>>
>>>> We use it, for example, to update the native Oberthur's AWP objects
>>>> descriptors,
>>>> when the card has to be used with the both OpenSC's and native
>>>> Oberthur's middlewares.
>>>>
>>>> Another question is a file indexing.
>>>> Now, afaik, the file index is lied to the object ID.
>>>> IMHO, it would be nice to have the possibility of the card-specific
>>>> file-indexing.
>>>> (Once more, I mean to implement a new 'get index' entry to the 'struct
>>>> sc_pkcs15init_operations').
>>>> This will permit, if neccessary, to make independent file index and
>>>> object ID.
>>>> For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>>>> modulus as the object ID,
>>>> and we use the linear, 'first available index' schema when getting
>>>> index
>>>> for the new file.
>>>>
>>>>    
>>>
>>> Hm, looks like a good idea, and not so hard to add. (You feel like
>>> doing it:-)
>>>
>>> This may also solve a problem with Mozilla keypair gen: it works for
>>> the first key, but at the
>>> end Mozilla renames the IDs. And the next time, the pkcs15init lib get
>>> stuck on the difference
>>> between the file and object id...
>>>  
>>
>>
>> If you agree, I will prepare patch proposal.
>>  
>>
> Yes, I agree. And I'd guess no-anyone will disagree that such a tight
> coupling
> between the pkcs15 and the file ID is rather bad, considering they are
> so different.
Here it is.

Kind wishes,
Viktor.

>
> Best regards,
> Stef
>
>
>


diff -Naur ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-init.h ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-init.h
--- ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-init.h 2005-04-14 11:02:03.000000000 +0200
+++ ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-init.h 2005-08-10 17:25:12.000000000 +0200
@@ -113,6 +113,11 @@
  */
  int (*finalize_card)(sc_card_t *);
 
+    /*
+ * Get index for the new object
+ */
+ int (*get_index)(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj);
+
  /*
  * Old-style API
  */
diff -Naur ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-lib.c ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-lib.c
--- ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-lib.c 2005-04-14 11:02:02.000000000 +0200
+++ ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-lib.c 2005-08-10 17:26:51.000000000 +0200
@@ -1545,9 +1545,12 @@
  } else {
 
  /* Get the number of objects of this type already on this card */
- index = sc_pkcs15_get_objects(p15card,
- object->type & SC_PKCS15_TYPE_CLASS_MASK,
- NULL, 0);
+ if (profile->ops->get_index)
+ index = profile->ops->get_index(p15card, object);
+ else
+ index = sc_pkcs15_get_objects(p15card,
+ object->type & SC_PKCS15_TYPE_CLASS_MASK,
+ NULL, 0);
 
  /* Allocate data file */
  r = profile->ops->new_file(profile, p15card->card,
diff -Naur ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-oberthur.c ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-oberthur.c
--- ./opensc-0.9.6.orig/src/pkcs15init/pkcs15-oberthur.c 2005-04-14 11:02:02.000000000 +0200
+++ ./opensc-0.9.6.commit/src/pkcs15init/pkcs15-oberthur.c 2005-08-10 17:30:07.000000000 +0200
@@ -686,6 +686,64 @@
 }
 
 
+int
+cosm_get_index(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj)
+{
+ sc_pkcs15_object_t  *objs[64];
+ int rv, ii;
+ struct sc_path path;
+ int obj_indx[0x100];
+ int indx;
+ unsigned int type;
+
+    if (!obj)   {
+ sc_error(p15card->card->ctx, "NULL object pointer");
+ return SC_ERROR_INVALID_ARGUMENTS;
+ }
+ type = obj->type;
+ sc_debug(p15card->card->ctx, "type %i\n", type);
+ memset(obj_indx, 0, sizeof(obj_indx));
+ rv = sc_pkcs15_get_objects(p15card, type, objs, 32);
+ if (rv<0)   {
+ sc_error(p15card->card->ctx, "Error while getting objects number. rv %i\n", rv);
+ return rv;
+ }
+
+ for (ii=0; ii<rv; ii++)   {
+ switch (type & SC_PKCS15_TYPE_CLASS_MASK) {
+ case SC_PKCS15_TYPE_CERT:
+ path = ((sc_pkcs15_cert_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_PRKEY:
+ path = ((sc_pkcs15_prkey_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_PUBKEY:
+ path = ((sc_pkcs15_pubkey_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_DATA_OBJECT:
+ path = ((sc_pkcs15_data_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ default:
+ return rv;
+ }
+ }
+
+ for (ii=0;ii<0x100;ii++)
+ if (!obj_indx[ii])
+ break;
+
+ sc_debug(p15card->card->ctx, "return index %i\n", ii);
+ return ii;
+}
+
 struct sc_pkcs15init_operations sc_pkcs15init_oberthur_operations;
 
 struct sc_pkcs15init_operations *
@@ -706,6 +764,7 @@
  ops->generate_key = NULL;
  ops->encode_private_key = NULL;
  ops->encode_public_key = NULL;
+ ops->get_index = cosm_get_index;
 
 //OLD
  ops->init_app = cosm_init_app;
@@ -713,6 +772,5 @@
  ops->new_key = cosm_new_key;
  ops->new_file = cosm_new_file;
  ops->old_generate_key = cosm_old_generate_key;
-
  return ops;
 };

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
In reply to this post by Stef Hoeben
Stef Hoeben wrote:

>
> Hi Viktor,
>
> what the Oberthur code does, is looking for the first FID (in fact,
> the last
> byte of the FID) that isn't used for exising file yet?

Yes, firstly, it looks for the indexes (low byte of FID) of the all
existing objects with the given type.
Then returns the first, starting from zero, free index.
That way I try to reuse the indexes of the removed objects.


> In that case, wouldn't it be better to use it for all cards
> (after adding a check for correct DF or so)?

Do you mean the other types of the card?
I do not know enough the other cards.
I remember, for example, that for the acient Schlumberger cards,
the FID of the public key and private key were fixed.
So, I don't know how the default index value should be calculated,
but, IMHO, there has to be possibility to overwrite it in the
card-specific part.

It concerns not only file index.
That's why, I propose (in another mail) to supply the card-specific
pkcs15init
with the pointer to the object as an argument, and not only the object type.

Kind wishes,
Viktor.

>
> Greetz,
> Stef


_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Nils Larsch
Tarasov Viktor wrote:
...
> That's why, I propose (in another mail) to supply the card-specific
> pkcs15init
> with the pointer to the object as an argument, and not only the object type.

if we would pass the pkcs15 object to the new_file operation wouldn't
this make this patch unnecessary ?

Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
Nils Larsch wrote:

> Tarasov Viktor wrote:
> ...
>
>> That's why, I propose (in another mail) to supply the card-specific
>> pkcs15init
>> with the pointer to the object as an argument, and not only the
>> object type.
>
>
> if we would pass the pkcs15 object to the new_file operation wouldn't
> this make this patch unnecessary ?

Agree.
So, do you accept the modification of the 'new_file' prototype?
I will prepare patch.

Viktor.

>
> Nils
>
>

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Nils Larsch
Tarasov Viktor wrote:

> Nils Larsch wrote:
>
>
>>Tarasov Viktor wrote:
>>...
>>
>>
>>>That's why, I propose (in another mail) to supply the card-specific
>>>pkcs15init
>>>with the pointer to the object as an argument, and not only the
>>>object type.
>>
>>
>>if we would pass the pkcs15 object to the new_file operation wouldn't
>>this make this patch unnecessary ?
>
>
> Agree.
> So, do you accept the modification of the 'new_file' prototype?

yep, this change is necessary anyway

> I will prepare patch.

hopefully against the current svn trunk ;-)

Nils

PS: and what is exactly the problem with the so-pin and the new
     pin api ?
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
Nils Larsch wrote:

> Tarasov Viktor wrote:
>
>> Nils Larsch wrote:
>>
>>
>>> Tarasov Viktor wrote:
>>> ...
>>>
>>>
>>>> That's why, I propose (in another mail) to supply the card-specific
>>>> pkcs15init
>>>> with the pointer to the object as an argument, and not only the
>>>> object type.
>>>
>>>
>>>
>>> if we would pass the pkcs15 object to the new_file operation wouldn't
>>> this make this patch unnecessary ?
>>
>>
>>
>> Agree.
>> So, do you accept the modification of the 'new_file' prototype?
>
>
> yep, this change is necessary anyway
>
>> I will prepare patch.
>
>
> hopefully against the current svn trunk ;-)
Here it is.

Kind wishes,
Viktor.


> Nils
>
> PS: and what is exactly the problem with the so-pin and the new
>     pin api ?

I answered in thread "patch to Oberthur SC: 'list file' command changed".
I will do a necessary patch.


diff -Naur ./opensc.trunk.orig/src/libopensc/card-oberthur.c ./opensc.trunk/src/libopensc/card-oberthur.c
--- ./opensc.trunk.orig/src/libopensc/card-oberthur.c 2005-08-11 14:28:40.000000000 +0200
+++ ./opensc.trunk/src/libopensc/card-oberthur.c 2005-08-11 15:16:30.000000000 +0200
@@ -2358,8 +2358,13 @@
  auth_ops.restore_security_env = auth_restore_security_env;
  auth_ops.compute_signature = auth_compute_signature;
  auth_ops.decipher = auth_decipher;
-
+
+/* not yet */
+#if 0
  auth_ops.pin_cmd = auth_pin_cmd;
+#else
+ auth_ops.pin_cmd = NULL
+#endif
  auth_ops.verify = auth_verify;
  auth_ops.reset_retry_counter = auth_reset_retry_counter;
  auth_ops.change_reference_data = auth_change_reference_data;
diff -Naur ./opensc.trunk.orig/src/pkcs15init/oberthur.profile ./opensc.trunk/src/pkcs15init/oberthur.profile
--- ./opensc.trunk.orig/src/pkcs15init/oberthur.profile 2005-08-11 14:28:24.000000000 +0200
+++ ./opensc.trunk/src/pkcs15init/oberthur.profile 2005-08-11 14:32:44.000000000 +0200
@@ -2,7 +2,7 @@
 # PKCS15 r/w profile for Oberthur cards
 #
 cardinfo {
-    label       = "S3M";
+    label       = "SCM";
     manufacturer    = "Oberthur/OpenSC";
 
     max-pin-length = 64;
diff -Naur ./opensc.trunk.orig/src/pkcs15init/pkcs15-init.h ./opensc.trunk/src/pkcs15init/pkcs15-init.h
--- ./opensc.trunk.orig/src/pkcs15init/pkcs15-init.h 2005-08-11 14:28:24.000000000 +0200
+++ ./opensc.trunk/src/pkcs15init/pkcs15-init.h 2005-08-11 14:34:40.000000000 +0200
@@ -133,7 +133,7 @@
  * help the card driver to pick the right file ID/directory ID/
  * pin file index.
  */
- int (*new_pin)(struct sc_profile *, struct sc_card *,
+ int (*new_pin)(struct sc_profile *, struct sc_pkcs15_card *,
  struct sc_pkcs15_pin_info *, unsigned int idx,
  const u8 *pin, size_t pin_len,
  const u8 *puk, size_t puk_len);
@@ -141,20 +141,21 @@
  /*
  * Store a key on the card
  */
- int (*new_key)(struct sc_profile *, struct sc_card *,
+ int (*new_key)(struct sc_profile *, struct sc_pkcs15_card *,
  struct sc_pkcs15_prkey *key, unsigned int idx,
  struct sc_pkcs15_prkey_info *);
 
  /*
  * Create a file based on a PKCS15_TYPE_xxx
  */
- int (*new_file)(struct sc_profile *, struct sc_card *,
- unsigned int, unsigned int, struct sc_file **out);
+ int (*new_file)(struct sc_profile *, struct sc_pkcs15_card *,
+ struct sc_pkcs15_object *, unsigned int,
+ struct sc_file **out);
 
  /*
  * Generate a new key pair
  */
- int (*old_generate_key)(struct sc_profile *, struct sc_card *,
+ int (*old_generate_key)(struct sc_profile *, struct sc_pkcs15_card *,
  unsigned int idx, unsigned int keybits,
  sc_pkcs15_pubkey_t *pubkey_res,
  struct sc_pkcs15_prkey_info *);
diff -Naur ./opensc.trunk.orig/src/pkcs15init/pkcs15-lib.c ./opensc.trunk/src/pkcs15init/pkcs15-lib.c
--- ./opensc.trunk.orig/src/pkcs15init/pkcs15-lib.c 2005-08-11 14:28:24.000000000 +0200
+++ ./opensc.trunk/src/pkcs15init/pkcs15-lib.c 2005-08-11 14:36:52.000000000 +0200
@@ -770,7 +770,7 @@
  idx = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH,
  NULL, 0);
 
- r = profile->ops->new_pin(profile, card, pin_info, idx,
+ r = profile->ops->new_pin(profile, p15card, pin_info, idx,
  args->pin, args->pin_len,
  args->puk, args->puk_len);
  }
@@ -1098,7 +1098,7 @@
  int idx;
 
  idx = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PRKEY, NULL, 0);
- r = profile->ops->old_generate_key(profile, p15card->card, idx, keybits,
+ r = profile->ops->old_generate_key(profile, p15card, idx, keybits,
  &pubkey_args.key, key_info);
  }
 
@@ -1194,7 +1194,7 @@
  if (r < 0)
  return r;
  } else {
- r = profile->ops->new_key(profile, p15card->card,
+ r = profile->ops->new_key(profile, p15card,
  &key, idx, key_info);
  if (r < 0)
  return r;
@@ -1611,8 +1611,7 @@
  NULL, 0);
 
  /* Allocate data file */
- r = profile->ops->new_file(profile, p15card->card,
- object->type, idx, &file);
+ r = profile->ops->new_file(profile, p15card, object, idx, &file);
  if (r < 0) {
  sc_error(p15card->card->ctx, "Unable to allocate file");
  goto done;
diff -Naur ./opensc.trunk.orig/src/pkcs15init/pkcs15-miocos.c ./opensc.trunk/src/pkcs15init/pkcs15-miocos.c
--- ./opensc.trunk.orig/src/pkcs15init/pkcs15-miocos.c 2005-08-11 14:28:24.000000000 +0200
+++ ./opensc.trunk/src/pkcs15init/pkcs15-miocos.c 2005-08-11 14:40:11.000000000 +0200
@@ -47,7 +47,7 @@
  * Store a PIN
  */
 static int
-miocos_new_pin(struct sc_profile *profile, sc_card_t *card,
+miocos_new_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
  struct sc_pkcs15_pin_info *info, unsigned int idx,
  const u8 *pin, size_t pin_len,
  const u8 *puk, size_t puk_len)
@@ -55,6 +55,7 @@
  struct sc_pkcs15_pin_info tmpinfo;
  struct sc_cardctl_miocos_ac_info ac_info;
  int r;
+ struct sc_card *card = p15card->card;
 
  info->path = profile->df_info->file->path;
  r = sc_select_file(card, &info->path, NULL);
@@ -83,14 +84,16 @@
  * Allocate a file
  */
 static int
-miocos_new_file(struct sc_profile *profile, sc_card_t *card,
- unsigned int type, unsigned int num,
+miocos_new_file(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
+ struct sc_pkcs15_object *obj, unsigned int num,
  sc_file_t **out)
 {
  struct sc_file *file;
  struct sc_path *p;
  char name[64];
  const char      *tag = NULL, *desc = NULL;
+ unsigned int type = obj->type;
+ struct sc_card *card = p15card->card;
 
  while (1) {
  switch (type) {
@@ -168,12 +171,14 @@
  * Store a private key
  */
 static int
-miocos_new_key(struct sc_profile *profile, sc_card_t *card,
+miocos_new_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
  struct sc_pkcs15_prkey *key, unsigned int idx,
  struct sc_pkcs15_prkey_info *info)
 {
  sc_file_t *keyfile;
  struct sc_pkcs15_prkey_rsa *rsa;
+ struct sc_card *card = p15card->card;
+ struct sc_pkcs15_object dummy_obj;
  int r;
 
  if (key->algorithm != SC_ALGORITHM_RSA) {
@@ -185,8 +190,8 @@
  sc_error(card->ctx, "MioCOS supports only 1024-bit RSA keys.");
  return SC_ERROR_NOT_SUPPORTED;
  }
- r = miocos_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
-    &keyfile);
+ dummy_obj.type = SC_PKCS15_TYPE_PRKEY_RSA;
+ r = miocos_new_file(profile, p15card, &dummy_obj, idx, &keyfile);
  if (r < 0)
  return r;
 
diff -Naur ./opensc.trunk.orig/src/pkcs15init/pkcs15-oberthur.c ./opensc.trunk/src/pkcs15init/pkcs15-oberthur.c
--- ./opensc.trunk.orig/src/pkcs15init/pkcs15-oberthur.c 2005-08-11 14:28:24.000000000 +0200
+++ ./opensc.trunk/src/pkcs15init/pkcs15-oberthur.c 2005-08-11 15:22:49.000000000 +0200
@@ -70,6 +70,8 @@
 static int cosm_update_pin(struct sc_profile *profile, sc_card_t *card,
  struct sc_pkcs15_pin_info *info, const u8 *pin, size_t pin_len,
  const u8 *puk, size_t puk_len);
+static int cosm_get_index(struct sc_pkcs15_card *p15card,
+ struct sc_pkcs15_object *obj);
 
 int cosm_delete_file(sc_card_t *card, struct sc_profile *profile,
  sc_file_t *df);
@@ -141,6 +143,8 @@
 
  sc_debug(card->ctx, "erase file ddf %04X\n",df->id);
  r=cosm_delete_file(card, profile, df);
+ if (r < 0 && r != SC_ERROR_FILE_NOT_FOUND)
+ goto done;
 
  if (sc_profile_get_file(profile, "private-DF", &dir) >= 0) {
  sc_debug(card->ctx, "erase file dir %04X\n",dir->id);
@@ -206,7 +210,7 @@
  return r;
 
  /* Oberthur AWP file system is expected.*/
- /* Create private objects DF */
+ /* Create PKCS#15, private and public objects DFs */
  for (ii = 0; ii<sizeof(create_dfs)/sizeof(char *); ii++)   {
  if (sc_profile_get_file(profile, create_dfs[ii], &file))   {
  sc_error(card->ctx, "Inconsistent profile: cannot find %s", create_dfs[ii]);
@@ -428,12 +432,20 @@
  * Allocate a file
  */
 static int
-cosm_new_file(struct sc_profile *profile, sc_card_t *card,
- unsigned int type, unsigned int num, sc_file_t **out)
+cosm_new_file(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
+ struct sc_pkcs15_object *obj, unsigned int num, sc_file_t **out)
 {
  struct sc_file *file;
  const char *_template = NULL, *desc = NULL;
  unsigned int structure = 0xFFFFFFFF;
+ struct sc_card *card = p15card->card;
+ unsigned int type = obj->type;
+
+ num = cosm_get_index(p15card, obj);
+ if (num<0)   {
+ sc_error(card->ctx, "Error while getting index: %i\n", num);
+ return num;
+ }
 
  sc_debug(card->ctx, "type %X; num %i\n",type, num);
  while (1) {
@@ -463,8 +475,14 @@
  _template = "template-certificate";
  break;
  case SC_PKCS15_TYPE_DATA_OBJECT:
- desc = "data object";
- _template = "template-public-data";
+ if (obj->auth_id.len)   {
+ desc = "private data";
+ _template = "template-private-data";
+ }
+ else {
+ desc = "public data";
+ _template = "template-public-data";
+ }
  break;
  }
  if (_template)
@@ -505,7 +523,8 @@
  * RSA key generation
  */
 static int
-cosm_old_generate_key(struct sc_profile *profile, sc_card_t *card,
+cosm_old_generate_key(struct sc_profile *profile,
+ struct sc_pkcs15_card *p15card,
  unsigned int idx, unsigned int keybits,
  sc_pkcs15_pubkey_t *pubkey,
  struct sc_pkcs15_prkey_info *info)
@@ -514,6 +533,8 @@
  struct sc_file *prkf = NULL, *tmpf = NULL;
  sc_path_t path;
  int rv;
+ struct sc_pkcs15_object dummy_obj;
+ struct sc_card *card = p15card->card;
 
  sc_debug(card->ctx, "index %i; nn %i\n",idx,keybits);
  if (keybits < 512 || keybits > 2048 || (keybits%0x20))   {
@@ -522,8 +543,8 @@
  }
 
  /* Get private key file from profile. */
- if ((rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
- &prkf)) < 0)
+ dummy_obj.type = SC_PKCS15_TYPE_PRKEY_RSA;
+ if ((rv = cosm_new_file(profile, p15card, &dummy_obj, idx, &prkf)) < 0)
  goto failed;
  sc_debug(card->ctx, "prv ef type %i\n",prkf->ef_structure);
  prkf->size = keybits;
@@ -610,13 +631,15 @@
  * Store a private key
  */
 static int
-cosm_new_key(struct sc_profile *profile, sc_card_t *card,
- struct sc_pkcs15_prkey *key, unsigned int idx,
- struct sc_pkcs15_prkey_info *info)
+cosm_new_key(struct sc_profile *profile,
+ struct sc_pkcs15_card *p15card, struct sc_pkcs15_prkey *key,
+ unsigned int idx, struct sc_pkcs15_prkey_info *info)
 {
  sc_file_t *prvfile = NULL, *pubfile = NULL;
  struct sc_pkcs15_prkey_rsa *rsa = NULL;
  struct sc_pkcs15_bignum bn[6];
+ struct sc_pkcs15_object dummy_obj;
+ struct sc_card *card = p15card->card;
  u8 *buff;
  int rv, ii;
 
@@ -627,7 +650,8 @@
  }
 
  /* Create and populate the private part. */
- rv = cosm_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, idx,
+ dummy_obj.type = SC_PKCS15_TYPE_PRKEY_RSA;
+ rv = cosm_new_file(profile, p15card, &dummy_obj, idx,
  &prvfile);
  if (rv < 0)
  return SC_ERROR_SYNTAX_ERROR;
@@ -686,6 +710,61 @@
 }
 
 
+static int
+cosm_get_index(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj)
+{
+ sc_pkcs15_object_t  *objs[64];
+ int rv, ii;
+ struct sc_path path;
+ int obj_indx[0x100];
+ int indx;
+
+ sc_debug(p15card->card->ctx, "type %i\n", obj->type);
+ memset(obj_indx, 0, sizeof(obj_indx));
+ rv = sc_pkcs15_get_objects(p15card, obj->type, objs, 32);
+ if (rv<0)   {
+ sc_error(p15card->card->ctx, "Error while getting objects number. rv %i\n", rv);
+ return rv;
+ }
+
+ for (ii=0; ii<rv; ii++)   {
+ switch (obj->type & SC_PKCS15_TYPE_CLASS_MASK) {
+ case SC_PKCS15_TYPE_CERT:
+ path = ((sc_pkcs15_cert_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_PRKEY:
+ path = ((sc_pkcs15_prkey_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_PUBKEY:
+ path = ((sc_pkcs15_pubkey_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ case SC_PKCS15_TYPE_DATA_OBJECT:
+ path = ((sc_pkcs15_data_info_t *)(objs[ii]->data))->path;
+ indx = path.value[path.len-1] & 0xFF;
+ obj_indx[indx] = 1;
+ break;
+ default:
+ return rv;
+ }
+ }
+
+ for (ii=0;ii<0x100;ii++)
+ if (!obj_indx[ii])
+ break;
+
+ sc_debug(p15card->card->ctx, "return index %i\n", ii);
+ return ii;
+}
+
+
+
+
 static struct sc_pkcs15init_operations sc_pkcs15init_oberthur_operations = {
  .erase_card = cosm_erase_card,
  /* NEW */

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
In reply to this post by Stef Hoeben
Stef Hoeben wrote:

>> Another question is a file indexing.
>> Now, afaik, the file index is lied to the object ID.
>> IMHO, it would be nice to have the possibility of the card-specific
>> file-indexing.
>> (Once more, I mean to implement a new 'get index' entry to the 'struct
>> sc_pkcs15init_operations').
>> This will permit, if neccessary, to make independent file index and
>> object ID.
>> For example, for the PrKey/PubKey/X509 objects we use the SHA1 of the
>> modulus as the object ID,
>> and we use the linear, 'first available index' schema when getting index
>> for the new file.
>>
> Hm, looks like a good idea, and not so hard to add. (You feel like
> doing it:-)
>
> This may also solve a problem with Mozilla keypair gen: it works for
> the first key, but at the
> end Mozilla renames the IDs. And the next time, the pkcs15init lib get
> stuck on the difference
> between the file and object id...

Once more about indexing.
Will it be better to implement the file indexing in the card profile,
and not in card pkcs15init?
For example to use the following syntax in profile:
file-id     = 5010:5020;
file-id     = 5011,5021,5031,5041;

Kind wishes,
Viktor.

>
> Best cheers,
> Stef
>
>
>

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Nils Larsch
In reply to this post by Tarasov Viktor
Tarasov Viktor wrote:
...
>>hopefully against the current svn trunk ;-)
>
>
> Here it is.

thanks, I will look at it this weekend (I've already committed
the first two trivial patches).

Thanks,
Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Stef Hoeben
In reply to this post by Tarasov Viktor
Hi,

>Once more about indexing.
>Will it be better to implement the file indexing in the card profile,
>and not in card pkcs15init?
>For example to use the following syntax in profile:
>file-id     = 5010:5020;
>file-id     = 5011,5021,5031,5041;
>
Don't know, would we gain something with this?
If not, it would only make things more complex, IMHO.

Cheers,
Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: Support for deleting pkcs15 objects

Tarasov Viktor
Stef Hoeben wrote:

> Hi,
>
>> Once more about indexing.
>> Will it be better to implement the file indexing in the card profile,
>> and not in card pkcs15init?
>> For example to use the following syntax in profile:
>> file-id = 5010:5020;
>> file-id = 5011,5021,5031,5041;
>>
> Don't know, would we gain something with this?
> If not, it would only make things more complex, IMHO.

The aim was to make card pkcs15init more general,
and to move the needed specifity to the profile.
For exemple, I need the possible values for FIDs
private key -- 30xx,
X509 -- 20xx,
...,
and I need four PIN domains with FIDs: 5011, ..., 5014.
So, it seemed to me more logical to move these restrictions from card
pkcs15init to the profile.
But, I agree, probably, my point of view is too 'card-specific'.

Kind wishes,
Viktor.

>
> Cheers,
> Stef
>
>
>

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
12