libopensc: fetch card's UID

Fetch card's UID.
For file caching, use UID if SN is not available.
This commit is contained in:
Frank Morgner 2016-06-20 11:43:27 +02:00 committed by Viktor Tarasov
parent cee092a930
commit 60f2d06308
5 changed files with 55 additions and 3 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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)) {

View File

@ -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;
}

View File

@ -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];