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.


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?

-- 
Henryk Plötz
Grüße aus Berlin
~~~~~~~ Un-CDs, nein danke! http://www.heise.de/ct/cd-register/ ~~~~~~~
~ Help Microsoft fight software piracy: Give Linux to a friend today! ~
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 {
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-prkey.c
===================================================================
--- src/libopensc/pkcs15-prkey.c	(Revision 3022)
+++ src/libopensc/pkcs15-prkey.c	(Arbeitskopie)
@@ -153,6 +153,9 @@
 		sc_error(ctx, "Neither RSA or DSA key in PrKDF entry.\n");
 		SC_FUNC_RETURN(ctx, 0, SC_ERROR_INVALID_ASN1_OBJECT);
 	}
+	r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
+	if (r < 0)
+		return r;
 	obj->data = malloc(sizeof(info));
 	if (obj->data == NULL)
 		SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
Index: src/libopensc/pkcs15-pubkey.c
===================================================================
--- src/libopensc/pkcs15-pubkey.c	(Revision 3022)
+++ src/libopensc/pkcs15-pubkey.c	(Arbeitskopie)
@@ -135,6 +135,9 @@
 	} else {
 		obj->type = SC_PKCS15_TYPE_PUBKEY_DSA;
 	}
+	r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
+	if (r < 0)
+		return r;
 	obj->data = malloc(sizeof(info));
 	if (obj->data == NULL)
 		SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
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;
+}
Index: src/libopensc/pkcs15.h
===================================================================
--- src/libopensc/pkcs15.h	(Revision 3022)
+++ src/libopensc/pkcs15.h	(Arbeitskopie)
@@ -632,6 +632,8 @@
 int sc_pkcs15_hex_string_to_id(const char *in, struct sc_pkcs15_id *out);
 void sc_der_copy(sc_pkcs15_der_t *, const sc_pkcs15_der_t *);
 void sc_der_clear(sc_pkcs15_der_t *);
+/* Prepend 'parent' to 'child' in case 'child' is a relative path */
+int sc_pkcs15_make_absolute_path(const sc_path_t *parent, sc_path_t *child);
 
 /* New object search API.
  * More complex, but also more powerful.
Index: src/libopensc/pkcs15-cert.c
===================================================================
--- src/libopensc/pkcs15-cert.c	(Revision 3022)
+++ src/libopensc/pkcs15-cert.c	(Arbeitskopie)
@@ -218,6 +218,9 @@
 	if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
 		return r;
 	SC_TEST_RET(ctx, r, "ASN.1 decoding failed");
+	r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
+	if (r < 0)
+		return r;
 	obj->type = SC_PKCS15_TYPE_CERT_X509;
 	obj->data = malloc(sizeof(info));
 	if (obj->data == NULL)
Index: src/libopensc/pkcs15-data.c
===================================================================
--- src/libopensc/pkcs15-data.c	(Revision 3022)
+++ src/libopensc/pkcs15-data.c	(Arbeitskopie)
@@ -109,8 +109,10 @@
 	r = sc_asn1_decode(ctx, asn1_data, *buf, *buflen, buf, buflen);
 	if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
 		return r;
-
 	SC_TEST_RET(ctx, r, "ASN.1 decoding failed");
+	r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
+	if (r < 0)
+		return r;
 	obj->type = SC_PKCS15_TYPE_DATA_OBJECT;
 	obj->data = malloc(sizeof(info));
 	if (obj->data == NULL)

Attachment: pgpyID9gfEiEV.pgp
Description: PGP signature

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

Reply via email to