From 9468d989cf5f279e11f1551164624c2cd1b25948 Mon Sep 17 00:00:00 2001 From: aj Date: Wed, 20 Aug 2008 15:17:59 +0000 Subject: [PATCH] Douglas E. Engert: The pkcs15-gemsafeV1.c code assumes that the key_ref is always 3. But that is not always the case. In our case it is 4. The patch tries to determine the key_ref by looking at what appears to be a table of allocated keys, and picking the first allocated key. In case this is not always true, the patch will also allow for the the opensc.conf card flag = n to specify the key_ref as the low order 4 bits of the flag. git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3557 c6295689-39f2-0310-b995-f0e70906c6a9 --- src/libopensc/pkcs15-gemsafeV1.c | 39 +++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/src/libopensc/pkcs15-gemsafeV1.c b/src/libopensc/pkcs15-gemsafeV1.c index c8ccdc07..108336ef 100644 --- a/src/libopensc/pkcs15-gemsafeV1.c +++ b/src/libopensc/pkcs15-gemsafeV1.c @@ -114,10 +114,12 @@ const prdata gemsafe_prkeys[] = { { NULL, NULL, 0, 0, NULL, 0, NULL, 0} }; -static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path) +static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path, + int *key_ref) { const char *fn_name = "gemsafe_get_cert_len"; int r; + int ind; u8 ibuf[248]; struct sc_file *file; size_t objlen, certlen; @@ -146,6 +148,26 @@ static int gemsafe_get_cert_len(sc_card_t *card, sc_path_t *path) return 0; } + /* + * We need to find the private key associated with the cert + * It looks like the first thing in the block is a table of + * which keys are allocated. + * We will look for the first allocated key, and save the + * key_ref. The table is small and is in the first 248 bytes. + * If for some reason this is not true, we can still override + * the key_ref in the opensc.conf with flag = n. + */ + ind = 2; /* skip length */ + while (ibuf[ind] == 0x01) { + if (ibuf[ind+1] == 0xFE) { + *key_ref = ibuf[ind+4]; + sc_debug(card->ctx, "Using key_ref %d found at offset %d\n", + *key_ref, ind); + break; + } + ind = ind + 8; + } + /* Using (block+1) in while loop avoids using final cert object data block */ while (!found && ( (block+1) * 248 < objlen) ) { /* Check current buffer */ @@ -193,6 +215,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) const char *fn_name = "sc_pkcs15emu_gemsafe_init"; int r, i; + int key_ref = 0x03; struct sc_path path; struct sc_file *file = NULL; struct sc_card *card = p15card->card; @@ -252,7 +275,7 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) struct sc_pkcs15_id p15Id; sc_format_path(gemsafe_cert[i].path, &path); - if (!gemsafe_get_cert_len(card, &path)) + if (!gemsafe_get_cert_len(card, &path, &key_ref)) /* skip errors */ continue; sc_pkcs15_format_id(gemsafe_cert[i].id, &p15Id); @@ -284,10 +307,20 @@ static int sc_pkcs15emu_gemsafeV1_init( sc_pkcs15_card_t *p15card) pauthId = &authId; } else pauthId = NULL; + /* + * the key ref may be different for different sites + * by adding flags=n where the low order 4 bits can be + * the key ref we can force it. + */ + if ( p15card->card->flags & 0x0F) { + key_ref = p15card->card->flags & 0x0F; + sc_debug(p15card->card->ctx, + "Overriding key_ref with %d\n", key_ref); + } sc_pkcs15emu_add_prkey(p15card, &p15Id, gemsafe_prkeys[i].label, SC_PKCS15_TYPE_PRKEY_RSA, gemsafe_prkeys[i].modulus_len, gemsafe_prkeys[i].usage, - &path, gemsafe_prkeys[i].ref, pauthId, + &path, key_ref, pauthId, gemsafe_prkeys[i].obj_flags); }