From 60f2d063085ffec2751bca9936842d558b3d0230 Mon Sep 17 00:00:00 2001 From: Frank Morgner Date: Mon, 20 Jun 2016 11:43:27 +0200 Subject: [PATCH] libopensc: fetch card's UID Fetch card's UID. For file caching, use UID if SN is not available. --- src/libopensc/card.c | 1 + src/libopensc/opensc.h | 2 ++ src/libopensc/pkcs15-cache.c | 17 ++++++++++++++--- src/libopensc/reader-pcsc.c | 32 ++++++++++++++++++++++++++++++++ src/libopensc/types.h | 6 ++++++ 5 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/libopensc/card.c b/src/libopensc/card.c index 8c042078..910cffb8 100644 --- a/src/libopensc/card.c +++ b/src/libopensc/card.c @@ -209,6 +209,7 @@ int sc_connect_card(sc_reader_t *reader, sc_card_t **card_out) card->ctx = ctx; memcpy(&card->atr, &reader->atr, sizeof(card->atr)); + memcpy(&card->uid, &reader->uid, sizeof(card->uid)); _sc_parse_atr(reader); diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h index 65d626ed..8913cc7c 100644 --- a/src/libopensc/opensc.h +++ b/src/libopensc/opensc.h @@ -316,6 +316,7 @@ typedef struct sc_reader { size_t max_recv_size; /* Mac Le supported by the reader layer */ struct sc_atr atr; + struct sc_uid uid; struct _atr_info { u8 *hist_bytes; size_t hist_bytes_len; @@ -470,6 +471,7 @@ typedef struct sc_card { struct sc_reader *reader; struct sc_atr atr; + struct sc_uid uid; int type; /* Card type, for card driver internal use */ unsigned long caps, flags; diff --git a/src/libopensc/pkcs15-cache.c b/src/libopensc/pkcs15-cache.c index 865db031..5cdd0cd3 100644 --- a/src/libopensc/pkcs15-cache.c +++ b/src/libopensc/pkcs15-cache.c @@ -36,6 +36,7 @@ #include "internal.h" #include "pkcs15.h" +#define RANDOM_UID_INDICATOR 0x08 static int generate_cache_filename(struct sc_pkcs15_card *p15card, const sc_path_t *path, char *buf, size_t bufsize) @@ -45,7 +46,9 @@ static int generate_cache_filename(struct sc_pkcs15_card *p15card, int r; unsigned u; - if (p15card->tokeninfo->serial_number == NULL) + if (p15card->tokeninfo->serial_number == NULL + && (p15card->card->uid.len == 0 + || p15card->card->uid.value[0] == RANDOM_UID_INDICATOR)) return SC_ERROR_INVALID_ARGUMENTS; assert(path->len <= SC_MAX_PATH_SIZE); @@ -58,8 +61,16 @@ static int generate_cache_filename(struct sc_pkcs15_card *p15card, if (!last_update) last_update = "NODATE"; - snprintf(dir + strlen(dir), sizeof(dir) - strlen(dir), - "%s_%s", p15card->tokeninfo->serial_number, last_update); + if (p15card->tokeninfo->serial_number) { + snprintf(dir + strlen(dir), sizeof(dir) - strlen(dir), + "%s_%s", p15card->tokeninfo->serial_number, + last_update); + } else { + snprintf(dir + strlen(dir), sizeof(dir) - strlen(dir), + "uid-%s_%s", sc_dump_hex( + p15card->card->uid.value, + p15card->card->uid.len), last_update); + } if (path->aid.len && (path->type == SC_PATH_TYPE_FILE_ID || path->type == SC_PATH_TYPE_PATH)) { diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c index 304a14e8..93bfbbed 100644 --- a/src/libopensc/reader-pcsc.c +++ b/src/libopensc/reader-pcsc.c @@ -470,6 +470,34 @@ static int pcsc_reconnect(sc_reader_t * reader, DWORD action) return pcsc_to_opensc_error(rv); } +static void initialize_uid(sc_reader_t *reader) +{ + sc_apdu_t apdu; + /* though we only expect 10 bytes max, we want to set the Le to 0x00 to not + * get 0x6282 as SW in case of a UID variant shorter than 10 bytes */ + u8 rbuf[256]; + + memset(&apdu, 0, sizeof(apdu)); + apdu.cse = SC_APDU_CASE_2_SHORT; + apdu.cla = 0xFF; + apdu.ins = 0xCA; + apdu.p1 = 0x00; + apdu.p2 = 0x00; + apdu.le = 0x00; + apdu.resp = rbuf; + apdu.resplen = sizeof rbuf; + + if (SC_SUCCESS == pcsc_transmit(reader, &apdu) + && apdu.sw1 == 0x90 && apdu.sw2 == 0x00) { + reader->uid.len = apdu.resplen; + memcpy(reader->uid.value, apdu.resp, reader->uid.len); + sc_debug_hex(reader->ctx, SC_LOG_DEBUG_NORMAL, "UID", + reader->uid.value, reader->uid.len); + } else { + sc_debug(reader->ctx, SC_LOG_DEBUG_NORMAL, "unable to get UID"); + } +} + static int pcsc_connect(sc_reader_t *reader) { DWORD active_proto, tmp, protocol = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; @@ -522,6 +550,8 @@ static int pcsc_connect(sc_reader_t *reader) sc_log(reader->ctx, "Final protocol: %s", reader->active_protocol == SC_PROTO_T1 ? "T=1" : "T=0"); } + initialize_uid(reader); + /* After connect reader is not locked yet */ priv->locked = 0; @@ -2185,6 +2215,8 @@ static int cardmod_connect(sc_reader_t *reader) if (!(reader->flags & SC_READER_CARD_PRESENT)) return SC_ERROR_CARD_NOT_PRESENT; + initialize_uid(reader); + return SC_SUCCESS; } diff --git a/src/libopensc/types.h b/src/libopensc/types.h index 38f4c4bf..a5f9250f 100644 --- a/src/libopensc/types.h +++ b/src/libopensc/types.h @@ -35,6 +35,7 @@ typedef unsigned char u8; #define SC_MAX_EXT_APDU_BUFFER_SIZE 65538 #define SC_MAX_PIN_SIZE 256 /* OpenPGP card has 254 max */ #define SC_MAX_ATR_SIZE 33 +#define SC_MAX_UID_SIZE 10 #define SC_MAX_AID_SIZE 16 #define SC_MAX_AID_STRING_SIZE (SC_MAX_AID_SIZE * 2 + 3) #define SC_MAX_IIN_SIZE 10 @@ -76,6 +77,11 @@ struct sc_atr { size_t len; }; +struct sc_uid { + unsigned char value[SC_MAX_UID_SIZE]; + size_t len; +}; + /* Issuer ID */ struct sc_iid { unsigned char value[SC_MAX_IIN_SIZE];