1 /* 2 * CCID Card Device. Emulated card. 3 * 4 * Copyright (c) 2011 Red Hat. 5 * Written by Alon Levy. 6 * 7 * This code is licensed under the GNU LGPL, version 2 or later. 8 */ 9 10 /* 11 * It can be used to provide access to the local hardware in a non exclusive 12 * way, or it can use certificates. It requires the usb-ccid bus. 13 * 14 * Usage 1: standard, mirror hardware reader+card: 15 * qemu .. -usb -device usb-ccid -device ccid-card-emulated 16 * 17 * Usage 2: use certificates, no hardware required 18 * one time: create the certificates: 19 * for i in 1 2 3; do 20 * certutil -d /etc/pki/nssdb -x -t "CT,CT,CT" -S -s "CN=user$i" -n user$i 21 * done 22 * qemu .. -usb -device usb-ccid \ 23 * -device ccid-card-emulated,cert1=user1,cert2=user2,cert3=user3 24 * 25 * If you use a non default db for the certificates you can specify it using 26 * the db parameter. 27 */ 28 29 #include "qemu/osdep.h" 30 #include <libcacard.h> 31 32 #include "qemu/thread.h" 33 #include "qemu/lockable.h" 34 #include "qemu/main-loop.h" 35 #include "qemu/module.h" 36 #include "ccid.h" 37 #include "hw/qdev-properties.h" 38 #include "qapi/error.h" 39 #include "qom/object.h" 40 41 #define DPRINTF(card, lvl, fmt, ...) \ 42 do {\ 43 if (lvl <= card->debug) {\ 44 printf("ccid-card-emul: %s: " fmt , __func__, ## __VA_ARGS__);\ 45 } \ 46 } while (0) 47 48 49 #define TYPE_EMULATED_CCID "ccid-card-emulated" 50 typedef struct EmulatedState EmulatedState; 51 DECLARE_INSTANCE_CHECKER(EmulatedState, EMULATED_CCID_CARD, 52 TYPE_EMULATED_CCID) 53 54 #define BACKEND_NSS_EMULATED_NAME "nss-emulated" 55 #define BACKEND_CERTIFICATES_NAME "certificates" 56 57 enum { 58 BACKEND_NSS_EMULATED = 1, 59 BACKEND_CERTIFICATES 60 }; 61 62 #define DEFAULT_BACKEND BACKEND_NSS_EMULATED 63 64 65 enum { 66 EMUL_READER_INSERT = 0, 67 EMUL_READER_REMOVE, 68 EMUL_CARD_INSERT, 69 EMUL_CARD_REMOVE, 70 EMUL_GUEST_APDU, 71 EMUL_RESPONSE_APDU, 72 EMUL_ERROR, 73 }; 74 75 static const char *emul_event_to_string(uint32_t emul_event) 76 { 77 switch (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"; 86 case EMUL_GUEST_APDU: 87 return "EMUL_GUEST_APDU"; 88 case EMUL_RESPONSE_APDU: 89 return "EMUL_RESPONSE_APDU"; 90 case EMUL_ERROR: 91 return "EMUL_ERROR"; 92 } 93 return "UNKNOWN"; 94 } 95 96 typedef struct EmulEvent { 97 QSIMPLEQ_ENTRY(EmulEvent) entry; 98 union { 99 struct { 100 uint32_t type; 101 } gen; 102 struct { 103 uint32_t type; 104 uint64_t code; 105 } error; 106 struct { 107 uint32_t type; 108 uint32_t len; 109 uint8_t data[]; 110 } data; 111 } p; 112 } EmulEvent; 113 114 #define MAX_ATR_SIZE 40 115 struct EmulatedState { 116 CCIDCardState base; 117 uint8_t debug; 118 char *backend_str; 119 uint32_t backend; 120 char *cert1; 121 char *cert2; 122 char *cert3; 123 char *db; 124 uint8_t atr[MAX_ATR_SIZE]; 125 uint8_t atr_length; 126 QSIMPLEQ_HEAD(, EmulEvent) event_list; 127 QemuMutex event_list_mutex; 128 QemuThread event_thread_id; 129 VReader *reader; 130 QSIMPLEQ_HEAD(, EmulEvent) guest_apdu_list; 131 QemuMutex vreader_mutex; /* and guest_apdu_list mutex */ 132 QemuMutex handle_apdu_mutex; 133 QemuCond handle_apdu_cond; 134 EventNotifier notifier; 135 int quit_apdu_thread; 136 QemuThread apdu_thread_id; 137 }; 138 139 static void emulated_apdu_from_guest(CCIDCardState *base, 140 const uint8_t *apdu, uint32_t len) 141 { 142 EmulatedState *card = EMULATED_CCID_CARD(base); 143 EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len); 144 145 assert(event); 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); 155 } 156 157 static const uint8_t *emulated_get_atr(CCIDCardState *base, uint32_t *len) 158 { 159 EmulatedState *card = EMULATED_CCID_CARD(base); 160 161 *len = card->atr_length; 162 return card->atr; 163 } 164 165 static void emulated_push_event(EmulatedState *card, EmulEvent *event) 166 { 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); 171 } 172 173 static void emulated_push_type(EmulatedState *card, uint32_t type) 174 { 175 EmulEvent *event = g_new(EmulEvent, 1); 176 177 assert(event); 178 event->p.gen.type = type; 179 emulated_push_event(card, event); 180 } 181 182 static void emulated_push_error(EmulatedState *card, uint64_t code) 183 { 184 EmulEvent *event = g_new(EmulEvent, 1); 185 186 assert(event); 187 event->p.error.type = EMUL_ERROR; 188 event->p.error.code = code; 189 emulated_push_event(card, event); 190 } 191 192 static void emulated_push_data_type(EmulatedState *card, uint32_t type, 193 const uint8_t *data, uint32_t len) 194 { 195 EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len); 196 197 assert(event); 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); 202 } 203 204 static void emulated_push_reader_insert(EmulatedState *card) 205 { 206 emulated_push_type(card, EMUL_READER_INSERT); 207 } 208 209 static void emulated_push_reader_remove(EmulatedState *card) 210 { 211 emulated_push_type(card, EMUL_READER_REMOVE); 212 } 213 214 static void emulated_push_card_insert(EmulatedState *card, 215 const uint8_t *atr, uint32_t len) 216 { 217 emulated_push_data_type(card, EMUL_CARD_INSERT, atr, len); 218 } 219 220 static void emulated_push_card_remove(EmulatedState *card) 221 { 222 emulated_push_type(card, EMUL_CARD_REMOVE); 223 } 224 225 static void emulated_push_response_apdu(EmulatedState *card, 226 const uint8_t *apdu, uint32_t len) 227 { 228 emulated_push_data_type(card, EMUL_RESPONSE_APDU, apdu, len); 229 } 230 231 #define APDU_BUF_SIZE 270 232 static void *handle_apdu_thread(void* arg) 233 { 234 EmulatedState *card = arg; 235 uint8_t recv_data[APDU_BUF_SIZE]; 236 int recv_len; 237 VReaderStatus reader_status; 238 EmulEvent *event; 239 240 while (1) { 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; /* debugging */ 246 break; 247 } 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((unsigned long)event > 1000); 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"); 255 g_free(event); 256 continue; 257 } 258 if (card->reader == NULL) { 259 DPRINTF(card, 1, "reader is NULL\n"); 260 g_free(event); 261 continue; 262 } 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); 270 } else { 271 emulated_push_error(card, reader_status); 272 } 273 g_free(event); 274 } 275 } 276 } 277 return NULL; 278 } 279 280 static void *event_thread(void *arg) 281 { 282 int atr_len = MAX_ATR_SIZE; 283 uint8_t atr[MAX_ATR_SIZE]; 284 VEvent *event = NULL; 285 EmulatedState *card = arg; 286 287 while (1) { 288 const char *reader_name; 289 290 event = vevent_wait_next_vevent(); 291 if (event == NULL || event->type == VEVENT_LAST) { 292 break; 293 } 294 if (event->type != VEVENT_READER_INSERT) { 295 if (card->reader == NULL && event->reader != NULL) { 296 /* Happens after device_add followed by card remove or insert. 297 * XXX: create synthetic add_reader events if vcard_emul_init 298 * already called, which happens if device_del and device_add 299 * are called */ 300 card->reader = vreader_reference(event->reader); 301 } else { 302 if (event->reader != card->reader) { 303 fprintf(stderr, 304 "ERROR: wrong reader: quitting event_thread\n"); 305 break; 306 } 307 } 308 } 309 switch (event->type) { 310 case VEVENT_READER_INSERT: 311 /* TODO: take a specific reader. i.e. track which reader 312 * we are seeing here, check it is the one we want (the first, 313 * or by a particular name), and ignore if we don't want it. 314 */ 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); 323 } 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); 329 break; 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); 335 card->reader = NULL; 336 qemu_mutex_unlock(&card->vreader_mutex); 337 emulated_push_reader_remove(card); 338 break; 339 case VEVENT_CARD_INSERT: 340 /* get the ATR (intended as a response to a power on from the 341 * reader */ 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); 347 break; 348 case VEVENT_CARD_REMOVE: 349 DPRINTF(card, 2, " CARD REMOVE\n"); 350 emulated_push_card_remove(card); 351 break; 352 case VEVENT_LAST: /* quit */ 353 vevent_delete(event); 354 return NULL; 355 default: 356 break; 357 } 358 vevent_delete(event); 359 } 360 return NULL; 361 } 362 363 static void card_event_handler(EventNotifier *notifier) 364 { 365 EmulatedState *card = container_of(notifier, EmulatedState, notifier); 366 EmulEvent *event, *next; 367 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, 375 event->p.data.len); 376 break; 377 case EMUL_READER_INSERT: 378 ccid_card_ccid_attach(&card->base); 379 break; 380 case EMUL_READER_REMOVE: 381 ccid_card_ccid_detach(&card->base); 382 break; 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); 388 break; 389 case EMUL_CARD_REMOVE: 390 ccid_card_card_removed(&card->base); 391 break; 392 case EMUL_ERROR: 393 ccid_card_card_error(&card->base, event->p.error.code); 394 break; 395 default: 396 DPRINTF(card, 2, "unexpected event\n"); 397 break; 398 } 399 g_free(event); 400 } 401 QSIMPLEQ_INIT(&card->event_list); 402 } 403 404 static int init_event_notifier(EmulatedState *card, Error **errp) 405 { 406 if (event_notifier_init(&card->notifier, false) < 0) { 407 error_setg(errp, "ccid-card-emul: event notifier creation failed"); 408 return -1; 409 } 410 event_notifier_set_handler(&card->notifier, card_event_handler); 411 return 0; 412 } 413 414 static void clean_event_notifier(EmulatedState *card) 415 { 416 event_notifier_set_handler(&card->notifier, NULL); 417 event_notifier_cleanup(&card->notifier); 418 } 419 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)" 423 424 static int wrap_vcard_emul_init(VCardEmulOptions *options) 425 { 426 static int called; 427 static int options_was_null; 428 429 if (called) { 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", 433 __func__); 434 return VCARD_EMUL_FAIL; 435 } 436 vcard_emul_replay_insertion_events(); 437 return VCARD_EMUL_OK; 438 } 439 options_was_null = (options == NULL); 440 called = 1; 441 return vcard_emul_init(options); 442 } 443 444 static int emulated_initialize_vcard_from_certificates(EmulatedState *card) 445 { 446 char emul_args[200]; 447 VCardEmulOptions *options = NULL; 448 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__); 456 } 457 return wrap_vcard_emul_init(options); 458 } 459 460 typedef struct EnumTable { 461 const char *name; 462 uint32_t value; 463 } EnumTable; 464 465 static const EnumTable backend_enum_table[] = { 466 {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED}, 467 {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES}, 468 {NULL, 0}, 469 }; 470 471 static uint32_t parse_enumeration(char *str, 472 const EnumTable *table, uint32_t not_found_value) 473 { 474 uint32_t ret = not_found_value; 475 476 if (str == NULL) 477 return 0; 478 479 while (table->name != NULL) { 480 if (strcmp(table->name, str) == 0) { 481 ret = table->value; 482 break; 483 } 484 table++; 485 } 486 return ret; 487 } 488 489 static void emulated_realize(CCIDCardState *base, Error **errp) 490 { 491 EmulatedState *card = EMULATED_CCID_CARD(base); 492 VCardEmulError ret; 493 const EnumTable *ptable; 494 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); 501 card->reader = NULL; 502 card->quit_apdu_thread = 0; 503 if (init_event_notifier(card, errp) < 0) { 504 goto out1; 505 } 506 507 card->backend = 0; 508 if (card->backend_str) { 509 card->backend = parse_enumeration(card->backend_str, 510 backend_enum_table, 0); 511 } 512 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); 517 } 518 goto out2; 519 } 520 521 /* TODO: a passthru backened that works on local machine. third card type?*/ 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); 525 } else { 526 error_setg(errp, "%s: you must provide all three certs for" 527 " certificates backend", TYPE_EMULATED_CCID); 528 goto out2; 529 } 530 } else { 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); 535 goto out2; 536 } 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); 540 goto out2; 541 } 542 /* default to mirroring the local hardware readers */ 543 ret = wrap_vcard_emul_init(NULL); 544 } 545 if (ret != VCARD_EMUL_OK) { 546 error_setg(errp, "%s: failed to initialize vcard", TYPE_EMULATED_CCID); 547 goto out2; 548 } 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); 553 554 return; 555 556 out2: 557 clean_event_notifier(card); 558 out1: 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); 563 } 564 565 static void emulated_unrealize(CCIDCardState *base) 566 { 567 EmulatedState *card = EMULATED_CCID_CARD(base); 568 VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL); 569 570 vevent_queue_vevent(vevent); /* stop vevent thread */ 571 qemu_thread_join(&card->event_thread_id); 572 573 card->quit_apdu_thread = 1; /* stop handle_apdu thread */ 574 qemu_cond_signal(&card->handle_apdu_cond); 575 qemu_thread_join(&card->apdu_thread_id); 576 577 clean_event_notifier(card); 578 /* threads exited, can destroy all condvars/mutexes */ 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); 583 } 584 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(), 593 }; 594 595 static void emulated_class_initfn(ObjectClass *klass, void *data) 596 { 597 DeviceClass *dc = DEVICE_CLASS(klass); 598 CCIDCardClass *cc = CCID_CARD_CLASS(klass); 599 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); 607 } 608 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, 614 }; 615 616 static void ccid_card_emulated_register_types(void) 617 { 618 type_register_static(&emulated_card_info); 619 } 620 621 type_init(ccid_card_emulated_register_types) 622