update pkcs15 emulation stuff

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1916 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
nils 2004-10-08 21:29:55 +00:00
parent 0d4ca34973
commit 5a328e3dcc
10 changed files with 453 additions and 188 deletions

View File

@ -70,7 +70,7 @@ int sc_module_get_address(struct sc_context *ctx, void *mod_handle, void **sym_a
if (address == NULL) {
if (ctx->debug)
/* TODO: scdl_error */
sc_debug(ctx, "sc_module_get_address: unknown error");
sc_debug(ctx, "sc_module_get_address: unable to get symbol %s\n", sym_name);
return SC_ERROR_UNKNOWN;
}
*sym_address = address;

View File

@ -865,6 +865,13 @@ struct sc_card_error {
extern const char *sc_get_version(void);
#define IMPLEMENT_DRIVER_VERSION(a) \
static const char *drv_version = (a); \
const char *sc_driver_version()\
{ \
return drv_version; \
}
extern struct sc_reader_driver *sc_get_pcsc_driver(void);
extern struct sc_reader_driver *sc_get_ctapi_driver(void);
extern struct sc_reader_driver *sc_get_openct_driver(void);

View File

@ -197,3 +197,40 @@ sc_pkcs15emu_esteid_init (sc_pkcs15_card_t * p15card)
}
return 0;
}
static const char *atr1 = "3B:FE:94:00:FF:80:B1:FA:45:1F:03:45:73:74:45:49:44:20:76:65:72:20:31:2E:30:43";
static const char *atr2 = "3B:6E:00:FF:45:73:74:45:49:44:20:76:65:72:20:31:2E:30";
static int esteid_detect_card(sc_pkcs15_card_t *p15card)
{
u8 buf[SC_MAX_ATR_SIZE];
size_t len = sizeof(buf);
sc_card_t *card = p15card->card;
/* XXX: save type of the micardo card in the card structure */
if (sc_hex_to_bin(atr1, buf, &len))
return SC_ERROR_INTERNAL;
if (len == card->atr_len && !memcmp(card->atr, buf, len))
return SC_SUCCESS;
len = sizeof(buf);
if (sc_hex_to_bin(atr2, buf, &len))
return SC_ERROR_INTERNAL;
if (len == card->atr_len && !memcmp(card->atr, buf, len))
return SC_SUCCESS;
return SC_ERROR_WRONG_CARD;
}
int sc_pkcs15emu_esteid_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_esteid_init(p15card);
else {
int r = esteid_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_esteid_init(p15card);
}
}

View File

@ -73,7 +73,7 @@ sc_pkcs15emu_infocamere_init(sc_pkcs15_card_t *p15card)
int r;
size_t len_chn, len_iccsn;
sc_format_path("2F02", &path);
sc_format_path("3F002F02", &path);
r = sc_select_file(card, &path, &file);
@ -262,9 +262,33 @@ sc_pkcs15emu_infocamere_init(sc_pkcs15_card_t *p15card)
return 0;
failed: sc_error(card->ctx, "Failed to initialize Infocamere SPK2.3 emulation: %s\n",
sc_strerror(r));
failed:
if (r != SC_ERROR_WRONG_CARD)
sc_error(card->ctx, "Failed to initialize Infocamere SPK2.3 emulation: %s\n", sc_strerror(r));
return r;
}
static int infocamere_detect_card(sc_pkcs15_card_t *p15card)
{
sc_card_t *card = p15card->card;
/* check if we have the correct card OS */
if (strcmp(card->name, "STARCOS SPK 2.3"))
return SC_ERROR_WRONG_CARD;
return SC_SUCCESS;
}
int sc_pkcs15emu_infocamere_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_infocamere_init(p15card);
else {
int r = infocamere_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_infocamere_init(p15card);
}
}

View File

@ -194,3 +194,33 @@ failed:
sc_debug(card->ctx, "Failed to initialize TeleSec Netkey E4 emulation: %s\n", sc_strerror(r));
return r;
}
static int netkey_detect_card(sc_pkcs15_card_t *p15card)
{
int r;
sc_path_t path;
sc_card_t *card = p15card->card;
/* check if we have the correct card OS */
if (strcmp(card->name, "TCOS"))
return SC_ERROR_WRONG_CARD;
/* check if we have a df01 DF */
sc_format_path("3F00DF01", &path);
r = sc_select_file(card, &path, NULL);
if (r < 0)
return SC_ERROR_WRONG_CARD;
return SC_SUCCESS;
}
int sc_pkcs15emu_netkey_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_netkey_init(p15card);
else {
int r = netkey_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_netkey_init(p15card);
}
}

