29
#include "qemu/osdep.h"
32
#include "qemu/thread.h"
33
#include "qemu/lockable.h"
34
#include "qemu/main-loop.h"
35
#include "qemu/module.h"
37
#include "hw/qdev-properties.h"
38
#include "qapi/error.h"
39
#include "qom/object.h"
41
#define DPRINTF(card, lvl, fmt, ...) \
43
if (lvl <= card->debug) {\
44
printf("ccid-card-emul: %s: " fmt , __func__, ## __VA_ARGS__);\
49
#define TYPE_EMULATED_CCID "ccid-card-emulated"
50
typedef struct EmulatedState EmulatedState;
51
DECLARE_INSTANCE_CHECKER(EmulatedState, EMULATED_CCID_CARD,
54
#define BACKEND_NSS_EMULATED_NAME "nss-emulated"
55
#define BACKEND_CERTIFICATES_NAME "certificates"
58
BACKEND_NSS_EMULATED = 1,
62
#define DEFAULT_BACKEND BACKEND_NSS_EMULATED
66
EMUL_READER_INSERT = 0,
75
static const char *emul_event_to_string(uint32_t emul_event)
78
case EMUL_READER_INSERT:
79
return "EMUL_READER_INSERT";
80
case EMUL_READER_REMOVE:
81
return "EMUL_READER_REMOVE";
82
case EMUL_CARD_INSERT:
83
return "EMUL_CARD_INSERT";
84
case EMUL_CARD_REMOVE:
85
return "EMUL_CARD_REMOVE";
87
return "EMUL_GUEST_APDU";
88
case EMUL_RESPONSE_APDU:
89
return "EMUL_RESPONSE_APDU";
96
typedef struct EmulEvent {
97
QSIMPLEQ_ENTRY(EmulEvent) entry;
114
#define MAX_ATR_SIZE 40
115
struct EmulatedState {
124
uint8_t atr[MAX_ATR_SIZE];
126
QSIMPLEQ_HEAD(, EmulEvent) event_list;
127
QemuMutex event_list_mutex;
128
QemuThread event_thread_id;
130
QSIMPLEQ_HEAD(, EmulEvent) guest_apdu_list;
131
QemuMutex vreader_mutex;
132
QemuMutex handle_apdu_mutex;
133
QemuCond handle_apdu_cond;
134
EventNotifier notifier;
135
int quit_apdu_thread;
136
QemuThread apdu_thread_id;
139
static void emulated_apdu_from_guest(CCIDCardState *base,
140
const uint8_t *apdu, uint32_t len)
142
EmulatedState *card = EMULATED_CCID_CARD(base);
143
EmulEvent *event = g_malloc(sizeof(EmulEvent) + len);
146
event->p.data.type = EMUL_GUEST_APDU;
147
event->p.data.len = len;
148
memcpy(event->p.data.data, apdu, len);
149
qemu_mutex_lock(&card->vreader_mutex);
150
QSIMPLEQ_INSERT_TAIL(&card->guest_apdu_list, event, entry);
151
qemu_mutex_unlock(&card->vreader_mutex);
152
qemu_mutex_lock(&card->handle_apdu_mutex);
153
qemu_cond_signal(&card->handle_apdu_cond);
154
qemu_mutex_unlock(&card->handle_apdu_mutex);
157
static const uint8_t *emulated_get_atr(CCIDCardState *base, uint32_t *len)
159
EmulatedState *card = EMULATED_CCID_CARD(base);
161
*len = card->atr_length;
165
static void emulated_push_event(EmulatedState *card, EmulEvent *event)
167
qemu_mutex_lock(&card->event_list_mutex);
168
QSIMPLEQ_INSERT_TAIL(&(card->event_list), event, entry);
169
qemu_mutex_unlock(&card->event_list_mutex);
170
event_notifier_set(&card->notifier);
173
static void emulated_push_type(EmulatedState *card, uint32_t type)
175
EmulEvent *event = g_new(EmulEvent, 1);
178
event->p.gen.type = type;
179
emulated_push_event(card, event);
182
static void emulated_push_error(EmulatedState *card, uint64_t code)
184
EmulEvent *event = g_new(EmulEvent, 1);
187
event->p.error.type = EMUL_ERROR;
188
event->p.error.code = code;
189
emulated_push_event(card, event);
192
static void emulated_push_data_type(EmulatedState *card, uint32_t type,
193
const uint8_t *data, uint32_t len)
195
EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len);
198
event->p.data.type = type;
199
event->p.data.len = len;
200
memcpy(event->p.data.data, data, len);
201
emulated_push_event(card, event);
204
static void emulated_push_reader_insert(EmulatedState *card)
206
emulated_push_type(card, EMUL_READER_INSERT);
209
static void emulated_push_reader_remove(EmulatedState *card)
211
emulated_push_type(card, EMUL_READER_REMOVE);
214
static void emulated_push_card_insert(EmulatedState *card,
215
const uint8_t *atr, uint32_t len)
217
emulated_push_data_type(card, EMUL_CARD_INSERT, atr, len);
220
static void emulated_push_card_remove(EmulatedState *card)
222
emulated_push_type(card, EMUL_CARD_REMOVE);
225
static void emulated_push_response_apdu(EmulatedState *card,
226
const uint8_t *apdu, uint32_t len)
228
emulated_push_data_type(card, EMUL_RESPONSE_APDU, apdu, len);
231
#define APDU_BUF_SIZE 270
232
static void *handle_apdu_thread(void* arg)
234
EmulatedState *card = arg;
235
uint8_t recv_data[APDU_BUF_SIZE];
237
VReaderStatus reader_status;
241
qemu_mutex_lock(&card->handle_apdu_mutex);
242
qemu_cond_wait(&card->handle_apdu_cond, &card->handle_apdu_mutex);
243
qemu_mutex_unlock(&card->handle_apdu_mutex);
244
if (card->quit_apdu_thread) {
245
card->quit_apdu_thread = 0;
248
WITH_QEMU_LOCK_GUARD(&card->vreader_mutex) {
249
while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) {
250
event = QSIMPLEQ_FIRST(&card->guest_apdu_list);
251
assert(event != NULL);
252
QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry);
253
if (event->p.data.type != EMUL_GUEST_APDU) {
254
DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n");
258
if (card->reader == NULL) {
259
DPRINTF(card, 1, "reader is NULL\n");
263
recv_len = sizeof(recv_data);
264
reader_status = vreader_xfr_bytes(card->reader,
265
event->p.data.data, event->p.data.len,
266
recv_data, &recv_len);
267
DPRINTF(card, 2, "got back apdu of length %d\n", recv_len);
268
if (reader_status == VREADER_OK) {
269
emulated_push_response_apdu(card, recv_data, recv_len);
271
emulated_push_error(card, reader_status);
280
static void *event_thread(void *arg)
282
int atr_len = MAX_ATR_SIZE;
283
uint8_t atr[MAX_ATR_SIZE];
284
VEvent *event = NULL;
285
EmulatedState *card = arg;
288
const char *reader_name;
290
event = vevent_wait_next_vevent();
291
if (event == NULL || event->type == VEVENT_LAST) {
294
if (event->type != VEVENT_READER_INSERT) {
295
if (card->reader == NULL && event->reader != NULL) {
300
card->reader = vreader_reference(event->reader);
302
if (event->reader != card->reader) {
304
"ERROR: wrong reader: quitting event_thread\n");
309
switch (event->type) {
310
case VEVENT_READER_INSERT:
315
reader_name = vreader_get_name(event->reader);
316
if (card->reader != NULL) {
317
DPRINTF(card, 2, "READER INSERT - replacing %s with %s\n",
318
vreader_get_name(card->reader), reader_name);
319
qemu_mutex_lock(&card->vreader_mutex);
320
vreader_free(card->reader);
321
qemu_mutex_unlock(&card->vreader_mutex);
322
emulated_push_reader_remove(card);
324
qemu_mutex_lock(&card->vreader_mutex);
325
DPRINTF(card, 2, "READER INSERT %s\n", reader_name);
326
card->reader = vreader_reference(event->reader);
327
qemu_mutex_unlock(&card->vreader_mutex);
328
emulated_push_reader_insert(card);
330
case VEVENT_READER_REMOVE:
331
DPRINTF(card, 2, " READER REMOVE: %s\n",
332
vreader_get_name(event->reader));
333
qemu_mutex_lock(&card->vreader_mutex);
334
vreader_free(card->reader);
336
qemu_mutex_unlock(&card->vreader_mutex);
337
emulated_push_reader_remove(card);
339
case VEVENT_CARD_INSERT:
342
atr_len = MAX_ATR_SIZE;
343
vreader_power_on(event->reader, atr, &atr_len);
344
card->atr_length = (uint8_t)atr_len;
345
DPRINTF(card, 2, " CARD INSERT\n");
346
emulated_push_card_insert(card, atr, atr_len);
348
case VEVENT_CARD_REMOVE:
349
DPRINTF(card, 2, " CARD REMOVE\n");
350
emulated_push_card_remove(card);
353
vevent_delete(event);
358
vevent_delete(event);
363
static void card_event_handler(EventNotifier *notifier)
365
EmulatedState *card = container_of(notifier, EmulatedState, notifier);
366
EmulEvent *event, *next;
368
event_notifier_test_and_clear(&card->notifier);
369
QEMU_LOCK_GUARD(&card->event_list_mutex);
370
QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) {
371
DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type));
372
switch (event->p.gen.type) {
373
case EMUL_RESPONSE_APDU:
374
ccid_card_send_apdu_to_guest(&card->base, event->p.data.data,
377
case EMUL_READER_INSERT:
378
ccid_card_ccid_attach(&card->base);
380
case EMUL_READER_REMOVE:
381
ccid_card_ccid_detach(&card->base);
383
case EMUL_CARD_INSERT:
384
assert(event->p.data.len <= MAX_ATR_SIZE);
385
card->atr_length = event->p.data.len;
386
memcpy(card->atr, event->p.data.data, card->atr_length);
387
ccid_card_card_inserted(&card->base);
389
case EMUL_CARD_REMOVE:
390
ccid_card_card_removed(&card->base);
393
ccid_card_card_error(&card->base, event->p.error.code);
396
DPRINTF(card, 2, "unexpected event\n");
401
QSIMPLEQ_INIT(&card->event_list);
404
static int init_event_notifier(EmulatedState *card, Error **errp)
406
if (event_notifier_init(&card->notifier, false) < 0) {
407
error_setg(errp, "ccid-card-emul: event notifier creation failed");
410
event_notifier_set_handler(&card->notifier, card_event_handler);
414
static void clean_event_notifier(EmulatedState *card)
416
event_notifier_set_handler(&card->notifier, NULL);
417
event_notifier_cleanup(&card->notifier);
420
#define CERTIFICATES_DEFAULT_DB "/etc/pki/nssdb"
421
#define CERTIFICATES_ARGS_TEMPLATE\
422
"db=\"%s\" use_hw=no soft=(,Virtual Reader,CAC,,%s,%s,%s)"
424
static int wrap_vcard_emul_init(VCardEmulOptions *options)
427
static int options_was_null;
430
if ((options == NULL) != options_was_null) {
431
printf("%s: warning: running emulated with certificates"
432
" and emulated side by side is not supported\n",
434
return VCARD_EMUL_FAIL;
436
vcard_emul_replay_insertion_events();
437
return VCARD_EMUL_OK;
439
options_was_null = (options == NULL);
441
return vcard_emul_init(options);
444
static int emulated_initialize_vcard_from_certificates(EmulatedState *card)
447
VCardEmulOptions *options = NULL;
449
snprintf(emul_args, sizeof(emul_args) - 1, CERTIFICATES_ARGS_TEMPLATE,
450
card->db ? card->db : CERTIFICATES_DEFAULT_DB,
451
card->cert1, card->cert2, card->cert3);
452
options = vcard_emul_options(emul_args);
453
if (options == NULL) {
454
printf("%s: warning: not using certificates due to"
455
" initialization error\n", __func__);
457
return wrap_vcard_emul_init(options);
460
typedef struct EnumTable {
465
static const EnumTable backend_enum_table[] = {
466
{BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED},
467
{BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES},
471
static uint32_t parse_enumeration(char *str,
472
const EnumTable *table, uint32_t not_found_value)
474
uint32_t ret = not_found_value;
479
while (table->name != NULL) {
480
if (strcmp(table->name, str) == 0) {
489
static void emulated_realize(CCIDCardState *base, Error **errp)
491
EmulatedState *card = EMULATED_CCID_CARD(base);
493
const EnumTable *ptable;
495
QSIMPLEQ_INIT(&card->event_list);
496
QSIMPLEQ_INIT(&card->guest_apdu_list);
497
qemu_mutex_init(&card->event_list_mutex);
498
qemu_mutex_init(&card->vreader_mutex);
499
qemu_mutex_init(&card->handle_apdu_mutex);
500
qemu_cond_init(&card->handle_apdu_cond);
502
card->quit_apdu_thread = 0;
503
if (init_event_notifier(card, errp) < 0) {
508
if (card->backend_str) {
509
card->backend = parse_enumeration(card->backend_str,
510
backend_enum_table, 0);
513
if (card->backend == 0) {
514
error_setg(errp, "backend must be one of:");
515
for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) {
516
error_append_hint(errp, "%s\n", ptable->name);
522
if (card->backend == BACKEND_CERTIFICATES) {
523
if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) {
524
ret = emulated_initialize_vcard_from_certificates(card);
526
error_setg(errp, "%s: you must provide all three certs for"
527
" certificates backend", TYPE_EMULATED_CCID);
531
if (card->backend != BACKEND_NSS_EMULATED) {
532
error_setg(errp, "%s: bad backend specified. The options are:%s"
533
" (default), %s.", TYPE_EMULATED_CCID,
534
BACKEND_NSS_EMULATED_NAME, BACKEND_CERTIFICATES_NAME);
537
if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) {
538
error_setg(errp, "%s: unexpected cert parameters to nss emulated "
539
"backend", TYPE_EMULATED_CCID);
543
ret = wrap_vcard_emul_init(NULL);
545
if (ret != VCARD_EMUL_OK) {
546
error_setg(errp, "%s: failed to initialize vcard", TYPE_EMULATED_CCID);
549
qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread,
550
card, QEMU_THREAD_JOINABLE);
551
qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread,
552
card, QEMU_THREAD_JOINABLE);
557
clean_event_notifier(card);
559
qemu_cond_destroy(&card->handle_apdu_cond);
560
qemu_mutex_destroy(&card->handle_apdu_mutex);
561
qemu_mutex_destroy(&card->vreader_mutex);
562
qemu_mutex_destroy(&card->event_list_mutex);
565
static void emulated_unrealize(CCIDCardState *base)
567
EmulatedState *card = EMULATED_CCID_CARD(base);
568
VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL);
570
vevent_queue_vevent(vevent);
571
qemu_thread_join(&card->event_thread_id);
573
card->quit_apdu_thread = 1;
574
qemu_cond_signal(&card->handle_apdu_cond);
575
qemu_thread_join(&card->apdu_thread_id);
577
clean_event_notifier(card);
579
qemu_cond_destroy(&card->handle_apdu_cond);
580
qemu_mutex_destroy(&card->handle_apdu_mutex);
581
qemu_mutex_destroy(&card->vreader_mutex);
582
qemu_mutex_destroy(&card->event_list_mutex);
585
static Property emulated_card_properties[] = {
586
DEFINE_PROP_STRING("backend", EmulatedState, backend_str),
587
DEFINE_PROP_STRING("cert1", EmulatedState, cert1),
588
DEFINE_PROP_STRING("cert2", EmulatedState, cert2),
589
DEFINE_PROP_STRING("cert3", EmulatedState, cert3),
590
DEFINE_PROP_STRING("db", EmulatedState, db),
591
DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0),
592
DEFINE_PROP_END_OF_LIST(),
595
static void emulated_class_initfn(ObjectClass *klass, void *data)
597
DeviceClass *dc = DEVICE_CLASS(klass);
598
CCIDCardClass *cc = CCID_CARD_CLASS(klass);
600
cc->realize = emulated_realize;
601
cc->unrealize = emulated_unrealize;
602
cc->get_atr = emulated_get_atr;
603
cc->apdu_from_guest = emulated_apdu_from_guest;
604
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
605
dc->desc = "emulated smartcard";
606
device_class_set_props(dc, emulated_card_properties);
609
static const TypeInfo emulated_card_info = {
610
.name = TYPE_EMULATED_CCID,
611
.parent = TYPE_CCID_CARD,
612
.instance_size = sizeof(EmulatedState),
613
.class_init = emulated_class_initfn,
615
module_obj(TYPE_EMULATED_CCID);
618
static void ccid_card_emulated_register_types(void)
620
type_register_static(&emulated_card_info);
623
type_init(ccid_card_emulated_register_types)