- 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
|
* pkcs15-init: when using an unblock PIN, write an AODF entry for it
|
||||||
(alternatively: set unblockDisabled flag for those PINs that have no PUK?)
|
(alternatively: set unblockDisabled flag for those PINs that have no PUK?)
|
||||||
* pkcs15: fix sc_pkcs15_change_reference_data; add unblock function
|
* 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 */
|
/* slot flags */
|
||||||
#define SC_SLOT_CARD_PRESENT 0x00000001
|
#define SC_SLOT_CARD_PRESENT 0x00000001
|
||||||
|
#define SC_SLOT_CARD_CHANGED 0x00000002
|
||||||
/* slot capabilities */
|
/* slot capabilities */
|
||||||
#define SC_SLOT_CAP_DISPLAY 0x00000001
|
#define SC_SLOT_CAP_DISPLAY 0x00000001
|
||||||
#define SC_SLOT_CAP_PIN_PAD 0x00000002
|
#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
|
* Checks if a card is present in a reader
|
||||||
* @param reader Reader structure
|
* @param reader Reader structure
|
||||||
* @param reader Slot ID
|
* @param slot_id Slot ID
|
||||||
* @retval 1 if a card is present
|
* @retval If an error occured, the return value is a (negative)
|
||||||
* @retval 0 card absent
|
* OpenSC error code. If no card is present, 0 is returned.
|
||||||
* @retval < 0 if an error occured
|
* 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);
|
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);
|
r = refresh_slot_attributes(reader, slot);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (slot->flags & SC_SLOT_CARD_PRESENT)
|
return slot->flags;
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ctapi_connect(struct sc_reader *reader, struct sc_slot_info *slot)
|
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 {
|
struct pcsc_slot_data {
|
||||||
SCARDHANDLE pcsc_card;
|
SCARDHANDLE pcsc_card;
|
||||||
|
SCARD_READERSTATE_A readerState;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int pcsc_ret_to_error(long rv)
|
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)
|
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_private_data *priv = GET_PRIV_DATA(reader);
|
||||||
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
LONG ret;
|
LONG ret;
|
||||||
SCARD_READERSTATE_A rgReaderStates[SC_MAX_READERS];
|
|
||||||
|
|
||||||
rgReaderStates[0].szReader = priv->reader_name;
|
if (pslot->readerState.szReader == NULL) {
|
||||||
rgReaderStates[0].dwCurrentState = SCARD_STATE_UNAWARE;
|
pslot->readerState.szReader = priv->reader_name;
|
||||||
rgReaderStates[0].dwEventState = SCARD_STATE_UNAWARE;
|
pslot->readerState.dwCurrentState = SCARD_STATE_UNAWARE;
|
||||||
ret = SCardGetStatusChange(priv->pcsc_ctx, SC_STATUS_TIMEOUT, rgReaderStates, 1);
|
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) {
|
if (ret != 0) {
|
||||||
PCSC_ERROR(reader->ctx, "SCardGetStatusChange failed", ret);
|
PCSC_ERROR(reader->ctx, "SCardGetStatusChange failed", ret);
|
||||||
return pcsc_ret_to_error(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->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)
|
if (slot->atr_len > SC_MAX_ATR_SIZE)
|
||||||
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 {
|
} else {
|
||||||
slot->flags &= ~SC_SLOT_CARD_PRESENT;
|
slot->flags &= ~(SC_SLOT_CARD_PRESENT|SC_SLOT_CARD_CHANGED);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
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)
|
if ((rv = refresh_slot_attributes(reader, slot)) < 0)
|
||||||
return rv;
|
return rv;
|
||||||
return (slot->flags & SC_SLOT_CARD_PRESENT)? 1 : 0;
|
return slot->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for an event to occur.
|
/* 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);
|
struct pcsc_slot_data *pslot = GET_SLOT_DATA(slot);
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if (pslot != NULL)
|
|
||||||
return SC_ERROR_SLOT_ALREADY_CONNECTED;
|
|
||||||
r = refresh_slot_attributes(reader, slot);
|
r = refresh_slot_attributes(reader, slot);
|
||||||
if (r)
|
if (r)
|
||||||
return r;
|
return r;
|
||||||
if (!(slot->flags & SC_SLOT_CARD_PRESENT))
|
if (!(slot->flags & SC_SLOT_CARD_PRESENT))
|
||||||
return SC_ERROR_CARD_NOT_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,
|
rv = SCardConnect(priv->pcsc_ctx, priv->reader_name,
|
||||||
SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY,
|
SCARD_SHARE_SHARED, SCARD_PROTOCOL_ANY,
|
||||||
&card_handle, &active_proto);
|
&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);
|
return pcsc_ret_to_error(rv);
|
||||||
}
|
}
|
||||||
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
|
slot->active_protocol = pcsc_proto_to_opensc(active_proto);
|
||||||
slot->drv_data = pslot;
|
|
||||||
pslot->pcsc_card = card_handle;
|
pslot->pcsc_card = card_handle;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -387,8 +397,8 @@ static int pcsc_disconnect(struct sc_reader *reader, struct sc_slot_info *slot,
|
||||||
|
|
||||||
/* FIXME: check action */
|
/* FIXME: check action */
|
||||||
SCardDisconnect(pslot->pcsc_card, SCARD_LEAVE_CARD);
|
SCardDisconnect(pslot->pcsc_card, SCARD_LEAVE_CARD);
|
||||||
free(pslot);
|
memset(pslot, 0, sizeof(*pslot));
|
||||||
slot->drv_data = NULL;
|
slot->flags = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,15 +486,17 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
||||||
do {
|
do {
|
||||||
struct sc_reader *reader = (struct sc_reader *) malloc(sizeof(struct sc_reader));
|
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_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;
|
struct sc_slot_info *slot;
|
||||||
|
|
||||||
if (reader == NULL || priv == NULL) {
|
if (reader == NULL || priv == NULL || pslot == NULL) {
|
||||||
if (reader)
|
if (reader)
|
||||||
free(reader);
|
free(reader);
|
||||||
if (priv)
|
if (priv)
|
||||||
free(priv);
|
free(priv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(reader, 0, sizeof(*reader));
|
memset(reader, 0, sizeof(*reader));
|
||||||
reader->drv_data = priv;
|
reader->drv_data = priv;
|
||||||
reader->ops = &pcsc_ops;
|
reader->ops = &pcsc_ops;
|
||||||
|
@ -503,11 +515,10 @@ static int pcsc_init(struct sc_context *ctx, void **reader_data)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
slot = &reader->slot[0];
|
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);
|
refresh_slot_attributes(reader, slot);
|
||||||
slot->capabilities = 0;
|
|
||||||
slot->atr_len = 0;
|
|
||||||
slot->drv_data = NULL;
|
|
||||||
|
|
||||||
while (*p++ != 0);
|
while (*p++ != 0);
|
||||||
} while (p < (reader_buf + reader_buf_size - 1));
|
} while (p < (reader_buf + reader_buf_size - 1));
|
||||||
|
|
|
@ -8,7 +8,8 @@ SUBDIRS = . rsaref
|
||||||
|
|
||||||
INCLUDES = @CFLAGS_OPENSC@ -I../pkcs15init
|
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 \
|
SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
|
||||||
mechanism.c openssl.c \
|
mechanism.c openssl.c \
|
||||||
|
|
|
@ -52,21 +52,39 @@ CK_RV card_initialize(int reader)
|
||||||
CK_RV card_detect(int reader)
|
CK_RV card_detect(int reader)
|
||||||
{
|
{
|
||||||
struct sc_pkcs11_card *card;
|
struct sc_pkcs11_card *card;
|
||||||
int rc, rv, i;
|
int rc, rv, i, retry = 1;
|
||||||
|
|
||||||
rv = CKR_OK;
|
rv = CKR_OK;
|
||||||
|
|
||||||
debug(context, "%d: Detecting SmartCard\n", reader);
|
debug(context, "%d: Detecting SmartCard\n", reader);
|
||||||
|
|
||||||
/* Already known to be present? */
|
/* Check if someone inserted a card */
|
||||||
if (card_table[reader].card == NULL) {
|
again: rc = sc_detect_card_presence(context->reader[reader], 0);
|
||||||
/* Check if someone inserted a card */
|
if (rc < 0) {
|
||||||
if (sc_detect_card_presence(context->reader[reader], 0) != 1) {
|
debug(context, "Card detection failed for reader %d: %s\n",
|
||||||
debug(context, "%d: Card absent\n", reader);
|
reader, sc_strerror(rc));
|
||||||
return CKR_TOKEN_NOT_PRESENT;
|
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);
|
debug(context, "%d: Connecting to SmartCard\n", reader);
|
||||||
rc = sc_connect_card(context->reader[reader], 0, &card_table[reader].card);
|
rc = sc_connect_card(context->reader[reader], 0, &card_table[reader].card);
|
||||||
if (rc != SC_SUCCESS)
|
if (rc != SC_SUCCESS)
|
||||||
|
|
|
@ -96,7 +96,7 @@ const char *scam_get_atr(unsigned int readernum)
|
||||||
sc_release_context(ctx);
|
sc_release_context(ctx);
|
||||||
return NULL;
|
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);
|
sc_release_context(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ int sc_test_init(int *argc, char *argv[])
|
||||||
opt_reader = i - 1;
|
opt_reader = i - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rc == 1) {
|
if (rc > 0) {
|
||||||
printf("Card detected in reader '%s'\n",
|
printf("Card detected in reader '%s'\n",
|
||||||
ctx->reader[opt_reader]->name);
|
ctx->reader[opt_reader]->name);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1156,7 +1156,7 @@ int main(int argc, char * const argv[])
|
||||||
err = 1;
|
err = 1;
|
||||||
goto end;
|
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");
|
fprintf(stderr, "Card not present.\n");
|
||||||
err = 3;
|
err = 3;
|
||||||
goto end;
|
goto end;
|
||||||
|
|
|
@ -892,11 +892,7 @@ test_digest(CK_SLOT_ID slot)
|
||||||
data[10 * i + j] = (unsigned char) (0x30 + j);
|
data[10 * i + j] = (unsigned char) (0x30 + j);
|
||||||
|
|
||||||
|
|
||||||
i = 0xffffff;
|
for (i = 0; mechTypes[i] != 0xffffff; i++) {
|
||||||
while (1) {
|
|
||||||
if (mechTypes[++i] == 0xffffff)
|
|
||||||
break;
|
|
||||||
|
|
||||||
ck_mech.mechanism = mechTypes[i];
|
ck_mech.mechanism = mechTypes[i];
|
||||||
|
|
||||||
rv = p11->C_DigestInit(session, &ck_mech);
|
rv = p11->C_DigestInit(session, &ck_mech);
|
||||||
|
@ -1298,23 +1294,42 @@ test_random(CK_SESSION_HANDLE session)
|
||||||
return 0;
|
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
|
static int
|
||||||
p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
|
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)
|
errors += test_card_detection();
|
||||||
printf("No errors\n");
|
|
||||||
else
|
|
||||||
printf("%d errors\n", errors);
|
|
||||||
|
|
||||||
return errors;
|
if (errors == 0)
|
||||||
|
printf("No errors\n");
|
||||||
|
else
|
||||||
|
printf("%d errors\n", errors);
|
||||||
|
|
||||||
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
|
|
@ -60,7 +60,7 @@ int connect_card(struct sc_context *ctx, struct sc_card **cardp,
|
||||||
|
|
||||||
reader = ctx->reader[reader_id];
|
reader = ctx->reader[reader_id];
|
||||||
slot_id = 0;
|
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");
|
fprintf(stderr, "Card not present.\n");
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue