Henryk Plötz wrote:
Moin,

Andreas sent me the already existing patches for better Siemens support
and I took the most promising, fixed them and added some more. These are
mostly fixes to general PKCS#15 functionality, no Siemens specific code
for now. Please have a look at them before I commit them.

opensc-ignore-empty.patch:
Don't call the ASN.1 parser when we read an empty (zero bytes long)
directory file. (E.g. an empty EF(PuKDF) means that there are no public
keys, which is not an error.)

opensc-siemens.diff:
Support linear variable tlv files for PKCS#15 directory files. This is
the minimum necessary to make the HiPath structures work at all, but I
think complete support for all possible file types should be added in
the future.

opensc-absolute-path.diff (based on pre-test.diff, by stef?):
Modify all paths that are not absolute (e.g. starting with the MF) to
be absolute by prepending the DF(PKCS#15) path.

this is certainly not a fix, more a workaround around a problem in
our pkcs15 handling. I'm not really happy with it as our internal
representation of the on-card pkcs15 structure doesn't reflect what's
actually on the card (with the consequence that if we read something
from the card and write it back the new object will be different).
It might be better to make the path absolute just before it's actually
used (if this is doable).



Together these patches allow most read-only functionality with Siemens
HiPath SIcurity formatted cards (including pkcs15-tool -D and
pkcs11-tool -L) plus decryption.

What's still missing is signing. Andreas suggested that using the
decryption routine for signing might be a common enough workaround to
be implemented in the general, non-cardos-specific code. Any opinions
on where the best place would be?

if we do this in a not cardos (or HiPath) specific code section
we would need to test everytime we try to generate a signature,
not really elegant. As we know that HiPath cards use the
decryption operation for signing (always ?) we could try to
utilize the pkcs15 emulation driver for this ...




------------------------------------------------------------------------

Index: src/libopensc/pkcs15.c
===================================================================
--- src/libopensc/pkcs15.c      (Revision 3022)
+++ src/libopensc/pkcs15.c      (Arbeitskopie)
@@ -1321,6 +1325,9 @@
                                        &buf, &bufsize, &df->file);
        if (r < 0)
                return r;
+       
+       if (bufsize == 0)
+               goto ret;
p = buf;
        do {


what about replacing the "do {] while();" loop with a "while() {}" loop ?


------------------------------------------------------------------------

Index: src/libopensc/pkcs15.c
===================================================================
--- src/libopensc/pkcs15.c      (revision 2789)
+++ src/libopensc/pkcs15.c      (working copy)
@@ -1365,13 +1365,50 @@
                        r = SC_ERROR_OUT_OF_MEMORY;
                        goto fail_unlock;
                }
