diff options
Diffstat (limited to 'qemu/libcacard/vreader.c')
-rw-r--r-- | qemu/libcacard/vreader.c | 578 |
1 files changed, 0 insertions, 578 deletions
diff --git a/qemu/libcacard/vreader.c b/qemu/libcacard/vreader.c deleted file mode 100644 index 9725f46a7..000000000 --- a/qemu/libcacard/vreader.c +++ /dev/null @@ -1,578 +0,0 @@ -/* - * emulate the reader - * - * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. - * See the COPYING.LIB file in the top-level directory. - */ - -#ifdef G_LOG_DOMAIN -#undef G_LOG_DOMAIN -#endif -#define G_LOG_DOMAIN "libcacard" - -#include "glib-compat.h" - -#include <string.h> - -#include "vcard.h" -#include "vcard_emul.h" -#include "card_7816.h" -#include "vreader.h" -#include "vevent.h" -#include "cac.h" /* just for debugging defines */ - -#define LIBCACARD_LOG_DOMAIN "libcacard" - -struct VReaderStruct { - int reference_count; - VCard *card; - char *name; - vreader_id_t id; - CompatGMutex lock; - VReaderEmul *reader_private; - VReaderEmulFree reader_private_free; -}; - -/* - * Debug helpers - */ - -static const char * -apdu_ins_to_string(int ins) -{ - switch (ins) { - case VCARD7816_INS_MANAGE_CHANNEL: - return "manage channel"; - case VCARD7816_INS_EXTERNAL_AUTHENTICATE: - return "external authenticate"; - case VCARD7816_INS_GET_CHALLENGE: - return "get challenge"; - case VCARD7816_INS_INTERNAL_AUTHENTICATE: - return "internal authenticate"; - case VCARD7816_INS_ERASE_BINARY: - return "erase binary"; - case VCARD7816_INS_READ_BINARY: - return "read binary"; - case VCARD7816_INS_WRITE_BINARY: - return "write binary"; - case VCARD7816_INS_UPDATE_BINARY: - return "update binary"; - case VCARD7816_INS_READ_RECORD: - return "read record"; - case VCARD7816_INS_WRITE_RECORD: - return "write record"; - case VCARD7816_INS_UPDATE_RECORD: - return "update record"; - case VCARD7816_INS_APPEND_RECORD: - return "append record"; - case VCARD7816_INS_ENVELOPE: - return "envelope"; - case VCARD7816_INS_PUT_DATA: - return "put data"; - case VCARD7816_INS_GET_DATA: - return "get data"; - case VCARD7816_INS_SELECT_FILE: - return "select file"; - case VCARD7816_INS_VERIFY: - return "verify"; - case VCARD7816_INS_GET_RESPONSE: - return "get response"; - case CAC_GET_PROPERTIES: - return "get properties"; - case CAC_GET_ACR: - return "get acr"; - case CAC_READ_BUFFER: - return "read buffer"; - case CAC_UPDATE_BUFFER: - return "update buffer"; - case CAC_SIGN_DECRYPT: - return "sign decrypt"; - case CAC_GET_CERTIFICATE: - return "get certificate"; - } - return "unknown"; -} - -/* manage locking */ -static inline void -vreader_lock(VReader *reader) -{ - g_mutex_lock(&reader->lock); -} - -static inline void -vreader_unlock(VReader *reader) -{ - g_mutex_unlock(&reader->lock); -} - -/* - * vreader constructor - */ -VReader * -vreader_new(const char *name, VReaderEmul *private, - VReaderEmulFree private_free) -{ - VReader *reader; - - reader = g_new(VReader, 1); - g_mutex_init(&reader->lock); - reader->reference_count = 1; - reader->name = g_strdup(name); - reader->card = NULL; - reader->id = (vreader_id_t)-1; - reader->reader_private = private; - reader->reader_private_free = private_free; - return reader; -} - -/* get a reference */ -VReader* -vreader_reference(VReader *reader) -{ - if (reader == NULL) { - return NULL; - } - vreader_lock(reader); - reader->reference_count++; - vreader_unlock(reader); - return reader; -} - -/* free a reference */ -void -vreader_free(VReader *reader) -{ - if (reader == NULL) { - return; - } - vreader_lock(reader); - if (reader->reference_count-- > 1) { - vreader_unlock(reader); - return; - } - vreader_unlock(reader); - g_mutex_clear(&reader->lock); - if (reader->card) { - vcard_free(reader->card); - } - g_free(reader->name); - if (reader->reader_private_free) { - reader->reader_private_free(reader->reader_private); - } - g_free(reader); -} - -static VCard * -vreader_get_card(VReader *reader) -{ - VCard *card; - - vreader_lock(reader); - card = vcard_reference(reader->card); - vreader_unlock(reader); - return card; -} - -VReaderStatus -vreader_card_is_present(VReader *reader) -{ - VCard *card = vreader_get_card(reader); - - if (card == NULL) { - return VREADER_NO_CARD; - } - vcard_free(card); - return VREADER_OK; -} - -vreader_id_t -vreader_get_id(VReader *reader) -{ - if (reader == NULL) { - return (vreader_id_t)-1; - } - return reader->id; -} - -VReaderStatus -vreader_set_id(VReader *reader, vreader_id_t id) -{ - if (reader == NULL) { - return VREADER_NO_CARD; - } - reader->id = id; - return VREADER_OK; -} - -const char * -vreader_get_name(VReader *reader) -{ - if (reader == NULL) { - return NULL; - } - return reader->name; -} - -VReaderEmul * -vreader_get_private(VReader *reader) -{ - return reader->reader_private; -} - -static VReaderStatus -vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len) -{ - VCard *card = vreader_get_card(reader); - - if (card == NULL) { - return VREADER_NO_CARD; - } - /* - * clean up our state - */ - vcard_reset(card, power); - if (atr) { - vcard_get_atr(card, atr, len); - } - vcard_free(card); /* free our reference */ - return VREADER_OK; -} - -VReaderStatus -vreader_power_on(VReader *reader, unsigned char *atr, int *len) -{ - return vreader_reset(reader, VCARD_POWER_ON, atr, len); -} - -VReaderStatus -vreader_power_off(VReader *reader) -{ - return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0); -} - - -VReaderStatus -vreader_xfr_bytes(VReader *reader, - unsigned char *send_buf, int send_buf_len, - unsigned char *receive_buf, int *receive_buf_len) -{ - VCardAPDU *apdu; - VCardResponse *response = NULL; - VCardStatus card_status; - unsigned short status; - VCard *card = vreader_get_card(reader); - - if (card == NULL) { - return VREADER_NO_CARD; - } - - apdu = vcard_apdu_new(send_buf, send_buf_len, &status); - if (apdu == NULL) { - response = vcard_make_response(status); - card_status = VCARD_DONE; - } else { - g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s", - __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2, - apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins)); - card_status = vcard_process_apdu(card, apdu, &response); - if (response) { - g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)", - __func__, response->b_status, response->b_sw1, - response->b_sw2, response->b_len, response->b_total_len); - } - } - assert(card_status == VCARD_DONE && response); - int size = MIN(*receive_buf_len, response->b_total_len); - memcpy(receive_buf, response->b_data, size); - *receive_buf_len = size; - vcard_response_delete(response); - vcard_apdu_delete(apdu); - vcard_free(card); /* free our reference */ - return VREADER_OK; -} - -struct VReaderListStruct { - VReaderListEntry *head; - VReaderListEntry *tail; -}; - -struct VReaderListEntryStruct { - VReaderListEntry *next; - VReaderListEntry *prev; - VReader *reader; -}; - - -static VReaderListEntry * -vreader_list_entry_new(VReader *reader) -{ - VReaderListEntry *new_reader_list_entry; - - new_reader_list_entry = g_new0(VReaderListEntry, 1); - new_reader_list_entry->reader = vreader_reference(reader); - return new_reader_list_entry; -} - -static void -vreader_list_entry_delete(VReaderListEntry *entry) -{ - if (entry == NULL) { - return; - } - vreader_free(entry->reader); - g_free(entry); -} - - -static VReaderList * -vreader_list_new(void) -{ - VReaderList *new_reader_list; - - new_reader_list = g_new0(VReaderList, 1); - return new_reader_list; -} - -void -vreader_list_delete(VReaderList *list) -{ - VReaderListEntry *current_entry; - VReaderListEntry *next_entry; - for (current_entry = vreader_list_get_first(list); current_entry; - current_entry = next_entry) { - next_entry = vreader_list_get_next(current_entry); - vreader_list_entry_delete(current_entry); - } - g_free(list); -} - - -VReaderListEntry * -vreader_list_get_first(VReaderList *list) -{ - return list ? list->head : NULL; -} - -VReaderListEntry * -vreader_list_get_next(VReaderListEntry *current) -{ - return current ? current->next : NULL; -} - -VReader * -vreader_list_get_reader(VReaderListEntry *entry) -{ - return entry ? vreader_reference(entry->reader) : NULL; -} - -static void -vreader_queue(VReaderList *list, VReaderListEntry *entry) -{ - if (entry == NULL) { - return; - } - entry->next = NULL; - entry->prev = list->tail; - if (list->head) { - list->tail->next = entry; - } else { - list->head = entry; - } - list->tail = entry; -} - -static void -vreader_dequeue(VReaderList *list, VReaderListEntry *entry) -{ - if (entry == NULL) { - return; - } - if (entry->next == NULL) { - list->tail = entry->prev; - } else if (entry->prev == NULL) { - list->head = entry->next; - } else { - entry->prev->next = entry->next; - entry->next->prev = entry->prev; - } - if ((list->tail == NULL) || (list->head == NULL)) { - list->head = list->tail = NULL; - } - entry->next = entry->prev = NULL; -} - -static VReaderList *vreader_list; -static CompatGMutex vreader_list_mutex; - -static void -vreader_list_init(void) -{ - vreader_list = vreader_list_new(); -} - -static void -vreader_list_lock(void) -{ - g_mutex_lock(&vreader_list_mutex); -} - -static void -vreader_list_unlock(void) -{ - g_mutex_unlock(&vreader_list_mutex); -} - -static VReaderList * -vreader_copy_list(VReaderList *list) -{ - VReaderList *new_list; - VReaderListEntry *current_entry; - - new_list = vreader_list_new(); - if (new_list == NULL) { - return NULL; - } - for (current_entry = vreader_list_get_first(list); current_entry; - current_entry = vreader_list_get_next(current_entry)) { - VReader *reader = vreader_list_get_reader(current_entry); - VReaderListEntry *new_entry = vreader_list_entry_new(reader); - - vreader_free(reader); - vreader_queue(new_list, new_entry); - } - return new_list; -} - -VReaderList * -vreader_get_reader_list(void) -{ - VReaderList *new_reader_list; - - vreader_list_lock(); - new_reader_list = vreader_copy_list(vreader_list); - vreader_list_unlock(); - return new_reader_list; -} - -VReader * -vreader_get_reader_by_id(vreader_id_t id) -{ - VReader *reader = NULL; - VReaderListEntry *current_entry; - - if (id == (vreader_id_t) -1) { - return NULL; - } - - vreader_list_lock(); - for (current_entry = vreader_list_get_first(vreader_list); current_entry; - current_entry = vreader_list_get_next(current_entry)) { - VReader *creader = vreader_list_get_reader(current_entry); - if (creader->id == id) { - reader = creader; - break; - } - vreader_free(creader); - } - vreader_list_unlock(); - return reader; -} - -VReader * -vreader_get_reader_by_name(const char *name) -{ - VReader *reader = NULL; - VReaderListEntry *current_entry; - - vreader_list_lock(); - for (current_entry = vreader_list_get_first(vreader_list); current_entry; - current_entry = vreader_list_get_next(current_entry)) { - VReader *creader = vreader_list_get_reader(current_entry); - if (strcmp(creader->name, name) == 0) { - reader = creader; - break; - } - vreader_free(creader); - } - vreader_list_unlock(); - return reader; -} - -/* called from card_emul to initialize the readers */ -VReaderStatus -vreader_add_reader(VReader *reader) -{ - VReaderListEntry *reader_entry; - - reader_entry = vreader_list_entry_new(reader); - if (reader_entry == NULL) { - return VREADER_OUT_OF_MEMORY; - } - vreader_list_lock(); - vreader_queue(vreader_list, reader_entry); - vreader_list_unlock(); - vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL)); - return VREADER_OK; -} - - -VReaderStatus -vreader_remove_reader(VReader *reader) -{ - VReaderListEntry *current_entry; - - vreader_list_lock(); - for (current_entry = vreader_list_get_first(vreader_list); current_entry; - current_entry = vreader_list_get_next(current_entry)) { - if (current_entry->reader == reader) { - break; - } - } - vreader_dequeue(vreader_list, current_entry); - vreader_list_unlock(); - vreader_list_entry_delete(current_entry); - vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL)); - return VREADER_OK; -} - -/* - * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader - * state. Separated from vreader_insert_card to allow replaying events - * for a given state. - */ -void -vreader_queue_card_event(VReader *reader) -{ - vevent_queue_vevent(vevent_new( - reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader, - reader->card)); -} - -/* - * insert/remove a new card. for removal, card == NULL - */ -VReaderStatus -vreader_insert_card(VReader *reader, VCard *card) -{ - vreader_lock(reader); - if (reader->card) { - /* decrement reference count */ - vcard_free(reader->card); - reader->card = NULL; - } - reader->card = vcard_reference(card); - vreader_unlock(reader); - vreader_queue_card_event(reader); - return VREADER_OK; -} - -/* - * initialize all the static reader structures - */ -void -vreader_init(void) -{ - vreader_list_init(); -} - |