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;