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:
parent
0d4ca34973
commit
5a328e3dcc
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue