From 5a0fbad9b3f44440d63c5b17a4e4197f4561f1e4 Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 10 Oct 2003 15:12:02 +0000 Subject: [PATCH] * cardglue.c (card_close): New. * ccid-driver.c (ccid_close_reader): New. * apdu.c (close_ccid_reader, close_ct_reader, close_csc_reader) (close_osc_reader, apdu_close_reader): New. Not all are properly implemented yet. * g10.c (g10_exit): Use close_card. --- g10/ChangeLog | 9 +++++++ g10/apdu.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ g10/apdu.h | 1 + g10/cardglue.c | 16 +++++++++++-- g10/cardglue.h | 2 ++ g10/ccid-driver.c | 61 +++++++++++++++++++++++++++++++++++++++-------- g10/ccid-driver.h | 1 + g10/g10.c | 3 +++ 8 files changed, 139 insertions(+), 12 deletions(-) diff --git a/g10/ChangeLog b/g10/ChangeLog index 9cfc79409..f96e83190 100644 --- a/g10/ChangeLog +++ b/g10/ChangeLog @@ -1,3 +1,12 @@ +2003-10-10 Werner Koch + + * cardglue.c (card_close): New. + * ccid-driver.c (ccid_close_reader): New. + * apdu.c (close_ccid_reader, close_ct_reader, close_csc_reader) + (close_osc_reader, apdu_close_reader): New. Not all are properly + implemented yet. + * g10.c (g10_exit): Use close_card. + 2003-10-09 David Shaw * g10.c (main): Give a deprecated option warning for diff --git a/g10/apdu.c b/g10/apdu.c index d5b93de6e..1587bfe5b 100644 --- a/g10/apdu.c +++ b/g10/apdu.c @@ -347,6 +347,14 @@ open_ct_reader (int port) return reader; } +static int +close_ct_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual retruned size will be @@ -570,6 +578,17 @@ pcsc_send_apdu (int slot, unsigned char *apdu, size_t apdulen, return err? -1:0; /* FIXME: Return appropriate error code. */ } +static int +close_pcsc_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + + + + #ifdef HAVE_LIBUSB /* @@ -609,6 +628,15 @@ open_ccid_reader (void) return slot; } +static int +close_ccid_reader (int slot) +{ + ccid_close_reader (reader_table[slot].ccid.handle); + reader_table[slot].used = 0; + return 0; +} + + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be @@ -738,6 +766,16 @@ open_osc_reader (int portno) } +static int +close_osc_reader (int slot) +{ + /* FIXME: Implement. */ + reader_table[slot].used = 0; + return 0; +} + + + /* Actually send the APDU of length APDULEN to SLOT and return a maximum of *BUFLEN data in BUFFER, the actual returned size will be set to BUFLEN. Returns: OpenSC error code. */ @@ -940,6 +978,26 @@ apdu_open_reader (const char *portstr) } +int +apdu_close_reader (int slot) +{ + if (slot < 0 || slot >= MAX_READER || !reader_table[slot].used ) + return SW_HOST_NO_DRIVER; + if (reader_table[slot].is_ctapi) + return close_ct_reader (slot); +#ifdef HAVE_LIBUSB + else if (reader_table[slot].is_ccid) + return close_ccid_reader (slot); +#endif +#ifdef HAVE_OPENSC + else if (reader_table[slot].is_osc) + return close_osc_reader (slot); +#endif + else + return close_pcsc_reader (slot); +} + + unsigned char * apdu_get_atr (int slot, size_t *atrlen) { diff --git a/g10/apdu.h b/g10/apdu.h index 6e4244ba0..21e2b9840 100644 --- a/g10/apdu.h +++ b/g10/apdu.h @@ -54,6 +54,7 @@ enum { /* Note , that apdu_open_reader returns no status word but -1 on error. */ int apdu_open_reader (const char *portstr); +int apdu_close_reader (int slot); unsigned char *apdu_get_atr (int slot, size_t *atrlen); diff --git a/g10/cardglue.c b/g10/cardglue.c index 91637a776..1bd36b342 100644 --- a/g10/cardglue.c +++ b/g10/cardglue.c @@ -249,7 +249,7 @@ open_card (void) int rc; APP app; - current_app = NULL;/* FIXME: Release it first.*/ + card_close (); slot = apdu_open_reader (default_reader_port); if (slot == -1) { @@ -262,7 +262,7 @@ open_card (void) rc = app_select_openpgp (app, &app->serialno, &app->serialnolen); if (rc) { -/* apdu_close_reader (slot); */ + apdu_close_reader (slot); log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc)); xfree (app); return NULL; @@ -273,6 +273,18 @@ open_card (void) return app; } +void +card_close (void) +{ + if (current_app) + { + APP app = current_app; + current_app = NULL; + + apdu_close_reader (app->slot); + xfree (app); + } +} /* Return a new malloced string by unescaping the string S. Escaping diff --git a/g10/cardglue.h b/g10/cardglue.h index fcd372682..b0ad8aa61 100644 --- a/g10/cardglue.h +++ b/g10/cardglue.h @@ -122,6 +122,8 @@ void log_printhex (const char *text, const void *buffer, size_t length); #define GCRY_MD_SHA1 DIGEST_ALGO_SHA1 #define GCRY_MD_RMD160 DIGEST_ALGO_RMD160 +void card_close (void); + /* Release the card info structure. */ void agent_release_card_info (struct agent_card_info_s *info); diff --git a/g10/ccid-driver.c b/g10/ccid-driver.c index 35f0329db..f14600cc2 100644 --- a/g10/ccid-driver.c +++ b/g10/ccid-driver.c @@ -174,6 +174,12 @@ struct ccid_driver_s { }; +static int bulk_out (ccid_driver_t handle, unsigned char *msg, size_t msglen); +static int bulk_in (ccid_driver_t handle, unsigned char *buffer, size_t length, + size_t *nread, int expected_type, int seqno); + + + /* Convert a little endian stored 4 byte value into an unsigned integer. */ static unsigned int @@ -182,6 +188,16 @@ convert_le_u32 (const unsigned char *buf) return buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); } +static void +set_msg_len (unsigned char *msg, unsigned int length) +{ + msg[1] = length; + msg[2] = length >> 8; + msg[3] = length >> 16; + msg[4] = length >> 24; +} + + /* Parse a CCID descriptor, optionally print all available features @@ -482,6 +498,41 @@ ccid_open_reader (ccid_driver_t *handle, int readerno) } +/* Close the reader HANDLE. */ +int +ccid_close_reader (ccid_driver_t handle) +{ + if (!handle || !handle->idev) + return 0; + + { + 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); + return 0; +} + + /* Return False if a card is present and powered. */ int ccid_check_card_presence (ccid_driver_t handle) @@ -491,16 +542,6 @@ ccid_check_card_presence (ccid_driver_t handle) } -static void -set_msg_len (unsigned char *msg, unsigned int length) -{ - msg[1] = length; - msg[2] = length >> 8; - msg[3] = length >> 16; - msg[4] = length >> 24; -} - - /* Write a MSG of length MSGLEN to the designated bulk out endpoint. Returns 0 on success. */ static int diff --git a/g10/ccid-driver.h b/g10/ccid-driver.h index 4d12d88c2..e33be55d9 100644 --- a/g10/ccid-driver.h +++ b/g10/ccid-driver.h @@ -60,6 +60,7 @@ struct ccid_driver_s; typedef struct ccid_driver_s *ccid_driver_t; int ccid_open_reader (ccid_driver_t *handle, int readerno); +int ccid_close_reader (ccid_driver_t handle); int ccid_get_atr (ccid_driver_t handle, unsigned char *atr, size_t maxatrlen, size_t *atrlen); int ccid_transceive (ccid_driver_t handle, diff --git a/g10/g10.c b/g10/g10.c index 34c8076f6..5dff5768a 100644 --- a/g10/g10.c +++ b/g10/g10.c @@ -2980,6 +2980,9 @@ main( int argc, char **argv ) void g10_exit( int rc ) { +#ifdef ENABLE_CARD_SUPPORT + card_close (); +#endif update_random_seed_file(); if( opt.debug & DBG_MEMSTAT_VALUE ) { m_print_stats("on exit");