View File

@ -201,3 +201,21 @@ failed: sc_error(card->ctx, "Failed to initialize OpenPGP emulation: %s\n",
return r;
}
static int openpgp_detect_card(sc_pkcs15_card_t *p15card)
{
return strcmp(p15card->card->name, "OpenPGP");
}
int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_openpgp_init(p15card);
else {
int r = openpgp_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_openpgp_init(p15card);
}
}

View File

@ -98,7 +98,7 @@ const prdata prkeys[] = {
{ NULL, NULL, 0, 0, NULL, 0, NULL, 0}
};
int get_cert_len(sc_card_t *card, sc_path_t *path)
static int get_cert_len(sc_card_t *card, sc_path_t *path)
{
int r;
u8 buf[8];
@ -117,6 +117,32 @@ int get_cert_len(sc_card_t *card, sc_path_t *path)
return 1;
}
static int starcert_detect_card(sc_pkcs15_card_t *p15card)
{
int r;
u8 buf[128];
sc_path_t path;
sc_card_t *card = p15card->card;
/* check if we have the correct card OS */
if (strcmp(card->name, "STARCOS SPK 2.3"))
return SC_ERROR_WRONG_CARD;
/* read EF_Info file */
sc_format_path("3F00FE13", &path);
card->ctx->suppress_errors++;
r = sc_select_file(card, &path, NULL);
card->ctx->suppress_errors--;
if (r != SC_SUCCESS)
return SC_ERROR_WRONG_CARD;
r = sc_read_binary(card, 0, buf, 64, 0);
if (r != 64)
return SC_ERROR_WRONG_CARD;
if (memcmp(buf + 24, STARCERT, strlen(STARCERT)))
return SC_ERROR_WRONG_CARD;
return SC_SUCCESS;
}
int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card)
{
int r, i;
@ -126,21 +152,6 @@ int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card)
struct sc_card *card = p15card->card;
struct sc_serial_number serial;
/* check if we have the correct card OS */
if (strcmp(card->name, "STARCOS SPK 2.3"))
return SC_ERROR_WRONG_CARD;
/* read EF_Info file */
sc_format_path("3F00FE13", &path);
card->ctx->suppress_errors++;
r = sc_select_file(card, &path, &file);
card->ctx->suppress_errors--;
if (r != SC_SUCCESS)
return SC_ERROR_WRONG_CARD;
r = sc_read_binary(card, 0, buf, 64, 0);
if (r != 64)
return SC_ERROR_WRONG_CARD;
if (memcmp(buf + 24, STARCERT, strlen(STARCERT)))
return SC_ERROR_WRONG_CARD;
/* get serial number */
r = sc_card_ctl(card, SC_CARDCTL_GET_SERIALNR, &serial);
r = sc_bin_to_hex(serial.value, serial.len, buf, sizeof(buf), 0);
@ -217,3 +228,17 @@ int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *p15card)
return SC_SUCCESS;
}
int sc_pkcs15emu_starcert_init_ex(sc_pkcs15_card_t *p15card,
sc_pkcs15emu_opt_t *opts)
{
if (opts && opts->flags & SC_PKCS15EMU_FLAGS_NO_CHECK)
return sc_pkcs15emu_starcert_init(p15card);
else {
int r = starcert_detect_card(p15card);
if (r)
return SC_ERROR_WRONG_CARD;
return sc_pkcs15emu_starcert_init(p15card);
}
}

View File

