- 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:
parent
a7551e1822
commit
5b1eb43b93
1
TODO
1
TODO
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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) {
|
||||
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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,6 +1294,23 @@ 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)
|
||||
{
|
||||
|
@ -1309,6 +1322,8 @@ p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
|
|||
|
||||
errors += test_signature(slot, session);
|
||||
|
||||
errors += test_card_detection();
|
||||
|
||||
if (errors == 0)
|
||||
printf("No errors\n");
|
||||
else
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue