mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-23 15:07:03 +01:00
* cardglue.c (open_card): Use shutdown code if possible.
(check_card_serialno): Ditto. * ccid-driver.c (do_close_reader): Factored some code out from ... (ccid_close_reader): ..here. (ccid_shutdown_reader): New. * apdu.c (apdu_shutdown_reader): New. (shutdown_ccid_reader): New.
This commit is contained in:
parent
ca26884b3a
commit
5576f6ef6c
@ -1,3 +1,15 @@
|
|||||||
|
2004-09-20 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* cardglue.c (open_card): Use shutdown code if possible.
|
||||||
|
(check_card_serialno): Ditto.
|
||||||
|
|
||||||
|
* ccid-driver.c (do_close_reader): Factored some code out from ...
|
||||||
|
(ccid_close_reader): ..here.
|
||||||
|
(ccid_shutdown_reader): New.
|
||||||
|
|
||||||
|
* apdu.c (apdu_shutdown_reader): New.
|
||||||
|
(shutdown_ccid_reader): New.
|
||||||
|
|
||||||
2004-09-17 Werner Koch <wk@g10code.com>
|
2004-09-17 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
* g10.c (list_config): New config option ccid-reader-id.
|
* g10.c (list_config): New config option ccid-reader-id.
|
||||||
|
24
g10/apdu.c
24
g10/apdu.c
@ -92,6 +92,7 @@ struct reader_table_s {
|
|||||||
|
|
||||||
/* Function pointers intialized to the various backends. */
|
/* Function pointers intialized to the various backends. */
|
||||||
int (*close_reader)(int);
|
int (*close_reader)(int);
|
||||||
|
int (*shutdown_reader)(int);
|
||||||
int (*reset_reader)(int);
|
int (*reset_reader)(int);
|
||||||
int (*get_status_reader)(int, unsigned int *);
|
int (*get_status_reader)(int, unsigned int *);
|
||||||
int (*send_apdu_reader)(int,unsigned char *,size_t,
|
int (*send_apdu_reader)(int,unsigned char *,size_t,
|
||||||
@ -244,6 +245,7 @@ new_reader_slot (void)
|
|||||||
}
|
}
|
||||||
#endif /*USE_GNU_PTH*/
|
#endif /*USE_GNU_PTH*/
|
||||||
reader_table[reader].close_reader = NULL;
|
reader_table[reader].close_reader = NULL;
|
||||||
|
reader_table[reader].shutdown_reader = NULL;
|
||||||
reader_table[reader].reset_reader = NULL;
|
reader_table[reader].reset_reader = NULL;
|
||||||
reader_table[reader].get_status_reader = NULL;
|
reader_table[reader].get_status_reader = NULL;
|
||||||
reader_table[reader].send_apdu_reader = NULL;
|
reader_table[reader].send_apdu_reader = NULL;
|
||||||
@ -1201,6 +1203,14 @@ close_ccid_reader (int slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
shutdown_ccid_reader (int slot)
|
||||||
|
{
|
||||||
|
ccid_shutdown_reader (reader_table[slot].ccid.handle);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
reset_ccid_reader (int slot)
|
reset_ccid_reader (int slot)
|
||||||
{
|
{
|
||||||
@ -1300,6 +1310,7 @@ open_ccid_reader (const char *portstr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
reader_table[slot].close_reader = close_ccid_reader;
|
reader_table[slot].close_reader = close_ccid_reader;
|
||||||
|
reader_table[slot].shutdown_reader = shutdown_ccid_reader;
|
||||||
reader_table[slot].reset_reader = reset_ccid_reader;
|
reader_table[slot].reset_reader = reset_ccid_reader;
|
||||||
reader_table[slot].get_status_reader = get_status_ccid;
|
reader_table[slot].get_status_reader = get_status_ccid;
|
||||||
reader_table[slot].send_apdu_reader = send_apdu_ccid;
|
reader_table[slot].send_apdu_reader = send_apdu_ccid;
|
||||||
@ -2051,6 +2062,19 @@ apdu_close_reader (int slot)
|
|||||||
return SW_HOST_NOT_SUPPORTED;
|
return SW_HOST_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Shutdown a reader; that is basically the same as a close but keeps
|
||||||
|
the handle ready for later use. A apdu_reset_header should be used
|
||||||
|
to get it active again. */
|
||||||
|
int
|
||||||
|
apdu_shutdown_reader (int slot)
|
||||||
|
{
|
||||||
|
if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used )
|
||||||
|
return SW_HOST_NO_DRIVER;
|
||||||
|
if (reader_table[slot].shutdown_reader)
|
||||||
|
return reader_table[slot].shutdown_reader (slot);
|
||||||
|
return SW_HOST_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
/* Enumerate all readers and return information on whether this reader
|
/* Enumerate all readers and return information on whether this reader
|
||||||
is in use. The caller should start with SLOT set to 0 and
|
is in use. The caller should start with SLOT set to 0 and
|
||||||
increment it with each call until an error is returned. */
|
increment it with each call until an error is returned. */
|
||||||
|
@ -76,6 +76,7 @@ int apdu_open_remote_reader (const char *portstr,
|
|||||||
void *writefnc_value,
|
void *writefnc_value,
|
||||||
void (*closefnc) (void *opaque),
|
void (*closefnc) (void *opaque),
|
||||||
void *closefnc_value);
|
void *closefnc_value);
|
||||||
|
int apdu_shutdown_reader (int slot);
|
||||||
int apdu_close_reader (int slot);
|
int apdu_close_reader (int slot);
|
||||||
int apdu_enum_reader (int slot, int *used);
|
int apdu_enum_reader (int slot, int *used);
|
||||||
unsigned char *apdu_get_atr (int slot, size_t *atrlen);
|
unsigned char *apdu_get_atr (int slot, size_t *atrlen);
|
||||||
|
@ -54,7 +54,6 @@ static APP current_app;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Create a serialno/fpr string from the serial number and the secret
|
/* Create a serialno/fpr string from the serial number and the secret
|
||||||
key. caller must free the returned string. There is no error
|
key. caller must free the returned string. There is no error
|
||||||
return. [Taken from 1.9's keyid.c]*/
|
return. [Taken from 1.9's keyid.c]*/
|
||||||
@ -247,18 +246,25 @@ agent_release_card_info (struct agent_card_info_s *info)
|
|||||||
static APP
|
static APP
|
||||||
open_card (void)
|
open_card (void)
|
||||||
{
|
{
|
||||||
int slot;
|
int slot = -1;
|
||||||
int rc;
|
int rc;
|
||||||
APP app;
|
APP app;
|
||||||
|
int did_shutdown = 0;
|
||||||
|
|
||||||
card_close ();
|
card_close ();
|
||||||
|
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
slot = apdu_open_reader (default_reader_port);
|
if (did_shutdown)
|
||||||
if (slot == -1)
|
apdu_reset (slot);
|
||||||
|
else
|
||||||
{
|
{
|
||||||
log_error ("card reader not available\n");
|
slot = apdu_open_reader (default_reader_port);
|
||||||
return NULL;
|
if (slot == -1)
|
||||||
|
{
|
||||||
|
log_error ("card reader not available\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app = xcalloc (1, sizeof *app);
|
app = xcalloc (1, sizeof *app);
|
||||||
@ -268,11 +274,14 @@ open_card (void)
|
|||||||
{
|
{
|
||||||
write_status_text (STATUS_CARDCTRL, "1");
|
write_status_text (STATUS_CARDCTRL, "1");
|
||||||
|
|
||||||
|
did_shutdown = !!apdu_shutdown_reader (slot);
|
||||||
|
|
||||||
if ( cpr_get_answer_okay_cancel ("cardctrl.insert_card.okay",
|
if ( cpr_get_answer_okay_cancel ("cardctrl.insert_card.okay",
|
||||||
_("Please insert the card and hit return or enter 'c' to cancel: "),
|
_("Please insert the card and hit return or enter 'c' to cancel: "),
|
||||||
1) )
|
1) )
|
||||||
{
|
{
|
||||||
apdu_close_reader (slot);
|
if (!did_shutdown)
|
||||||
|
apdu_close_reader (slot);
|
||||||
xfree (app);
|
xfree (app);
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
@ -323,7 +332,7 @@ card_close (void)
|
|||||||
function return 0 is the present card is okay, -1 if the user
|
function return 0 is the present card is okay, -1 if the user
|
||||||
selected to insert a new card or an error value. Note that the
|
selected to insert a new card or an error value. Note that the
|
||||||
card context will be closed in all cases except for 0 as return
|
card context will be closed in all cases except for 0 as return
|
||||||
value. */
|
value and if it was possible to merely shutdown the reader. */
|
||||||
static int
|
static int
|
||||||
check_card_serialno (APP app, const char *serialno)
|
check_card_serialno (APP app, const char *serialno)
|
||||||
{
|
{
|
||||||
@ -346,8 +355,12 @@ check_card_serialno (APP app, const char *serialno)
|
|||||||
if (ask)
|
if (ask)
|
||||||
{
|
{
|
||||||
char buf[5+32+1];
|
char buf[5+32+1];
|
||||||
|
int did_shutdown = 0;
|
||||||
|
|
||||||
card_close ();
|
if (current_app && !apdu_shutdown_reader (current_app->slot))
|
||||||
|
did_shutdown = 1;
|
||||||
|
else
|
||||||
|
card_close ();
|
||||||
tty_printf (_("Please remove the current card and "
|
tty_printf (_("Please remove the current card and "
|
||||||
"insert the one with the serial number:\n"
|
"insert the one with the serial number:\n"
|
||||||
" %.*s\n"), 32, serialno);
|
" %.*s\n"), 32, serialno);
|
||||||
@ -359,7 +372,14 @@ check_card_serialno (APP app, const char *serialno)
|
|||||||
_("Hit return when ready "
|
_("Hit return when ready "
|
||||||
"or enter 'c' to cancel: "),
|
"or enter 'c' to cancel: "),
|
||||||
1) )
|
1) )
|
||||||
return -1;
|
{
|
||||||
|
card_close ();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (did_shutdown)
|
||||||
|
apdu_reset (current_app->slot);
|
||||||
|
else
|
||||||
|
card_close ();
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -196,6 +196,7 @@ struct ccid_driver_s
|
|||||||
int auto_ifsd;
|
int auto_ifsd;
|
||||||
int max_ifsd;
|
int max_ifsd;
|
||||||
int ifsd;
|
int ifsd;
|
||||||
|
int powered_off;
|
||||||
int has_pinpad;
|
int has_pinpad;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -863,6 +864,102 @@ ccid_open_reader (ccid_driver_t *handle, const char *readerid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_close_reader (ccid_driver_t handle)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
unsigned char msg[100];
|
||||||
|
size_t msglen;
|
||||||
|
unsigned char seqno;
|
||||||
|
|
||||||
|
if (!handle->powered_off)
|
||||||
|
{
|
||||||
|
msg[0] = PC_to_RDR_IccPowerOff;
|
||||||
|
msg[5] = 0; /* slot */
|
||||||
|
msg[6] = seqno = handle->seqno++;
|
||||||
|
msg[7] = 0; /* RFU */
|
||||||
|
msg[8] = 0; /* RFU */
|
||||||
|
msg[9] = 0; /* RFU */
|
||||||
|
set_msg_len (msg, 0);
|
||||||
|
msglen = 10;
|
||||||
|
|
||||||
|
rc = bulk_out (handle, msg, msglen);
|
||||||
|
if (!rc)
|
||||||
|
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus,seqno);
|
||||||
|
handle->powered_off = 1;
|
||||||
|
}
|
||||||
|
if (handle->idev)
|
||||||
|
{
|
||||||
|
usb_release_interface (handle->idev, 0);
|
||||||
|
usb_close (handle->idev);
|
||||||
|
handle->idev = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Reset a reader on HANDLE. This is useful in case a reader has been
|
||||||
|
plugged of and inserted at a different port. By resetting the
|
||||||
|
handle, the same reader will be get used. Note, that on error the
|
||||||
|
handle won't get released.
|
||||||
|
|
||||||
|
This does not return an ATR, so ccid_get_atr should be called right
|
||||||
|
after this one.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ccid_shutdown_reader (ccid_driver_t handle)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct usb_device *dev = NULL;
|
||||||
|
usb_dev_handle *idev = NULL;
|
||||||
|
unsigned char *ifcdesc_extra = NULL;
|
||||||
|
size_t ifcdesc_extra_len;
|
||||||
|
|
||||||
|
if (!handle || !handle->rid)
|
||||||
|
return CCID_DRIVER_ERR_INV_VALUE;
|
||||||
|
|
||||||
|
do_close_reader (handle);
|
||||||
|
|
||||||
|
idev = scan_or_find_devices (-1, handle->rid, NULL, &dev,
|
||||||
|
&ifcdesc_extra, &ifcdesc_extra_len);
|
||||||
|
if (!idev)
|
||||||
|
{
|
||||||
|
DEBUGOUT_1 ("no CCID reader with ID %s\n", handle->rid);
|
||||||
|
return CCID_DRIVER_ERR_NO_READER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
handle->idev = idev;
|
||||||
|
|
||||||
|
if (parse_ccid_descriptor (handle, ifcdesc_extra, ifcdesc_extra_len))
|
||||||
|
{
|
||||||
|
DEBUGOUT ("device not supported\n");
|
||||||
|
rc = CCID_DRIVER_ERR_NO_READER;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fixme: Do we need to claim and set the interface as
|
||||||
|
determined above? */
|
||||||
|
rc = usb_claim_interface (idev, 0);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
DEBUGOUT_1 ("usb_claim_interface failed: %d\n", rc);
|
||||||
|
rc = CCID_DRIVER_ERR_CARD_IO_ERROR;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free (ifcdesc_extra);
|
||||||
|
if (rc)
|
||||||
|
{
|
||||||
|
usb_close (handle->idev);
|
||||||
|
handle->idev = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Close the reader HANDLE. */
|
/* Close the reader HANDLE. */
|
||||||
int
|
int
|
||||||
ccid_close_reader (ccid_driver_t handle)
|
ccid_close_reader (ccid_driver_t handle)
|
||||||
@ -870,34 +967,13 @@ ccid_close_reader (ccid_driver_t handle)
|
|||||||
if (!handle || !handle->idev)
|
if (!handle || !handle->idev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
{
|
do_close_reader (handle);
|
||||||
int rc;
|
|
||||||
unsigned char msg[100];
|
|
||||||
size_t msglen;
|
|
||||||
unsigned char seqno;
|
|
||||||
|
|
||||||
msg[0] = PC_to_RDR_IccPowerOff;
|
|
||||||
msg[5] = 0; /* slot */
|
|
||||||
msg[6] = seqno = handle->seqno++;
|
|
||||||
msg[7] = 0; /* RFU */
|
|
||||||
msg[8] = 0; /* RFU */
|
|
||||||
msg[9] = 0; /* RFU */
|
|
||||||
set_msg_len (msg, 0);
|
|
||||||
msglen = 10;
|
|
||||||
|
|
||||||
rc = bulk_out (handle, msg, msglen);
|
|
||||||
if (!rc)
|
|
||||||
bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_SlotStatus, seqno);
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_release_interface (handle->idev, 0);
|
|
||||||
usb_close (handle->idev);
|
|
||||||
handle->idev = NULL;
|
|
||||||
free (handle->rid);
|
free (handle->rid);
|
||||||
free (handle);
|
free (handle);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Return False if a card is present and powered. */
|
/* Return False if a card is present and powered. */
|
||||||
int
|
int
|
||||||
ccid_check_card_presence (ccid_driver_t handle)
|
ccid_check_card_presence (ccid_driver_t handle)
|
||||||
@ -1120,6 +1196,8 @@ ccid_get_atr (ccid_driver_t handle,
|
|||||||
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno);
|
rc = bulk_in (handle, msg, sizeof msg, &msglen, RDR_to_PC_DataBlock, seqno);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
handle->powered_off = 0;
|
||||||
|
|
||||||
if (atr)
|
if (atr)
|
||||||
{
|
{
|
||||||
@ -1680,16 +1758,16 @@ main (int argc, char **argv)
|
|||||||
ccid_poll (ccid);
|
ccid_poll (ccid);
|
||||||
|
|
||||||
/* if (!ccid->has_pinpad) */
|
/* if (!ccid->has_pinpad) */
|
||||||
{
|
/* { */
|
||||||
fputs ("verifying that CHV1 is 123456....\n", stderr);
|
/* fputs ("verifying that CHV1 is 123456....\n", stderr); */
|
||||||
{
|
/* { */
|
||||||
static unsigned char apdu[] = {0, 0x20, 0, 0x81,
|
/* static unsigned char apdu[] = {0, 0x20, 0, 0x81, */
|
||||||
6, '1','2','3','4','5','6'};
|
/* 6, '1','2','3','4','5','6'}; */
|
||||||
rc = ccid_transceive (ccid, apdu, sizeof apdu,
|
/* rc = ccid_transceive (ccid, apdu, sizeof apdu, */
|
||||||
result, sizeof result, &resultlen);
|
/* result, sizeof result, &resultlen); */
|
||||||
print_result (rc, result, resultlen);
|
/* print_result (rc, result, resultlen); */
|
||||||
}
|
/* } */
|
||||||
}
|
/* } */
|
||||||
/* else */
|
/* else */
|
||||||
/* { */
|
/* { */
|
||||||
/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */
|
/* fputs ("verifying CHV1 using the PINPad ....\n", stderr); */
|
||||||
|
@ -78,6 +78,7 @@ typedef struct ccid_driver_s *ccid_driver_t;
|
|||||||
int ccid_set_debug_level (int level);
|
int ccid_set_debug_level (int level);
|
||||||
char *ccid_get_reader_list (void);
|
char *ccid_get_reader_list (void);
|
||||||
int ccid_open_reader (ccid_driver_t *handle, const char *readerid);
|
int ccid_open_reader (ccid_driver_t *handle, const char *readerid);
|
||||||
|
int ccid_shutdown_reader (ccid_driver_t handle);
|
||||||
int ccid_close_reader (ccid_driver_t handle);
|
int ccid_close_reader (ccid_driver_t handle);
|
||||||
int ccid_get_atr (ccid_driver_t handle,
|
int ccid_get_atr (ccid_driver_t handle,
|
||||||
unsigned char *atr, size_t maxatrlen, size_t *atrlen);
|
unsigned char *atr, size_t maxatrlen, size_t *atrlen);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user