@ -2,6 +2,7 @@
* pkcs15-syn.c: PKCS #15 emulation of non-pkcs15 cards
*
* Copyright (C) 2003 Olaf Kirch <okir@suse.de>
* 2004 Nils Larsch <nlarsch@betrusted.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -26,39 +27,47 @@
#include <stdio.h>
#include <assert.h>
static int sc_pkcs15_bind_emulation(sc_pkcs15_card_t *, const char *,
scconf_block *, int);
extern int sc_pkcs15emu_openpgp_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_infocamere_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_starcert_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_netkey_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_esteid_init(sc_pkcs15_card_t *);
extern int sc_pkcs15emu_openpgp_init_ex(sc_pkcs15_card_t *,
sc_pkcs15emu_opt_t *);
extern int sc_pkcs15emu_infocamere_init_ex(sc_pkcs15_card_t *,
sc_pkcs15emu_opt_t *);
extern int sc_pkcs15emu_starcert_init_ex(sc_pkcs15_card_t *,
sc_pkcs15emu_opt_t *);
extern int sc_pkcs15emu_netkey_init_ex(sc_pkcs15_card_t *,
sc_pkcs15emu_opt_t *);
extern int sc_pkcs15emu_esteid_init_ex(sc_pkcs15_card_t *,
sc_pkcs15emu_opt_t *);
static struct {
const char * name;
int (*handler)(sc_pkcs15_card_t *);
int (*handler)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
} builtin_emulators[] = {
{ "openpgp", sc_pkcs15emu_openpgp_init },
{ "infocamere", sc_pkcs15emu_infocamere_init },
{ "starcert", sc_pkcs15emu_starcert_init },
{ "netkey", sc_pkcs15emu_netkey_init },
{ "esteid", sc_pkcs15emu_esteid_init },
{ "openpgp", sc_pkcs15emu_openpgp_init_ex },
{ "infocamere", sc_pkcs15emu_infocamere_init_ex },
{ "starcert", sc_pkcs15emu_starcert_init_ex },
{ "netkey", sc_pkcs15emu_netkey_init_ex },
{ "esteid", sc_pkcs15emu_esteid_init_ex },
{ NULL }
};
static int parse_emu_block(sc_pkcs15_card_t *, scconf_block *);
static const char *builtin_name = "builtin";
static const char *func_name = "sc_pkcs15_init_func";
static const char *exfunc_name = "sc_pkcs15_init_func_ex";
int
sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card, int check_atr)
sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card)
{
sc_context_t *ctx = p15card->card->ctx;
const scconf_list *clist, *tmp;
scconf_block *conf_block, **blocks, *blk;
int i, r;
sc_pkcs15emu_opt_t opts;
int i, r = SC_ERROR_WRONG_CARD;
SC_FUNC_CALLED(ctx, 1);
assert(p15card);
memset(&opts, 0, sizeof(opts));
conf_block = NULL;
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
@ -68,43 +77,60 @@ sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *p15card, int check_atr)
conf_block = blocks[0];
free(blocks);
}
if (!conf_block)
return SC_ERROR_WRONG_CARD;
/* Old-style: get the pkcs15_syn libs from the conf file */
clist = scconf_find_list(conf_block, "pkcs15_syn");
for (tmp = clist; tmp != NULL; tmp = tmp->next) {
const char *module = tmp->data;
if (module == NULL)
continue;
r = sc_pkcs15_bind_emulation(p15card, module, NULL, check_atr);
if (r != SC_ERROR_WRONG_CARD)
goto out;
}
/* New-style: get lib name, function name, ATR list */
blocks = scconf_find_blocks(ctx->conf, conf_block, "emulate", NULL);
for (i = 0; (blk = blocks[i]) != NULL; i++) {
const char *module;
module = scconf_get_str(blk, "module", NULL);
if (!module)
continue;
r = sc_pkcs15_bind_emulation(p15card, module, blk, check_atr);
if (r != SC_ERROR_WRONG_CARD) {
free(blocks);
goto out;
if (!conf_block) {
/* no conf file found => try the internal drivers */
sc_debug(ctx, "no conf file, trying builtin emulators\n");
for (i = 0; builtin_emulators[i].name; i++) {
sc_debug(ctx, "trying %s\n", builtin_emulators[i].name);
r = builtin_emulators[i].handler(p15card, &opts);
if (r == SC_SUCCESS)
/* we got a hit */
goto out;
}
}
free(blocks);
} else {
/* we have a conf file => let's use it */
const scconf_list *list, *item;
/* find out if the internal drivers should be used */
i = scconf_get_bool(conf_block, "enable_builtin_emulation", 1);
if (i) {
/* get the list of the internal drivers */
sc_debug(ctx, "use builtin drivers\n");
list = scconf_find_list(conf_block, "builtin_emulators");
for (item = list; item; item = item->next) {
/* get through the list of builtin drivers */
const char *name = item->data;
sc_debug(ctx, "trying %s\n", name);
for (i = 0; builtin_emulators[i].name; i++)
if (!strcmp(builtin_emulators[i].name, name)) {
r = builtin_emulators[i].handler(p15card, &opts);
if (r == SC_SUCCESS)
goto out;
}
}
}
/* search for 'emulate foo { ... }' entries in the conf file */
sc_debug(ctx, "searching for 'emulate foo { ... }' blocks\n");
blocks = scconf_find_blocks(ctx->conf, conf_block, "emulate", NULL);
for (i = 0; (blk = blocks[i]) != NULL; i++) {
const char *name = blk->name->data;
sc_debug(ctx, "trying %s\n", name);
r = parse_emu_block(p15card, blk);
if (r == SC_SUCCESS) {
free(blocks);
goto out;
}
}
if (blocks)
free(blocks);
}
/* Total failure */
return SC_ERROR_WRONG_CARD;
out: if (r == SC_SUCCESS) {
/* p15card->flags |= SC_PKCS15_CARD_FLAG_READONLY; */
p15card->magic = 0x10203040;
} else if (r != SC_ERROR_WRONG_CARD) {
sc_error(ctx, "Failed to load card emulator: %s\n",
@ -114,94 +140,119 @@ out: if (r == SC_SUCCESS) {
return r;
}
int
sc_pkcs15_bind_emulation(sc_pkcs15_card_t *p15card,
const char *module_name,
scconf_block *conf,
int check_atr)
static int emu_detect_card(const sc_card_t *card, const scconf_block *blk)
{
int r = 1, match = 0;
const scconf_list *list, *item;
/* currently only ATR matching is supported (more to follow) */
/* check the ATR */
list = scconf_find_list(blk, "atr");
if (list) {
for (item = list; item; item = item->next) {
u8 atr[SC_MAX_ATR_SIZE];
size_t len = sizeof(atr);
if (!item->data)
/* skip empty data */
continue;
if (sc_hex_to_bin(item->data, atr, &len) != SC_SUCCESS)
/* ignore errors, try next atr */
continue;
if (len == card->atr_len && !memcmp(card->atr, atr, len)){
match = 1;
break;
}
}
if (match)
r = 1;
else
r = 0;
}
return r;
}
static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
{
sc_card_t *card = p15card->card;
sc_context_t *ctx = card->ctx;
const scconf_list *list, *item;
sc_pkcs15emu_opt_t opts;
void *dll = NULL;
int (*init_func)(sc_pkcs15_card_t *);
int (*init_func_ex)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
int r;
const char *module_name;
if (conf && (list = scconf_find_list(conf, "atr"))) {
int match = 0;
if (!check_atr)
return SC_ERROR_WRONG_CARD;
for (item = list; item; item = item->next) {
u8 atr[SC_MAX_ATR_SIZE];
size_t len = sizeof(atr);
if (!item->data)
continue;
if (sc_hex_to_bin(item->data, atr, &len))
continue;
if (len > card->atr_len
|| memcmp(card->atr, atr, len))
continue;
match = 1;
break;
}
if (!match)
return SC_ERROR_WRONG_CARD;
} else if (!check_atr) {
/* ATR checking required, but no ATR list to match against */
r = emu_detect_card(card, conf);
if (!r)
return SC_ERROR_WRONG_CARD;
}
init_func = NULL;
init_func = NULL;
init_func_ex = NULL;
opts.blk = conf;
opts.flags = SC_PKCS15EMU_FLAGS_NO_CHECK;
module_name = scconf_get_str(conf, "module", builtin_name);
if (!strcmp(module_name, "builtin")) {
int i;
/* This function is built into libopensc itself.
* Look it up in the table of emulators */
if (conf == NULL || !conf->name)
if (!conf->name)
return SC_ERROR_INTERNAL;
module_name = conf->name->data;
for (i = 0; builtin_emulators[i].name; i++) {
if (!strcmp(builtin_emulators[i].name, module_name)) {
init_func = builtin_emulators[i].handler;
init_func_ex = builtin_emulators[i].handler;
break;
}
}
if (!init_func)
return SC_ERROR_WRONG_CARD;
} else {
const char *function_name = NULL;
const char *(*get_version)(void);
const char *name = NULL;
void *address;
if (ctx->debug >= 4)
sc_debug(ctx, "Loading %s\n", module_name);
sc_debug(ctx, "Loading %s\n", module_name);
/* try to open dynamic library */
r = sc_module_open(ctx, &dll, module_name);
if (r != SC_SUCCESS)
return r;
/* try to get version of the driver/api */
r = sc_module_get_address(ctx, dll, &address, "sc_driver_version");
if (r < 0)
get_version = NULL;
else
get_version = (const char *(*)())address;
if (!get_version || strcmp(get_version(), "0.9.3") < 0) {
/* no sc_driver_version function => assume old style
* init function (note: this should later give an error
*/
/* get the init function name */
name = scconf_get_str(conf, "function", func_name);
/* get a handle to the pkcs15 init function
* XXX the init_func should not modify the contents of
* sc_pkcs15_card_t unless the card is really the one
* the driver is intended for -- Nils
*/
if (conf)
function_name = scconf_get_str(conf, "function", NULL);
if (function_name == NULL)
function_name = "sc_pkcs15_init_func";
r = sc_module_get_address(ctx, dll, &address, name);
if (r == SC_SUCCESS)
init_func = (int (*)(sc_pkcs15_card_t *)) address;
} else {
name = scconf_get_str(conf, "function", exfunc_name);
r = sc_module_get_address(ctx, dll, &address, function_name);
if (r != SC_SUCCESS)
return r;
/* try to initialize synthetic pkcs15 structures */
init_func = (int (*)(sc_pkcs15_card_t *)) address;
r = sc_module_get_address(ctx, dll, &address, name);
if (r == SC_SUCCESS)
init_func_ex = (int (*)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *)) address;
}
}
/* try to initialize the pkcs15 structures */
if (init_func_ex)
r = init_func_ex(p15card, &opts);
else if (init_func)
r = init_func(p15card);
else
r = SC_ERROR_WRONG_CARD;
r = init_func(p15card);
if (r >= 0) {
sc_debug(card->ctx, "%s succeeded, card bound\n",
module_name);
@ -209,6 +260,8 @@ sc_pkcs15_bind_emulation(sc_pkcs15_card_t *p15card,
} else if (ctx->debug >= 4) {
sc_debug(card->ctx, "%s failed: %s\n",
module_name, sc_strerror(r));
/* clear pkcs15 card */
sc_pkcs15_card_clear(p15card);
if (dll)
sc_module_close(ctx, dll);
}

View File

@ -222,9 +222,9 @@ static int encode_ddo(struct sc_pkcs15_card *p15card, u8 **buf, size_t *buflen)
}
#endif
#if 0
int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card, struct sc_card *card)
{
#if 0
struct sc_path path;
struct sc_file file;
u8 *buf;
@ -266,9 +266,9 @@ int sc_pkcs15_create_dir(struct sc_pkcs15_card *p15card, struct sc_card *card)
r = sc_update_binary(card, 0, buf, bufsize, 0);
free(buf);
SC_TEST_RET(card->ctx, r, "Error updating EF(DIR)");
#endif
return 0;
}
#endif
static const struct sc_asn1_entry c_asn1_odf[] = {
{ "privateKeys", SC_ASN1_STRUCT, SC_ASN1_CTX | 0 | SC_ASN1_CONS, 0, NULL },
@ -420,70 +420,70 @@ void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card)
free(p15card);
}
int sc_pkcs15_bind(struct sc_card *card,
struct sc_pkcs15_card **p15card_out)
void sc_pkcs15_card_clear(sc_pkcs15_card_t *p15card)
{
p15card->version = 0;
p15card->flags = 0;
while (p15card->obj_list)
sc_pkcs15_remove_object(p15card, p15card->obj_list);
p15card->obj_list = NULL;
while (p15card->df_list)
sc_pkcs15_remove_df(p15card, p15card->df_list);
p15card->df_list = NULL;
if (p15card->file_app) {
sc_file_free(p15card->file_app);
p15card->file_app = NULL;
}
if (p15card->file_tokeninfo) {
sc_file_free(p15card->file_tokeninfo);
p15card->file_tokeninfo = NULL;
}
if (p15card->file_odf) {
sc_file_free(p15card->file_odf);
p15card->file_odf = NULL;
}
if (p15card->label) {
free(p15card->label);
p15card->label = NULL;
}
if (p15card->serial_number) {
free(p15card->serial_number);
p15card->serial_number = NULL;
}
if (p15card->manufacturer_id) {
free(p15card->manufacturer_id);
p15card->manufacturer_id = NULL;
}
if (p15card->preferred_language) {
free(p15card->preferred_language);
p15card->preferred_language = NULL;
}
}
static int sc_pkcs15_bind_internal(sc_pkcs15_card_t *p15card)
{
unsigned char buf[SC_MAX_APDU_BUFFER_SIZE];
int err;
int err, ok = 0;
size_t len;
struct sc_pkcs15_card *p15card = NULL;
struct sc_path tmppath;
struct sc_context *ctx;
scconf_block *conf_block = NULL, **blocks;
int i;
struct sc_card *card = p15card->card;
struct sc_context *ctx = card->ctx;
assert(sc_card_valid(card) && p15card_out != NULL);
ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1);
p15card = sc_pkcs15_card_new();
if (p15card == NULL)
return SC_ERROR_OUT_OF_MEMORY;
p15card->card = card;
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
"framework", "pkcs15");
if (blocks[0] != NULL)
conf_block = blocks[0];
free(blocks);
}
if (conf_block)
p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0);
err = sc_lock(card);
if (err) {
sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(err));
sc_pkcs15_card_free(p15card);
SC_FUNC_RETURN(ctx, 1, err);
}
/* Check for non-pkcs15 cards that we emulate. We do this
* twice - first, we check all emulators that list the ATRs
* they match - the OpenPGP emulator is one of them.
*
* If we find no emulator at this stage, we do the normal
* pkcs15 stuff - looking for EF(DIR), trying to locate the
* application DF, parsing EF(TokenInfo) etc etc.
*
* If that fails, too, we check all other emulators as a last
* resort.
*/
err = sc_pkcs15_bind_synthetic(p15card, 1);
if (err >= 0)
goto done;
if (ctx->debug > 4)
sc_debug(ctx, "trying normal pkcs15 processing\n");
/* Enumerate apps now */
if (card->app_count < 0) {
err = sc_enum_apps(card);
if (err < 0 && err != SC_ERROR_FILE_NOT_FOUND) {
sc_error(ctx, "unable to enumerate apps: %s\n", sc_strerror(err));
goto error;
goto end;
}
}
p15card->file_app = sc_file_new();
if (p15card->file_app == NULL) {
err = SC_ERROR_OUT_OF_MEMORY;
goto error;
goto end;
}
sc_format_path("3F005015", &p15card->file_app->path);
if (card->app_count > 0) {
@ -502,12 +502,8 @@ int sc_pkcs15_bind(struct sc_card *card,
card->ctx->suppress_errors++;
err = sc_select_file(card, &p15card->file_app->path, NULL);
card->ctx->suppress_errors--;
if (err < 0) {
err = sc_pkcs15_bind_synthetic(p15card, 0);
if (err < 0)
goto error;
goto done;
}
if (err < 0)
goto end;
if (p15card->file_odf == NULL) {
tmppath = p15card->file_app->path;
@ -519,7 +515,7 @@ int sc_pkcs15_bind(struct sc_card *card,
}
err = sc_select_file(card, &tmppath, &p15card->file_odf);
if (err) /* FIXME: finish writing error reporting stuff */
goto error;
goto end;
/* XXX: fix buffer overflow. Silently truncate ODF if it
* is too large. --okir */
@ -527,16 +523,16 @@ int sc_pkcs15_bind(struct sc_card *card,
len = sizeof(buf);
err = sc_read_binary(card, 0, buf, len, 0);
if (err < 0)
goto error;
goto end;
if (err < 2) {
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
goto error;
goto end;
}
len = err;
if (parse_odf(buf, len, p15card)) {
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
sc_error(card->ctx, "Unable to parse ODF\n");
goto error;
goto end;
}
if (card->ctx->debug) {
@ -561,19 +557,85 @@ int sc_pkcs15_bind(struct sc_card *card,
}
err = sc_select_file(card, &tmppath, &p15card->file_tokeninfo);
if (err)
goto error;
goto end;
if ((len = p15card->file_tokeninfo->size) > sizeof(buf))
len = sizeof(buf);
err = sc_read_binary(card, 0, buf, len, 0);
if (err < 0)
goto error;
goto end;
if (err <= 2) {
err = SC_ERROR_PKCS15_APP_NOT_FOUND;
goto error;
goto end;
}
parse_tokeninfo(p15card, buf, err);
ok = 1;
end:
if (!ok) {
sc_pkcs15_card_clear(p15card);
return err;
}
return SC_SUCCESS;
}
int sc_pkcs15_bind(struct sc_card *card,
struct sc_pkcs15_card **p15card_out)
{
struct sc_pkcs15_card *p15card = NULL;
struct sc_context *ctx;
scconf_block *conf_block = NULL, **blocks;
int i, r, emu_first, enable_emu;
assert(sc_card_valid(card) && p15card_out != NULL);
ctx = card->ctx;
SC_FUNC_CALLED(ctx, 1);
p15card = sc_pkcs15_card_new();
if (p15card == NULL)
return SC_ERROR_OUT_OF_MEMORY;
p15card->card = card;
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i],
"framework", "pkcs15");
if (blocks[0] != NULL)
conf_block = blocks[0];
free(blocks);
}
if (conf_block)
p15card->opts.use_cache = scconf_get_bool(conf_block, "use_caching", 0);
r = sc_lock(card);
if (r) {
sc_error(ctx, "sc_lock() failed: %s\n", sc_strerror(r));
sc_pkcs15_card_free(p15card);
SC_FUNC_RETURN(ctx, 1, r);
}
enable_emu = scconf_get_bool(conf_block, "enable_pkcs15_emulation", 1);
if (enable_emu) {
emu_first = scconf_get_bool(conf_block, "try_emulation_first", 0);
if (emu_first) {
r = sc_pkcs15_bind_synthetic(p15card);
if (r == SC_SUCCESS)
goto done;
r = sc_pkcs15_bind_internal(p15card);
if (r < 0)
goto error;
} else {
r = sc_pkcs15_bind_internal(p15card);
if (r == SC_SUCCESS)
goto done;
r = sc_pkcs15_bind_synthetic(p15card);
if (r < 0)
goto error;
}
} else {
r = sc_pkcs15_bind_internal(p15card);
if (r < 0)
goto error;
}
done:
*p15card_out = p15card;
sc_unlock(card);
@ -581,7 +643,7 @@ done:
error:
sc_unlock(card);
sc_pkcs15_card_free(p15card);
SC_FUNC_RETURN(ctx, 1, err);
SC_FUNC_RETURN(ctx, 1, r);
}
int sc_pkcs15_detect(struct sc_card *card)

View File

@ -383,6 +383,7 @@ int sc_pkcs15_find_object_by_id(sc_pkcs15_card_t *, int,
struct sc_pkcs15_card * sc_pkcs15_card_new(void);
void sc_pkcs15_card_free(struct sc_pkcs15_card *p15card);
void sc_pkcs15_card_clear(sc_pkcs15_card_t *p15card);
int sc_pkcs15_decipher(struct sc_pkcs15_card *p15card,
const struct sc_pkcs15_object *prkey_obj,
@ -601,7 +602,15 @@ typedef struct sc_pkcs15_search_key {
int sc_pkcs15_search_objects(sc_pkcs15_card_t *, sc_pkcs15_search_key_t *,
sc_pkcs15_object_t **, size_t);
extern int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *, int);
/* This structure is passed to the new sc_pkcs15emu_*_init functions */
typedef struct sc_pkcs15emu_opt {
scconf_block *blk;
unsigned int flags;
} sc_pkcs15emu_opt_t;
#define SC_PKCS15EMU_FLAGS_NO_CHECK 0x00000001
extern int sc_pkcs15_bind_synthetic(sc_pkcs15_card_t *);
sc_pkcs15_df_t *sc_pkcs15emu_get_df(sc_pkcs15_card_t *p15card,
int type);