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
This commit is contained in:
viktor.tarasov 2010-03-09 16:49:00 +00:00
parent e47baeaf9e
commit 3a2f0415fe
6 changed files with 71 additions and 16 deletions

View File

@ -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

View File

@ -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++;
}

View File

@ -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);
}

View File

@ -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;

View File

@ -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
}

View File

@ -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;