From 3a2f0415feee5c006169c59b29561343b903af68 Mon Sep 17 00:00:00 2001 From: "viktor.tarasov" Date: Tue, 9 Mar 2010 16:49:00 +0000 Subject: [PATCH] libopensc emu: postponed object loading Some non-pkcs15 cards protect the reading of the private objects attributes. For the emulated pkcs15 cards, the 'init' emu-handler was the only place where pkcs15 objects could be loaded. This handler is called before the card is binded, and so, for an application there was no 'normal' way to verify PIN and load the objects with protected attributes. Actually it's possible to complete list of the pkcs15 objects after the emulated pkcs15 card has been binded. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4096 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/libopensc.exports | 1 + src/libopensc/pkcs15-gemsafeV1.c | 2 +- src/libopensc/pkcs15-syn.c | 33 +++++++++++++++++++++++++++++++- src/libopensc/pkcs15.c | 30 +++++++++++++++++++++++------ src/libopensc/pkcs15.h | 19 +++++++++++------- src/pkcs15init/pkcs15-lib.c | 2 +- 6 files changed, 71 insertions(+), 16 deletions(-) diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports index 3cb6d645..1bd29fd0 100644 --- a/src/libopensc/libopensc.exports +++ b/src/libopensc/libopensc.exports @@ -213,6 +213,7 @@ sc_pkcs15emu_add_rsa_prkey sc_pkcs15emu_add_rsa_pubkey sc_pkcs15emu_add_x509_cert sc_pkcs15emu_object_add +sc_pkcs15emu_postponed_load sc_print_path sc_put_data sc_read_binary diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index 0ae304c4..b9b28664 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -379,7 +379,7 @@ sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, unsigned int type) if (!file) return NULL; sc_format_path("11001101", &file->path); - sc_pkcs15_add_df(p15card, type, &file->path, file); + sc_pkcs15_add_df(p15card, type, &file->path, file, NULL); sc_file_free(file); created++; } diff --git a/src/libopensc/pkcs15-syn.c b/src/libopensc/pkcs15-syn.c index 1d1c2d34..44f075a2 100644 --- a/src/libopensc/pkcs15-syn.c +++ b/src/libopensc/pkcs15-syn.c @@ -307,7 +307,7 @@ static sc_pkcs15_df_t * sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card, if (!file) return NULL; sc_format_path("11001101", &file->path); - sc_pkcs15_add_df(p15card, type, &file->path, file); + sc_pkcs15_add_df(p15card, type, &file->path, file, NULL); sc_file_free(file); created++; } @@ -416,3 +416,34 @@ int sc_pkcs15emu_object_add(sc_pkcs15_card_t *p15card, unsigned int type, return SC_SUCCESS; } + +int +sc_pkcs15emu_postponed_load(sc_pkcs15_card_t *p15card, unsigned long *loaded_mask) +{ + sc_context_t *ctx = p15card->card->ctx; + sc_pkcs15_df_t *df; + int r; + + SC_FUNC_CALLED(ctx, 1); + + if (loaded_mask) + *loaded_mask = 0; + + for (df = p15card->df_list; df; df = df->next) { + sc_debug(ctx, "Type:%X,enumerated:%i", df->type, df->enumerated); + if (df->enumerated) + continue; + if (!df->parse_handler) + continue; + r = df->parse_handler(p15card, df); + SC_TEST_RET(ctx, r, "DF parse error"); + + if (loaded_mask) + *loaded_mask |= (1 << df->type); + } + + if (loaded_mask) + sc_debug(ctx, "Loaded mask 0x%lX", *loaded_mask); + SC_FUNC_RETURN(ctx, 1, SC_SUCCESS); +} + diff --git a/src/libopensc/pkcs15.c b/src/libopensc/pkcs15.c index 3b33bef9..c6f6eafc 100644 --- a/src/libopensc/pkcs15.c +++ b/src/libopensc/pkcs15.c @@ -337,7 +337,7 @@ static int parse_odf(const u8 * buf, size_t buflen, struct sc_pkcs15_card *p15ca r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &path); if (r < 0) return r; - r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path, NULL); + r = sc_pkcs15_add_df(p15card, odf_indexes[type], &path, NULL, NULL); if (r) return r; } @@ -886,9 +886,15 @@ __sc_pkcs15_search_objects(sc_pkcs15_card_t *p15card, continue; /* Enumerate the DF's, so p15card->obj_list is * populated. */ - r = sc_pkcs15_parse_df(p15card, df); - SC_TEST_RET(p15card->card->ctx, r, "DF parsing failed"); - df->enumerated = 1; + if (df->parse_handler) { + r = df->parse_handler(p15card, df); + SC_TEST_RET(p15card->card->ctx, r, "DF parsing failed"); + } + else { + r = sc_pkcs15_parse_df(p15card, df); + SC_TEST_RET(p15card->card->ctx, r, "DF parsing failed"); + df->enumerated = 1; + } } /* And now loop over all objects */ @@ -1347,15 +1353,21 @@ void sc_pkcs15_free_object(struct sc_pkcs15_object *obj) int sc_pkcs15_add_df(struct sc_pkcs15_card *p15card, unsigned int type, const sc_path_t *path, - const sc_file_t *file) + const sc_file_t *file, + int (*parse_handler)(struct sc_pkcs15_card *, unsigned)) { - struct sc_pkcs15_df *p = p15card->df_list, *newdf; + struct sc_pkcs15_df *p, *newdf; + + for (p = p15card->df_list; p; p = p->next) + if (p->type == type) + return 0; newdf = (struct sc_pkcs15_df *) calloc(1, sizeof(struct sc_pkcs15_df)); if (newdf == NULL) return SC_ERROR_OUT_OF_MEMORY; newdf->path = *path; newdf->type = type; + newdf->parse_handler = parse_handler; if (file != NULL) { sc_file_dup(&newdf->file, file); if (newdf->file == NULL) { @@ -1364,10 +1376,13 @@ int sc_pkcs15_add_df(struct sc_pkcs15_card *p15card, } } + if (p15card->df_list == NULL) { p15card->df_list = newdf; return 0; } + + p = p15card->df_list; while (p->next != NULL) p = p->next; p->next = newdf; @@ -1461,6 +1476,9 @@ int sc_pkcs15_parse_df(struct sc_pkcs15_card *p15card, int (* func)(struct sc_pkcs15_card *, struct sc_pkcs15_object *, const u8 **nbuf, size_t *nbufsize) = NULL; + if (df->parse_handler) + return df->parse_handler(p15card, df->type); + switch (df->type) { case SC_PKCS15_PRKDF: func = sc_pkcs15_decode_prkdf_entry; diff --git a/src/libopensc/pkcs15.h b/src/libopensc/pkcs15.h index ec83f7ec..c1605a6f 100644 --- a/src/libopensc/pkcs15.h +++ b/src/libopensc/pkcs15.h @@ -356,6 +356,8 @@ typedef struct sc_pkcs15_object sc_pkcs15_object_t; #define SC_PKCS15_AODF 8 #define SC_PKCS15_DF_TYPE_COUNT 9 +struct sc_pkcs15_card; + struct sc_pkcs15_df { struct sc_file *file; @@ -364,6 +366,8 @@ struct sc_pkcs15_df { unsigned int type; int enumerated; + int (*parse_handler)(struct sc_pkcs15_card *, struct sc_pkcs15_df *); + struct sc_pkcs15_df *next, *prev; }; typedef struct sc_pkcs15_df sc_pkcs15_df_t; @@ -649,9 +653,9 @@ int sc_pkcs15_add_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj); void sc_pkcs15_remove_object(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj); -int sc_pkcs15_add_df(struct sc_pkcs15_card *p15card, - unsigned int type, const sc_path_t *path, - const struct sc_file *file); +int sc_pkcs15_add_df(struct sc_pkcs15_card *p15card, unsigned int type, + const sc_path_t *path, const struct sc_file *file, + int (*)(struct sc_pkcs15_card *, unsigned)); void sc_pkcs15_remove_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df); @@ -744,8 +748,8 @@ typedef struct sc_pkcs15emu_opt { extern int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *); extern int sc_pkcs15_is_emulation_only(sc_card_t *); -int sc_pkcs15emu_object_add(sc_pkcs15_card_t *p15card, unsigned int type, - const sc_pkcs15_object_t *obj, const void *data); +int sc_pkcs15emu_object_add(sc_pkcs15_card_t *, unsigned int, + const sc_pkcs15_object_t *, const void *); /* some wrapper functions for sc_pkcs15emu_object_add */ int sc_pkcs15emu_add_pin_obj(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_pin_info_t *); @@ -753,10 +757,11 @@ int sc_pkcs15emu_add_rsa_prkey(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_prkey_info_t *); int sc_pkcs15emu_add_rsa_pubkey(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_pubkey_info_t *); -int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *p15card, +int sc_pkcs15emu_add_x509_cert(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_cert_info_t *); -int sc_pkcs15emu_add_data_object(sc_pkcs15_card_t *p15card, +int sc_pkcs15emu_add_data_object(sc_pkcs15_card_t *, const sc_pkcs15_object_t *, const sc_pkcs15_data_info_t *); +int sc_pkcs15emu_postponed_load(sc_pkcs15_card_t *, unsigned long *); #ifdef __cplusplus } diff --git a/src/pkcs15init/pkcs15-lib.c b/src/pkcs15init/pkcs15-lib.c index 3f5c6ccc..ad911877 100644 --- a/src/pkcs15init/pkcs15-lib.c +++ b/src/pkcs15init/pkcs15-lib.c @@ -2554,7 +2554,7 @@ sc_pkcs15init_add_object(struct sc_pkcs15_card *p15card, sc_debug(ctx, "Profile doesn't define a DF file %u", df_type); SC_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "DF not found in profile"); } - sc_pkcs15_add_df(p15card, df_type, &file->path, file); + sc_pkcs15_add_df(p15card, df_type, &file->path, file, NULL); df = find_df_by_type(p15card, df_type); assert(df != NULL); is_new = 1;