PC/SC: move protocol (T=0/T=1) selection to reader-pcsc.c, where it is used.
Also, check fot the required protocol before connecting to the card and use the forced prtocol instead of re-connecting. See http://lists.drizzle.com/pipermail/muscle/2010-November/008671.html git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@4873 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
5e909df85d
commit
c6eb9d3d92
|
@ -697,7 +697,7 @@ int _sc_card_add_algorithm(sc_card_t *card, const sc_algorithm_info_t *info)
|
||||||
p += card->algorithm_count;
|
p += card->algorithm_count;
|
||||||
card->algorithm_count++;
|
card->algorithm_count++;
|
||||||
*p = *info;
|
*p = *info;
|
||||||
return 0;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
|
int _sc_card_add_rsa_alg(sc_card_t *card, unsigned int key_length,
|
||||||
|
@ -896,33 +896,6 @@ int _sc_free_atr(sc_context_t *ctx, struct sc_card_driver *driver)
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int _sc_check_forced_protocol(sc_context_t *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, SC_LOG_DEBUG_NORMAL, "force_protocol: %s\n", forcestr);
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char *name2, int priority)
|
scconf_block *sc_get_conf_block(sc_context_t *ctx, const char *name1, const char *name2, int priority)
|
||||||
{
|
{
|
||||||
|
|
|
@ -107,8 +107,6 @@ scconf_block *_sc_match_atr_block(sc_context_t *ctx, struct sc_card_driver *driv
|
||||||
* be null terminated. */
|
* be null terminated. */
|
||||||
int _sc_match_atr(struct sc_card *card, struct sc_atr_table *table, int *type_out);
|
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_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,
|
int _sc_card_add_rsa_alg(struct sc_card *card, unsigned int key_length,
|
||||||
unsigned long flags, unsigned long exponent);
|
unsigned long flags, unsigned long exponent);
|
||||||
|
|
|
@ -37,10 +37,6 @@
|
||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
#include "internal-winscard.h"
|
#include "internal-winscard.h"
|
||||||
|
|
||||||
/* Some windows specific kludge */
|
|
||||||
#undef SCARD_PROTOCOL_ANY
|
|
||||||
#define SCARD_PROTOCOL_ANY (SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
|
|
||||||
|
|
||||||
/* Logging */
|
/* Logging */
|
||||||
#define PCSC_TRACE(reader, desc, rv) do { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s:" desc ": 0x%08lx\n", reader->name, rv); } while (0)
|
#define PCSC_TRACE(reader, desc, rv) do { sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "%s:" desc ": 0x%08lx\n", reader->name, rv); } while (0)
|
||||||
#define PCSC_LOG(ctx, desc, rv) do { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, desc ": 0x%08lx\n", rv); } while (0)
|
#define PCSC_LOG(ctx, desc, rv) do { sc_debug(ctx, SC_LOG_DEBUG_NORMAL, desc ": 0x%08lx\n", rv); } while (0)
|
||||||
|
@ -316,7 +312,6 @@ static int refresh_attributes(sc_reader_t *reader)
|
||||||
reader->flags |= SC_READER_CARD_CHANGED;
|
reader->flags |= SC_READER_CARD_CHANGED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (old_flags & SC_READER_CARD_PRESENT) {
|
if (old_flags & SC_READER_CARD_PRESENT) {
|
||||||
/* Requires pcsc-lite 1.6.5+ to function properly */
|
/* Requires pcsc-lite 1.6.5+ to function properly */
|
||||||
if ((state & 0xFFFF0000) != (prev_state & 0xFFFF0000)) {
|
if ((state & 0xFFFF0000) != (prev_state & 0xFFFF0000)) {
|
||||||
|
@ -357,10 +352,36 @@ static int pcsc_detect_card_presence(sc_reader_t *reader)
|
||||||
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, reader->flags);
|
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, reader->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int check_forced_protocol(sc_context_t *ctx, u8 *atr, size_t atr_len, DWORD *protocol)
|
||||||
|
{
|
||||||
|
scconf_block *atrblock = NULL;
|
||||||
|
int ok = 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 = SCARD_PROTOCOL_T0;
|
||||||
|
ok = 1;
|
||||||
|
} else if (!strcmp(forcestr, "t1")) {
|
||||||
|
*protocol = SCARD_PROTOCOL_T1;
|
||||||
|
ok = 1;
|
||||||
|
} else if (!strcmp(forcestr, "raw")) {
|
||||||
|
*protocol = SCARD_PROTOCOL_RAW;
|
||||||
|
ok = 1;
|
||||||
|
}
|
||||||
|
if (ok)
|
||||||
|
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "force_protocol: %s\n", forcestr);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
||||||
{
|
{
|
||||||
DWORD active_proto, protocol;
|
DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
||||||
LONG rv;
|
LONG rv;
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
int r;
|
int r;
|
||||||
|
@ -374,24 +395,16 @@ static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
||||||
if (!(reader->flags & SC_READER_CARD_PRESENT))
|
if (!(reader->flags & SC_READER_CARD_PRESENT))
|
||||||
return SC_ERROR_CARD_NOT_PRESENT;
|
return SC_ERROR_CARD_NOT_PRESENT;
|
||||||
|
|
||||||
|
/* Check if we need a specific protocol. refresh_attributes above already sets the ATR */
|
||||||
|
if (check_forced_protocol(reader->ctx, reader->atr, reader->atr_len, &tmp))
|
||||||
|
protocol = tmp;
|
||||||
|
|
||||||
/* reconnect always unlocks transaction */
|
/* reconnect always unlocks transaction */
|
||||||
priv->locked = 0;
|
priv->locked = 0;
|
||||||
|
|
||||||
rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
|
rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
||||||
SCARD_PROTOCOL_ANY, reset ? SCARD_UNPOWER_CARD : SCARD_LEAVE_CARD, &active_proto);
|
protocol, reset ? SCARD_UNPOWER_CARD : SCARD_LEAVE_CARD, &active_proto);
|
||||||
|
|
||||||
/* Check for protocol difference */
|
|
||||||
if (rv == SCARD_S_SUCCESS && _sc_check_forced_protocol
|
|
||||||
(reader->ctx, reader->atr, reader->atr_len,
|
|
||||||
(unsigned int *)&protocol)) {
|
|
||||||
protocol = opensc_proto_to_pcsc(protocol);
|
|
||||||
if (pcsc_proto_to_opensc(active_proto) != protocol) {
|
|
||||||
rv = priv->gpriv->SCardReconnect(priv->pcsc_card,
|
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
|
||||||
protocol, SCARD_UNPOWER_CARD, &active_proto);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
PCSC_TRACE(reader, "SCardReconnect failed", rv);
|
PCSC_TRACE(reader, "SCardReconnect failed", rv);
|
||||||
|
@ -404,7 +417,7 @@ static int pcsc_reconnect(sc_reader_t * reader, int reset)
|
||||||
|
|
||||||
static int pcsc_connect(sc_reader_t *reader)
|
static int pcsc_connect(sc_reader_t *reader)
|
||||||
{
|
{
|
||||||
DWORD active_proto, protocol;
|
DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1;
|
||||||
SCARDHANDLE card_handle;
|
SCARDHANDLE card_handle;
|
||||||
LONG rv;
|
LONG rv;
|
||||||
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
@ -419,16 +432,19 @@ static int pcsc_connect(sc_reader_t *reader)
|
||||||
if (!(reader->flags & SC_READER_CARD_PRESENT))
|
if (!(reader->flags & SC_READER_CARD_PRESENT))
|
||||||
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_CARD_NOT_PRESENT);
|
SC_FUNC_RETURN(reader->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_CARD_NOT_PRESENT);
|
||||||
|
|
||||||
/* Always connect with whatever protocol possible */
|
/* Check if we need a specific protocol. refresh_attributes above already sets the ATR */
|
||||||
|
if (check_forced_protocol(reader->ctx, reader->atr, reader->atr_len, &tmp))
|
||||||
|
protocol = tmp;
|
||||||
|
|
||||||
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
|
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
||||||
SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
protocol, &card_handle, &active_proto);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
if (rv == (LONG)SCARD_E_SHARING_VIOLATION) {
|
if (rv == (LONG)SCARD_E_SHARING_VIOLATION) {
|
||||||
sleep(1); /* Try again to compete with Tokend probes */
|
sleep(1); /* Try again to compete with Tokend probes */
|
||||||
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
|
rv = priv->gpriv->SCardConnect(priv->gpriv->pcsc_ctx, reader->name,
|
||||||
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
priv->gpriv->connect_exclusive ? SCARD_SHARE_EXCLUSIVE : SCARD_SHARE_SHARED,
|
||||||
SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
protocol, &card_handle, &active_proto);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (rv != SCARD_S_SUCCESS) {
|
if (rv != SCARD_S_SUCCESS) {
|
||||||
|
@ -442,20 +458,6 @@ static int pcsc_connect(sc_reader_t *reader)
|
||||||
priv->locked = 0;
|
priv->locked = 0;
|
||||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "After connect protocol = %d", reader->active_protocol);
|
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "After connect protocol = %d", reader->active_protocol);
|
||||||
|
|
||||||
/* If we need a specific protocol, reconnect if needed */
|
|
||||||
if (_sc_check_forced_protocol(reader->ctx, reader->atr, reader->atr_len, (unsigned int *) &protocol)) {
|
|
||||||
/* If current protocol differs from the protocol we want to force */
|
|
||||||
if (reader->active_protocol != protocol) {
|
|
||||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Protocol difference, forcing protocol (%d)", protocol);
|
|
||||||
/* Reconnect with a reset. pcsc_reconnect figures out the right forced protocol */
|
|
||||||
r = pcsc_reconnect(reader, 1);
|
|
||||||
if (r != SC_SUCCESS) {
|
|
||||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "pcsc_reconnect (to force protocol) failed", r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "Proto after reconnect = %d", reader->active_protocol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return SC_SUCCESS;
|
return SC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -935,13 +937,13 @@ static int pcsc_detect_readers(sc_context_t *ctx)
|
||||||
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Requesting reader features ... ");
|
sc_debug(ctx, SC_LOG_DEBUG_NORMAL, "Requesting reader features ... ");
|
||||||
|
|
||||||
#ifndef _WIN32 /* Apple 10.5.7 and pcsc-lite previous to v1.5.5 do not support 0 as protocol identifier */
|
#ifndef _WIN32 /* Apple 10.5.7 and pcsc-lite previous to v1.5.5 do not support 0 as protocol identifier */
|
||||||
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle, &active_proto);
|
||||||
#else
|
#else
|
||||||
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, 0, &card_handle, &active_proto);
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_DIRECT, 0, &card_handle, &active_proto);
|
||||||
#endif
|
#endif
|
||||||
PCSC_TRACE(reader, "SCardConnect(DIRECT)", rv);
|
PCSC_TRACE(reader, "SCardConnect(DIRECT)", rv);
|
||||||
if (rv == (LONG)SCARD_E_SHARING_VIOLATION) { /* Assume that there is a card in the reader in shared mode if direct communcation failed */
|
if (rv == (LONG)SCARD_E_SHARING_VIOLATION) { /* Assume that there is a card in the reader in shared mode if direct communcation failed */
|
||||||
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY, &card_handle, &active_proto);
|
rv = gpriv->SCardConnect(gpriv->pcsc_ctx, reader->name, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0|SCARD_PROTOCOL_T1, &card_handle, &active_proto);
|
||||||
PCSC_TRACE(reader, "SCardConnect(SHARED)", rv);
|
PCSC_TRACE(reader, "SCardConnect(SHARED)", rv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue