- 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:
parent
b80890d49c
commit
8a8f2cd6bc
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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++) {
|
||||
|
|
Loading…
Reference in New Issue