- add some support for card removal in pkcs11

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@867 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-01-19 17:47:07 +00:00
parent a7551e1822
commit 5b1eb43b93
11 changed files with 106 additions and 58 deletions

1
TODO
View File

@ -18,5 +18,6 @@ Nitty gritty details:
* pkcs15-init: when using an unblock PIN, write an AODF entry for it
(alternatively: set unblockDisabled flag for those PINs that have no PUK?)
* pkcs15: fix sc_pkcs15_change_reference_data; add unblock function
* pkcs11: make sure all PIN ops work through pkcs11

View File

@ -252,6 +252,7 @@ struct sc_reader_driver {
/* slot flags */
#define SC_SLOT_CARD_PRESENT 0x00000001
#define SC_SLOT_CARD_CHANGED 0x00000002
/* slot capabilities */
#define SC_SLOT_CAP_DISPLAY 0x00000001
#define SC_SLOT_CAP_PIN_PAD 0x00000002
@ -629,10 +630,13 @@ inline int sc_card_valid(const struct sc_card *card);
/**
* Checks if a card is present in a reader
* @param reader Reader structure
* @param reader Slot ID
* @retval 1 if a card is present
* @retval 0 card absent
* @retval < 0 if an error occured
* @param slot_id Slot ID
* @retval If an error occured, the return value is a (negative)
* OpenSC error code. If no card is present, 0 is returned.
* Otherwise, a positive value is returned, which is a
* combination of flags. The flag SC_SLOT_CARD_PRESENT is
* always set. In addition, if the card was exchanged,
* the SC_SLOT_CARD_CHANGED flag is set.
*/
int sc_detect_card_presence(struct sc_reader *reader, int slot_id);

View File

@ -120,9 +120,7 @@ static int ctapi_detect_card_presence(struct sc_reader *reader, struct sc_slot_i
r = refresh_slot_attributes(reader, slot);
if (r)
return r;
if (slot->flags & SC_SLOT_CARD_PRESENT)
return 1;
return 0;
return slot->flags;
}
static int ctapi_connect(struct sc_reader *reader, struct sc_slot_info *slot)

View File

@ -76,6 +76,7 @@ struct pcsc_private_data {
struct pcsc_slot_data {
SCARDHANDLE pcsc_card;
SCARD_READERSTATE_A readerState;
};
static int pcsc_ret_to_error(long rv)
@ -203,25 +204,40 @@ static int pcsc_transmit(struct sc_reader *reader, struct sc_slot_info *slot,
static int refresh_slot_attributes(struct sc_reader *reader, struct sc_slot_info *slot)
{
struct pcsc_private_data *priv = GET_PRIV_DATA(reader);
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
LONG ret;
SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS];
rgReaderStates[0].szReader = priv->reader_name;
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
rgReaderStates[0].dwEventState = SCARD_STATE_UNAWARE;
ret = SCardGetStatusChange(priv->pcsc_ctx, SC_STATUS_TIMEOUT, rgReaderStates, 1);
if (pslot->readerState.szReader == NULL) {
pslot->readerState.szReader = priv->reader_name;
pslot->readerState.dwCurrentState = SCARD_STATE_UNAWARE;
pslot->readerState.dwEventState = SCARD_STATE_UNAWARE;
} else {
pslot->readerState.dwCurrentState = pslot->readerState.dwEventState;
}
ret = SCardGetStatusChange(priv->pcsc_ctx, SC_STATUS_TIMEOUT, &pslot->readerState, 1);
if (ret != 0) {
PCSC_ERROR(reader->ctx, "SCardGetStatusChange failed", ret);
return pcsc_ret_to_error(ret);
}
if (rgReaderStates[0].dwEventState & SCARD_STATE_PRESENT) {
if (pslot->readerState.dwEventState & SCARD_STATE_PRESENT) {
int old_flags = slot->flags;
slot->flags |= SC_SLOT_CARD_PRESENT;
slot->atr_len = rgReaderStates[0].cbAtr;
slot->atr_len = pslot->readerState.cbAtr;
if (slot->atr_len > SC_MAX_ATR_SIZE)
slot->atr_len = SC_MAX_ATR_SIZE;
memcpy(slot->atr, rgReaderStates[0].rgbAtr, slot->atr_len);
memcpy(slot->atr, pslot->readerState.rgbAtr, slot->atr_len);
/* If there was a card in the slot previously, and the
* PCSC driver reports a state change, we assume the
* user removed the old card and inserted a new one in the
* meantime. */
if ((pslot->readerState.dwEventState & SCARD_STATE_CHANGED)
&& (old_flags & SC_SLOT_CARD_PRESENT))
slot->flags |= SC_SLOT_CARD_CHANGED;
} else {
slot->flags &= ~SC_SLOT_CARD_PRESENT;
slot->flags &= ~(SC_SLOT_CARD_PRESENT|SC_SLOT_CARD_CHANGED);
}
return 0;
@ -233,7 +249,7 @@ static int pcsc_detect_card_presence(struct sc_reader *reader, struct sc_slot_in
if ((rv = refresh_slot_attributes(reader, slot)) < 0)
return rv;
return (slot->flags & SC_SLOT_CARD_PRESENT)? 1 : 0;
return slot->flags;
}
/* Wait for an event to occur.
@ -355,16 +371,11 @@ static int pcsc_connect(struct sc_reader *reader, struct sc_slot_info *slot)
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
int r;
if (pslot != NULL)
return SC_ERROR_SLOT_ALREADY_CONNECTED;
r = refresh_slot_attributes(reader, slot);
if (r)
return r;
if (!(slot->flags & SC_SLOT_CARD_PRESENT))
return SC_ERROR_CARD_NOT_PRESENT;
pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data));
if (pslot == NULL)
return SC_ERROR_OUT_OF_MEMORY;
rv = SCardConnect(priv->pcsc_ctx, priv->reader_name,
SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY,
&card_handle, &active_proto);
@ -374,7 +385,6 @@ static int pcsc_connect(struct sc_reader *reader, struct sc_slot_info *slot)
return pcsc_ret_to_error(rv);
}
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
slot->drv_data = pslot;
pslot->pcsc_card = card_handle;
return 0;
@ -387,8 +397,8 @@ static int pcsc_disconnect(struct sc_reader *reader, struct sc_slot_info *slot,
/* FIXME: check action */
SCardDisconnect(pslot->pcsc_card, SCARD_LEAVE_CARD);
free(pslot);
slot->drv_data = NULL;
memset(pslot, 0, sizeof(*pslot));
slot->flags = 0;
return 0;
}
@ -476,15 +486,17 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
do {
struct sc_reader *reader = (struct sc_reader *) malloc(sizeof(struct sc_reader));
struct pcsc_private_data *priv = (struct pcsc_private_data *) malloc(sizeof(struct pcsc_private_data));
struct pcsc_slot_data *pslot = (struct pcsc_slot_data *) malloc(sizeof(struct pcsc_slot_data));
struct sc_slot_info *slot;
if (reader == NULL || priv == NULL) {
if (reader == NULL || priv == NULL || pslot == NULL) {
if (reader)
free(reader);
if (priv)
free(priv);
break;
}
memset(reader, 0, sizeof(*reader));
reader->drv_data = priv;
reader->ops = &pcsc_ops;
@ -503,11 +515,10 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
break;
}
slot = &reader->slot[0];
slot->id = 0;
memset(slot, 0, sizeof(*slot));
slot->drv_data = pslot;
memset(pslot, 0, sizeof(*pslot));
refresh_slot_attributes(reader, slot);
slot->capabilities = 0;
slot->atr_len = 0;
slot->drv_data = NULL;
while (*p++ != 0);
} while (p < (reader_buf + reader_buf_size - 1));

View File

@ -8,7 +8,8 @@ SUBDIRS = . rsaref
INCLUDES = @CFLAGS_OPENSC@ -I../pkcs15init
LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ ../pkcs15init/libpkcs15init.la
LDFLAGS = @LDFLAGS@ @LIBDL@ @LIBOPENSC@ ../pkcs15init/libpkcs15init.la \
../scrandom/libscrandom.la
SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
mechanism.c openssl.c \

View File

@ -52,21 +52,39 @@ CK_RV card_initialize(int reader)
CK_RV card_detect(int reader)
{
struct sc_pkcs11_card *card;
int rc, rv, i;
int rc, rv, i, retry = 1;
rv = CKR_OK;
debug(context, "%d: Detecting SmartCard\n", reader);
/* Already known to be present? */
if (card_table[reader].card == NULL) {
/* Check if someone inserted a card */
if (sc_detect_card_presence(context->reader[reader], 0) != 1) {
debug(context, "%d: Card absent\n", reader);
return CKR_TOKEN_NOT_PRESENT;
}
/* Check if someone inserted a card */
again: rc = sc_detect_card_presence(context->reader[reader], 0);
if (rc < 0) {
debug(context, "Card detection failed for reader %d: %s\n",
reader, sc_strerror(rc));
return sc_to_cryptoki_error(rc, reader);
}
if (rc == 0) {
debug(context, "%d: Card absent\n", reader);
card_removed(reader); /* Release all resources */
return CKR_TOKEN_NOT_PRESENT;
}
/* Detect the card */
/* If the card was changed, disconnect the current one */
if (rc & SC_SLOT_CARD_CHANGED) {
debug(context, "%d: Card changed\n", reader);
/* The following should never happen - but if it
* does we'll be stuck in an endless loop.
* So better be fussy. */
if (!retry--)
return CKR_TOKEN_NOT_PRESENT;
card_removed(reader);
goto again;
}
/* Detect the card if it's not known already */
if (card_table[reader].card == NULL) {
debug(context, "%d: Connecting to SmartCard\n", reader);
rc = sc_connect_card(context->reader[reader], 0, &card_table[reader].card);
if (rc != SC_SUCCESS)

View File

@ -96,7 +96,7 @@ const char *scam_get_atr(unsigned int readernum)
sc_release_context(ctx);
return NULL;
}
if (sc_detect_card_presence(ctx->reader[readernum], 0) != 1) {
if (sc_detect_card_presence(ctx->reader[readernum], 0) <= 0) {
sc_release_context(ctx);
return NULL;
}

View File

@ -94,7 +94,7 @@ int sc_test_init(int *argc, char *argv[])
opt_reader = i - 1;
}
if (rc == 1) {
if (rc > 0) {
printf("Card detected in reader '%s'\n",
ctx->reader[opt_reader]->name);
break;

View File

@ -1156,7 +1156,7 @@ int main(int argc, char * const argv[])
err = 1;
goto end;
}
if (sc_detect_card_presence(ctx->reader[opt_reader], 0) != 1) {
if (sc_detect_card_presence(ctx->reader[opt_reader], 0) <= 0) {
fprintf(stderr, "Card not present.\n");
err = 3;
goto end;

View File

@ -892,11 +892,7 @@ test_digest(CK_SLOT_ID slot)
data[10 * i + j] = (unsigned char) (0x30 + j);
i = 0xffffff;
while (1) {
if (mechTypes[++i] == 0xffffff)
break;
for (i = 0; mechTypes[i] != 0xffffff; i++) {
ck_mech.mechanism = mechTypes[i];
rv = p11->C_DigestInit(session, &ck_mech);
@ -1298,23 +1294,42 @@ test_random(CK_SESSION_HANDLE session)
return 0;
}
static int
test_card_detection(void)
{
char buffer[256];
while (1) {
printf("Please press return or x to exit: ");
fflush(stdout);
if (fgets(buffer, sizeof(buffer), stdin) == NULL
|| buffer[0] == 'x')
break;
list_slots();
}
return 0;
}
static int
p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
int errors = 0;
int errors = 0;
errors += test_random(session);
errors += test_random(session);
errors += test_digest(slot);
errors += test_digest(slot);
errors += test_signature(slot, session);
errors += test_signature(slot, session);
if (errors == 0)
printf("No errors\n");
else
printf("%d errors\n", errors);
errors += test_card_detection();
return errors;
if (errors == 0)
printf("No errors\n");
else
printf("%d errors\n", errors);
return errors;
}
const char *

View File

@ -60,7 +60,7 @@ int connect_card(struct sc_context *ctx, struct sc_card **cardp,
reader = ctx->reader[reader_id];
slot_id = 0;
if (sc_detect_card_presence(reader, 0) != 1) {
if (sc_detect_card_presence(reader, 0) <= 0) {
fprintf(stderr, "Card not present.\n");
return 3;
}