-               r = sc_read_binary(p15card->card, offset, data, len, 0);
-               if (r < 0) {
+               if (file->ef_structure == SC_FILE_EF_TRANSPARENT) {
+                       r = sc_read_binary(p15card->card, offset, data, len, 0);
+                       if (r < 0) {
+                               free(data);
+                               goto fail_unlock;
+                       }
+                       /* sc_read_binary may return less than requested */
+                       len = r;
+               } else if (file->ef_structure == SC_FILE_EF_LINEAR_VARIABLE_TLV)
+               {
+                       int i;
+                       size_t l;
+                       unsigned char *head;
+
+                       head = data;
+                       for (i=1;  ; i++) {
+                               l = len - (head - data);
+                               if (l > 256) { l = 256; }
+                               p15card->card->ctx->suppress_errors++;
+                               r = sc_read_record(p15card->card, i, head, l,
+                                               SC_RECORD_BY_REC_NR);
+                               p15card->card->ctx->suppress_errors--;
+                               if (r == SC_ERROR_RECORD_NOT_FOUND)
+                                       break;
+                               if (r < 0) {
+                                       free(data);
+                                       goto fail_unlock;
+                               }
+                               if (r <= 2)
+                                       break;
+                               memmove(head,head+2,r-2);
+                               head += (r-2);
+                       }
+                       len = head-data;
+                       r = len;
+               } else {
+                       sc_error(p15card->card->ctx,
+                               "can't read file %s of type %d\n",
+                               sc_print_path(&file->path),
+                               file->ef_structure);
+                       r=-1;
                        free(data);
                        goto fail_unlock;
                }
-               /* sc_read_binary may return less than requested */
-               len = r;
                sc_unlock(p15card->card);
/* Return of release file */




Index: src/libopensc/pkcs15.c
===================================================================
--- src/libopensc/pkcs15.c      (Revision 3022)
+++ src/libopensc/pkcs15.c      (Arbeitskopie)
@@ -303,7 +303,7 @@
 {
        const u8 *p = buf;
        size_t left = buflen;
-       int r, i;
+       int r, i, type;
        sc_path_t path;
        struct sc_asn1_entry asn1_obj_or_path[] = {
                { "path", SC_ASN1_PATH, SC_ASN1_CONS | SC_ASN1_SEQUENCE, 0, 
&path, NULL },
@@ -320,7 +320,11 @@
                        break;
                if (r < 0)
                        return r;
-               r = sc_pkcs15_add_df(card, odf_indexes[r], &path, NULL);
+               type = r;
+               r = sc_pkcs15_make_absolute_path(&card->file_app->path, &path);
+               if (r < 0)
+                       return r;
+               r = sc_pkcs15_add_df(card, odf_indexes[type], &path, NULL);
                if (r)
                        return r;
        }
@@ -1523,9 +1527,12 @@
                if (r < 0)
                        return r;
                /* If the path length is 0, it's a dummy path then don't add it.
-                * If the path length isn't include (-1) then it's against the 
standard
+                * If the path length isn't included (-1) then it's against the 
standard
                 *   but we'll just ignore it instead of returning an error. */
                if (path.count > 0) {
+                       r = sc_pkcs15_make_absolute_path(&card->file_app->path, 
&path);
+                       if (r < 0)
+                               return r;
                        r = sc_pkcs15_add_unusedspace(card, &path, &auth_id);
                        if (r)
                                return r;
@@ -1543,7 +1550,6 @@
                        sc_file_t **file_out)
 {
        sc_file_t *file = NULL;
-       sc_path_t tmp_path, *path = &tmp_path;
        u8      *data = NULL;
        size_t  len = 0, offset = 0;
        int     r;
@@ -1561,34 +1567,25 @@
                        pbuf, in_path->index, in_path->count);
        }
- if (in_path->type == SC_PATH_TYPE_FILE_ID) {
-               /* in case of a FID prepend the application DF */
-               memcpy(path, &p15card->file_app->path, sizeof(sc_path_t));
-               sc_append_path(path, in_path);
-               path->index = in_path->index;
-               path->count = in_path->count;
-       } else {
-               memcpy(path, in_path, sizeof(sc_path_t));
-       }
        r = -1; /* file state: not in cache */
        if (p15card->opts.use_cache) {
-               r = sc_pkcs15_read_cached_file(p15card, path, &data, &len);
+               r = sc_pkcs15_read_cached_file(p15card, in_path, &data, &len);
        }
        if (r) {
                r = sc_lock(p15card->card);
                SC_TEST_RET(p15card->card->ctx, r, "sc_lock() failed");
-               r = sc_select_file(p15card->card, path, &file);
+               r = sc_select_file(p15card->card, in_path, &file);
                if (r)
                        goto fail_unlock;
/* Handle the case where the ASN.1 Path object specified
                 * index and length values */
-               if (path->count < 0) {
+               if (in_path->count < 0) {
                        len = file->size;
                        offset = 0;
                } else {
-                       offset = path->index;
-                       len = path->count;
+                       offset = in_path->index;
+                       len = in_path->count;
                        /* Make sure we're within proper bounds */
                        if (offset >= file->size
                         || offset + len > file->size) {
@@ -1657,3 +1654,35 @@
        out->len = sizeof(out->value);
        return sc_hex_to_bin(in, out->value, &out->len);
 }
+
+int sc_pkcs15_make_absolute_path(const sc_path_t *parent, sc_path_t *child)
+{
+       if (child->len == 0)
+               return 0; /* No path -> leave it this way */
+       
+       if (child->len < 2)
+               return SC_ERROR_INVALID_ARGUMENTS;
+       
+       if (sc_compare_path_prefix(sc_get_mf_path(), child))
+               return 0;
+       
+       if (child->len + parent->len > SC_MAX_PATH_SIZE)
+               return SC_ERROR_BUFFER_TOO_SMALL;
+               
+#if 0
+       fprintf(stderr,"build absolute path from %s ",
+                       sc_print_path(parent));
+       fprintf(stderr, " and %s: ", sc_print_path(child));
+#endif
+       memmove(child->value + parent->len, child->value, child->len);
+       memcpy(child->value, parent->value, parent->len);
+       child->len += parent->len;
+#if 0
+       fprintf(stderr,"%s\n", sc_print_path(child));
+#endif
+       
+       if(child->type == SC_PATH_TYPE_FILE_ID)
+           child->type = SC_PATH_TYPE_PATH;
+       
+       return 0;
+}

we already have a function to concatenate to paths (sc_concatenate_path())
and it should be used here

Cheers,
Nils
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to