- Introduce a new powerful card_atr mechanism to opensc

configuration file to handle any configuring related
  to certain card / cards using atrmask.
- Rewrite Martin's force_protocol to _sc_check_forced_protocol()
  to make it possible to share the code with other reader driver
  implementations than pcsc.
- Implement _sc_match_atr_block() to help out with force protocol
  and pkcs15 emulation layers, to find information that's not
  stored directly to sc_atr_table.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@2192 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
aet 2005-02-22 07:59:42 +00:00
parent b80890d49c
commit 8a8f2cd6bc
8 changed files with 323 additions and 146 deletions

View File

@ -102,34 +102,12 @@ app default {
# Card driver configuration blocks.
# For all drivers, you can specify ATRs of cards that
# should be handled by this driver (in addition to the
# list of compiled-in ATRs).
#
# The supported internal card driver names are
# flex Cryptoflex/Multiflex
# setcos Setec
# etoken Aladdin eToken and other CardOS based cards
# gpk GPK 4K/8K/16K
# mcrd MICARDO 2.1
# miocos MioCOS 1.1
# openpgp OpenPGP card
# tcos TCOS 2.0
# emv EMV compatible cards
# GPK card driver additional ATR entry:
card_driver gpk {
# atr = 00:11:22;
}
# For card drivers loaded from an external shared library/DLL,
# you need to specify the path name of the module
#
# card_driver customcos {
# The location of the driver library
# module = /usr/lib/opensc/drivers/card_customcos.so;
# atr = 00:11:22:33:44;
# atr = 55:66:77:88:99:aa:bb;
# }
# Force using specific card driver
@ -141,6 +119,108 @@ app default {
#
# force_card_driver = customcos;
# In addition to the built-in list of known cards in the
# card driver, you can configure a new card for the driver
# using the card_atr block. The goal is to centralize
# everything related to a certain card to card_atr.
#
# The supported internal card driver names are
# etoken Aladdin eToken and other Siemens CardOS cards
# flex Schlumberger Multiflex/Cryptoflex
# cyberflex Schlumberger Cyberflex
# gpk Gemplus GPK
# miocos MioCOS 1.1
# mcrd MICARDO 2.1
# setcos Setec cards
# starcos STARCOS SPK 2.3
# tcos TCOS 2.0
# openpgp OpenPGP card
# jcop JCOP cards with BlueZ PKCS#15 applet
# oberthur Oberthur AuthentIC.v2/CosmopolIC.v4
# belpic Belpic cards
# emv EMV compatible cards
# Generic format: card_atr <hex encoded ATR (case-sensitive!)>
# New card entry for the flex card driver
# card_atr 3b:f0:0d:ca:fe {
# All parameters for the context are
# optional unless specified otherwise.
# Context: global, card driver
#
# ATR mask value
#
# The mask is logically AND'd with an
# card ATR prior to comparison with the
# ATR reference value above. Using mask
# allows identifying and configuring
# multiple ATRs as the same card model.
# atrmask = "ff:ff:ff:ff:ff";
# Context: card driver
#
# Specify used card driver (REQUIRED).
#
# When enabled, overrides all possible
# settings from the card drivers built-in
# card configuration list.
# driver = "flex";
# Set card name for card drivers that allows it.
# name = "My CryptoFlex card";
# Card type as an integer value.
#
# Depending on card driver, this allows
# tuning the behaviour of the card driver
# for your card.
# type = "2002";
# Card flags as an hex value.
# Multiple values are OR'd together.
#
# Depending on card driver, this allows
# fine-tuning the capabilities in
# the card driver for your card.
#
# Optionally, some known parameters
# can be specified as strings:
#
# keygen - On-board key generation capability
# rng - On-board random number source
#
# flags = "keygen", "rng", "0x80000000";
#
# Context: PKCS#15 emulation layer
#
# When using PKCS#15 emulation, force
# the emulation driver for specific cards.
#
# Required for external drivers, but can
# be used with built-in drivers, too.
# pkcs15emu = "custom";
#
# Context: reader driver
#
# Force protocol selection for specific cards.
# Known parameters: t0, t1, raw
# force_protocol = "t0";
# }
# Estonian ID card and Micardo driver currently play together with T=0 only.
# In theory only the 'cold' ATR should be specified, as T=0 will be the preferred
# protocol once you boot it up with T=0, but be paranoid.
card_atr 3b:6e:00:ff:45:73:74:45:49:44:20:76:65:72:20:31:2e:30 {
force_protocol = t0;
}
card_atr 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 {
force_protocol = t0;
}
# Below are the framework specific configuration blocks.
# PKCS #15
@ -172,27 +252,14 @@ app default {
# additional settings per driver
#
# For pkcs15 emulators loaded from an external shared library/DLL,
# you need to specify the path name of the module
# you need to specify the path name of the module and customize
# the card_atr example above correctly.
#
# emulate custom {
# The location of the driver library
# module = builtin;
# atr = 11:22:33:44;
# module = /usr/lib/opensc/drivers/p15emu_custom.so;
# }
}
# Estonian ID card and Micardo driver currently play together with T=0 only.
# In theory only the 'cold' ATR should be specified, as T=0 will be the preferred
# protocol once you boot it up with T=0, but be paranoid.
# Generic format: card_atr <hex encoded ATR (case-sensitive!)>
# Only parameter currently understood is force_protocol
card_atr 3b:6e:00:ff:45:73:74:45:49:44:20:76:65:72:20:31:2e:30 {
force_protocol = t0;
}
card_atr 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 {
force_protocol = t0;
}
}
# For applications that use SCAM (pam_opensc, sia_opensc)

View File

@ -23,9 +23,6 @@
#include <stdlib.h>
#include <string.h>
#define FLAG_KEYGEN 0x0001
#define FLAG_FULL_DES 0x0002 /* whatever that means */
#define IS_CYBERFLEX(card) (card->type == SC_CARD_TYPE_FLEX_CYBER)
static struct sc_atr_table flex_atrs[] = {
@ -37,21 +34,21 @@ static struct sc_atr_table flex_atrs[] = {
/* 8k */
{ "3B:85:40:20:68:01:01:05:01", NULL, "Cryptoflex 8K", SC_CARD_TYPE_FLEX_CRYPTO, 0 },
/* 16k */
{ "3B:95:94:40:FF:63:01:01:02:01", NULL, "Cryptoflex 16K", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:95:94:40:FF:63:01:01:02:01", NULL, "Cryptoflex 16K", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
/* 32K v4 */
{ "3B:95:18:40:FF:64:02:01:01:02", NULL, "Cryptoflex 32K v4", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:95:18:40:FF:64:02:01:01:02", NULL, "Cryptoflex 32K v4", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
/* 32K e-gate */
{ "3B:95:18:40:FF:62:01:02:01:04", NULL, "Cryptoflex 32K e-gate", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:95:18:40:FF:62:01:02:01:04", NULL, "Cryptoflex 32K e-gate", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
/* 32K e-gate v4 */
{ "3B:95:18:40:FF:62:04:01:01:05", NULL, "Cryptoflex 32K e-gate v4", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:95:18:40:FF:62:04:01:01:05", NULL, "Cryptoflex 32K e-gate v4", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
{ "3B:E2:00:00:40:20:49:06", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, 0 },
/* + full DES option */
{ "3B:E2:00:00:40:20:49:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_FULL_DES },
{ "3B:E2:00:00:40:20:49:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, 0 },
/* + Key Generation */
{ "3B:E2:00:00:40:20:49:07", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:E2:00:00:40:20:49:07", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
/* + Key Generation */
{ "3B:85:40:20:68:01:01:03:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN },
{ "3B:85:40:20:68:01:01:03:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, SC_CARD_FLAG_ONBOARD_KEY_GEN },
/* Multiflex */
/* 3K */
@ -61,7 +58,7 @@ static struct sc_atr_table flex_atrs[] = {
/* 8K */
{ "3B:32:15:00:06:80", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0 },
/* 8K + full DES option */
{ "3B:32:15:00:06:95", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, FLAG_FULL_DES },
{ "3B:32:15:00:06:95", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0 },
/* 8K */
{ "3B:19:14:59:01:01:0F:01:00:05:08:B0", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0 },
/* 8K */
@ -166,7 +163,7 @@ static int flex_init(struct sc_card *card)
flags = SC_ALGORITHM_RSA_RAW;
flags |= SC_ALGORITHM_RSA_HASH_NONE;
if (card->flags & FLAG_KEYGEN)
if (card->flags & SC_CARD_FLAG_ONBOARD_KEY_GEN)
flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
_sc_card_add_rsa_alg(card, 512, flags, 0);

View File

@ -395,7 +395,8 @@ int sc_connect_card(struct sc_reader *reader, int slot_id,
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
driver = ctx->card_drivers[i];
if (driver->atr_map == NULL) {
if (driver->atr_map == NULL ||
!strcmp(driver->short_name, "default")) {
driver = NULL;
continue;
}
@ -929,21 +930,21 @@ struct sc_algorithm_info * _sc_card_find_rsa_alg(struct sc_card *card,
return NULL;
}
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_out)
static int match_atr_table(struct sc_context *ctx, struct sc_atr_table *table, u8 *atr, size_t atr_len)
{
struct sc_context *ctx = card->ctx;
char card_atr[3 * SC_MAX_ATR_SIZE];
size_t card_atr_len;
u8 *card_atr_bin = atr;
size_t card_atr_bin_len = atr_len;
char card_atr_hex[3 * SC_MAX_ATR_SIZE];
size_t card_atr_hex_len;
unsigned int i = 0;
if (table == NULL || card == NULL)
if (ctx == NULL || table == NULL || atr == NULL)
return -1;
sc_bin_to_hex(card->atr, card->atr_len, card_atr, sizeof(card_atr), ':');
card_atr_len = strlen(card_atr);
sc_bin_to_hex(card_atr_bin, card_atr_bin_len, card_atr_hex, sizeof(card_atr_hex), ':');
card_atr_hex_len = strlen(card_atr_hex);
if (ctx->debug >= 4)
sc_debug(ctx, "ATR : %s\n", card_atr);
sc_debug(ctx, "ATR : %s\n", card_atr_hex);
for (i = 0; table[i].atr != NULL; i++) {
const char *tatr = table[i].atr;
@ -953,7 +954,7 @@ int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_ou
if (ctx->debug >= 4)
sc_debug(ctx, "ATR try : %s\n", tatr);
if (tatr_len != card_atr_len)
if (tatr_len != card_atr_hex_len)
continue;
if (matr != NULL) {
u8 mbin[SC_MAX_ATR_SIZE], tbin[SC_MAX_ATR_SIZE];
@ -967,25 +968,67 @@ int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_ou
continue;
mbin_len = sizeof(mbin);
sc_hex_to_bin(matr, mbin, &mbin_len);
if (mbin_len != card->atr_len)
if (mbin_len != card_atr_bin_len)
continue;
for (s = 0; s < mbin_len; s++)
mbin[s] = (card->atr[s] & mbin[s]);
mbin[s] = (card_atr_bin[s] & mbin[s]);
tbin_len = sizeof(tbin);
sc_hex_to_bin(tatr, tbin, &tbin_len);
if (memcmp(tbin, mbin, tbin_len) != 0)
continue;
} else {
if (strncasecmp(tatr, card_atr, tatr_len) != 0)
if (strncasecmp(tatr, card_atr_hex, tatr_len) != 0)
continue;
}
if (type_out != NULL)
*type_out = table[i].type;
return i;
}
return -1;
}
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_out)
{
int res;
if (card == NULL)
return -1;
res = match_atr_table(card->ctx, table, card->atr, card->atr_len);
if (res < 0)
return res;
if (type_out != NULL)
*type_out = table[res].type;
return res;
}
scconf_block *_sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *driver, u8 *atr, size_t atr_len)
{
struct sc_card_driver *drv;
struct sc_atr_table *table;
int res;
if (ctx == NULL)
return NULL;
if (driver) {
drv = driver;
table = drv->atr_map;
res = match_atr_table(ctx, table, atr, atr_len);
if (res < 0)
return NULL;
return table[res].card_atr;
} else {
unsigned int i;
for (i = 0; ctx->card_drivers[i] != NULL; i++) {
drv = ctx->card_drivers[i];
table = drv->atr_map;
res = match_atr_table(ctx, table, atr, atr_len);
if (res < 0)
continue;
return table[res].card_atr;
}
}
return NULL;
}
int _sc_add_atr(struct sc_context *ctx, struct sc_card_driver *driver, struct sc_atr_table *src)
{
struct sc_atr_table *map, *dst;
@ -1016,6 +1059,7 @@ int _sc_add_atr(struct sc_context *ctx, struct sc_card_driver *driver, struct sc
}
dst->type = src->type;
dst->flags = src->flags;
dst->card_atr = src->card_atr;
return SC_SUCCESS;
}
@ -1032,6 +1076,7 @@ int _sc_free_atr(struct sc_context *ctx, struct sc_card_driver *driver)
free(src->atrmask);
if (src->name)
free(src->name);
src->card_atr = NULL;
src = NULL;
}
if (driver->atr_map)
@ -1041,3 +1086,31 @@ int _sc_free_atr(struct sc_context *ctx, struct sc_card_driver *driver)
return SC_SUCCESS;
}
int _sc_check_forced_protocol(struct sc_context *ctx, u8 *atr, size_t atr_len, unsigned int *protocol)
{
scconf_block *atrblock = NULL;
int ok = 0;
if (!protocol)
return 0;
atrblock = _sc_match_atr_block(ctx, NULL, atr, atr_len);
if (atrblock != NULL) {
const char *forcestr;
forcestr = scconf_get_str(atrblock, "force_protocol", "unknown");
if (!strcmp(forcestr, "t0")) {
*protocol = SC_PROTO_T0;
ok = 1;
} else if (!strcmp(forcestr, "t1")) {
*protocol = SC_PROTO_T1;
ok = 1;
} else if (!strcmp(forcestr, "raw")) {
*protocol = SC_PROTO_RAW;
ok = 1;
}
if (ok)
sc_debug(ctx, "force_protocol: %s\n", forcestr);
}
return ok;
}

View File

@ -414,7 +414,6 @@ static int load_card_driver_options(struct sc_context *ctx,
struct sc_card_driver *driver)
{
scconf_block **blocks, *blk;
const scconf_list *list;
int i;
for (i = 0; ctx->conf_blocks[i]; i++) {
@ -427,15 +426,7 @@ static int load_card_driver_options(struct sc_context *ctx,
if (blk == NULL)
continue;
list = scconf_find_list(blk, "atr");
while (list != NULL) {
struct sc_atr_table t;
memset(&t, 0, sizeof(struct sc_atr_table));
t.atr = list->data;
_sc_add_atr(ctx, driver, &t);
list = list->next;
}
/* no options at the moment */
}
return SC_SUCCESS;
}
@ -481,6 +472,84 @@ static int load_card_drivers(struct sc_context *ctx,
return SC_SUCCESS;
}
static int load_card_atrs(struct sc_context *ctx,
struct _sc_ctx_options *opts)
{
struct sc_card_driver *driver;
scconf_block **blocks;
int i, j, k;
for (i = 0; ctx->conf_blocks[i] != NULL; i++) {
blocks = scconf_find_blocks(ctx->conf, ctx->conf_blocks[i], "card_atr", NULL);
if (!blocks)
continue;
for (j = 0; blocks[j] != NULL; j++) {
scconf_block *b = blocks[j];
char *atr = b->name->data;
const scconf_list *list;
struct sc_atr_table t;
const char *dname;
driver = NULL;
if (strlen(atr) < 4)
continue;
/* The interesting part. If there's no card
* driver assigned for the ATR, add it to
* the default driver. This will reduce the
* amount of code required to process things
* related to card_atr blocks in situations,
* where the code is not exactly related to
* card driver settings, but for example
* forcing a protocol at the reader driver.
*/
dname = scconf_get_str(b, "driver", "default");
/* Find the card driver structure according to dname */
for (k = 0; ctx->card_drivers[k] != NULL; k++) {
driver = ctx->card_drivers[k];
if (!strcmp(dname, driver->short_name))
break;
driver = NULL;
}
if (!driver)
continue;
memset(&t, 0, sizeof(struct sc_atr_table));
t.atr = atr;
t.atrmask = (char *) scconf_get_str(b, "atrmask", NULL);
t.name = (char *) scconf_get_str(b, "name", NULL);
t.type = scconf_get_int(b, "type", -1);
list = scconf_find_list(b, "flags");
while (list != NULL) {
unsigned int flags;
if (!list->data) {
list = list->next;
continue;
}
flags = 0;
if (!strcmp(list->data, "keygen")) {
flags = SC_CARD_FLAG_ONBOARD_KEY_GEN;
} else if (!strcmp(list->data, "rng")) {
flags = SC_CARD_FLAG_RNG;
} else {
if (sscanf(list->data, "%x", &flags) != 1)
flags = 0;
}
t.flags |= flags;
list = list->next;
}
t.card_atr = b;
_sc_add_atr(ctx, driver, &t);
}
free(blocks);
}
return SC_SUCCESS;
}
static void process_config_file(struct sc_context *ctx, struct _sc_ctx_options *opts)
{
int i, r, count = 0;
@ -558,6 +627,7 @@ int sc_establish_context(struct sc_context **ctx_out, const char *app_name)
sc_debug(ctx, "opensc version: %s\n", sc_get_version());
load_reader_drivers(ctx, &opts);
load_card_drivers(ctx, &opts);
load_card_atrs(ctx, &opts);
if (opts.forced_card_driver) {
sc_set_card_driver(ctx, opts.forced_card_driver);
free(opts.forced_card_driver);

View File

@ -50,6 +50,9 @@ struct sc_atr_table {
char *name;
int type;
unsigned long flags;
/* Reference to card_atr configuration block,
* available to user configured card entries. */
scconf_block *card_atr;
};
/* Internal use only */
@ -58,16 +61,23 @@ size_t _sc_count_bit_string_size(const void * buf, size_t bufsize);
int _sc_add_reader(struct sc_context *ctx, struct sc_reader *reader);
int _sc_parse_atr(struct sc_context *ctx, struct sc_slot_info *slot);
struct sc_slot_info * _sc_get_slot_info(struct sc_reader *reader, int slot_id);
struct sc_slot_info *_sc_get_slot_info(struct sc_reader *reader, int slot_id);
/* Add an ATR to the card driver's struct sc_atr_table */
int _sc_add_atr(struct sc_context *ctx, struct sc_card_driver *driver, struct sc_atr_table *src);
int _sc_free_atr(struct sc_context *ctx, struct sc_card_driver *driver);
/* Returns an scconf_block entry with matching ATR/ATRmask to the ATR specified,
* NULL otherwise. Additionally, if card driver is not specified, search through
* all card drivers user configured ATRs. */
scconf_block *_sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *driver, u8 *atr, size_t atr_len);
/* Returns an index number if a match was found, -1 otherwise. table has to
* be null terminated. */
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_out);
int _sc_check_forced_protocol(struct sc_context *ctx, u8 *atr, size_t atr_len, unsigned int *protocol);
int _sc_card_add_algorithm(struct sc_card *card, const struct sc_algorithm_info *info);
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
unsigned long flags, unsigned long exponent);

View File

@ -421,8 +421,20 @@ void sc_mutex_free(struct sc_mutex *p);
/*
* Card flags
*
* Used to hint about card specific capabilities and algorithms
* supported to the card driver. Used in sc_atr_table and
* card_atr block structures in the configuration file.
*
* Unknown, card vendor specific values may exists, but must
* not conflict with values defined here. All actions defined
* by the flags must be handled by the card driver themselves.
*/
/* none yet */
/* Hint SC_ALGORITHM_ONBOARD_KEY_GEN */
#define SC_CARD_FLAG_ONBOARD_KEY_GEN 0x00000001
/* Hint SC_CARD_CAP_RNG */
#define SC_CARD_FLAG_RNG 0x00000002
/*
* Card capabilities

View File

@ -144,39 +144,6 @@ out: if (r == SC_SUCCESS) {
return r;
}
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;
@ -186,11 +153,19 @@ static int parse_emu_block(sc_pkcs15_card_t *p15card, scconf_block *conf)
int (*init_func)(sc_pkcs15_card_t *);
int (*init_func_ex)(sc_pkcs15_card_t *, sc_pkcs15emu_opt_t *);
int r;
const char *driver, *module_name;
scconf_block *atrblock = NULL;
const char *driver, *matchstr, *module_name;
driver = conf->name->data;
r = emu_detect_card(card, conf);
if (!r)
/* XXX: Pass card->driver? Requires that the pkcs15emu
* parameter is assigned to actual card driver used. */
atrblock = _sc_match_atr_block(ctx, NULL, card->atr, card->atr_len);
if (!atrblock)
return SC_ERROR_WRONG_CARD;
matchstr = scconf_get_str(atrblock, "pkcs15emu", NULL);
if (!matchstr)
return SC_ERROR_WRONG_CARD;
if (strcmp(driver, matchstr))
return SC_ERROR_WRONG_CARD;
init_func = NULL;

View File

@ -374,13 +374,12 @@ static int pcsc_wait_for_event(struct sc_reader **readers,
PCSC_ERROR(ctx, "SCardGetStatusChange(2) failed", ret);
return pcsc_ret_to_error(ret);
}
}
}
static int pcsc_connect(struct sc_reader *reader, struct sc_slot_info *slot)
{
DWORD active_proto, protocol = SCARD_PROTOCOL_ANY;
DWORD active_proto, protocol;
SCARDHANDLE card_handle;
LONG rv;
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
@ -394,36 +393,10 @@ static int pcsc_connect(struct sc_reader *reader, struct sc_slot_info *slot)
if (!(slot->flags & SC_SLOT_CARD_PRESENT))
return SC_ERROR_CARD_NOT_PRESENT;
/* force a protocol */
/* XXX: Why it's at reader driver level, and not shared by others? */
for (i = 0; reader->ctx->conf_blocks[i] != NULL; i++) {
char name[3 * SC_MAX_ATR_SIZE];
r = sc_bin_to_hex(slot->atr, slot->atr_len, name, sizeof(name), ':');
assert(r == 0);
blocks = scconf_find_blocks(reader->ctx->conf, reader->ctx->conf_blocks[i],
"card_atr", name);
conf_block = blocks[0];
free(blocks);
if (conf_block != NULL)
break;
}
if (conf_block != NULL) {
const char *forcestr;
sc_debug(reader->ctx, "Found card_atr with current atr");
forcestr = scconf_get_str(conf_block, "force_protocol", NULL);
if (forcestr) {
if (!strcmp(forcestr, "t0"))
protocol = SCARD_PROTOCOL_T0;
else if (!strcmp(forcestr, "t1"))
protocol = SCARD_PROTOCOL_T1;
else if (!strcmp(forcestr, "raw"))
protocol = SCARD_PROTOCOL_RAW;
else
sc_error(reader->ctx, "Unknown force_protocol: %s (Ignored)", forcestr);
}
if (_sc_check_forced_protocol(reader->ctx, slot->atr, slot->atr_len, (unsigned int *) &protocol)) {
protocol = opensc_proto_to_pcsc(protocol);
} else {
protocol = SCARD_PROTOCOL_ANY;
}
for (i = 0; reader->ctx->conf_blocks[i] != NULL; i++) {