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/main-loop.h" 34 #include "ccid.h" 35 #include "qapi/error.h" 36 37 #define DPRINTF(card, lvl, fmt, ...) \ 38 do {\ 39 if (lvl <= card->debug) {\ 40 printf("ccid-card-emul: %s: " fmt , __func__, ## __VA_ARGS__);\ 41 } \ 42 } while (0) 43 44 45 #define TYPE_EMULATED_CCID "ccid-card-emulated" 46 #define EMULATED_CCID_CARD(obj) \ 47 OBJECT_CHECK(EmulatedState, (obj), TYPE_EMULATED_CCID) 48 49 #define BACKEND_NSS_EMULATED_NAME "nss-emulated" 50 #define BACKEND_CERTIFICATES_NAME "certificates" 51 52 enum { 53 BACKEND_NSS_EMULATED = 1, 54 BACKEND_CERTIFICATES 55 }; 56 57 #define DEFAULT_BACKEND BACKEND_NSS_EMULATED 58 59 typedef struct EmulatedState EmulatedState; 60 61 enum { 62 EMUL_READER_INSERT = 0, 63 EMUL_READER_REMOVE, 64 EMUL_CARD_INSERT, 65 EMUL_CARD_REMOVE, 66 EMUL_GUEST_APDU, 67 EMUL_RESPONSE_APDU, 68 EMUL_ERROR, 69 }; 70 71 static const char *emul_event_to_string(uint32_t emul_event) 72 { 73 switch (emul_event) { 74 case EMUL_READER_INSERT: 75 return "EMUL_READER_INSERT"; 76 case EMUL_READER_REMOVE: 77 return "EMUL_READER_REMOVE"; 78 case EMUL_CARD_INSERT: 79 return "EMUL_CARD_INSERT"; 80 case EMUL_CARD_REMOVE: 81 return "EMUL_CARD_REMOVE"; 82 case EMUL_GUEST_APDU: 83 return "EMUL_GUEST_APDU"; 84 case EMUL_RESPONSE_APDU: 85 return "EMUL_RESPONSE_APDU"; 86 case EMUL_ERROR: 87 return "EMUL_ERROR"; 88 } 89 return "UNKNOWN"; 90 } 91 92 typedef struct EmulEvent { 93 QSIMPLEQ_ENTRY(EmulEvent) entry; 94 union { 95 struct { 96 uint32_t type; 97 } gen; 98 struct { 99 uint32_t type; 100 uint64_t code; 101 } error; 102 struct { 103 uint32_t type; 104 uint32_t len; 105 uint8_t data[]; 106 } data; 107 } p; 108 } EmulEvent; 109 110 #define MAX_ATR_SIZE 40 111 struct EmulatedState { 112 CCIDCardState base; 113 uint8_t debug; 114 char *backend_str; 115 uint32_t backend; 116 char *cert1; 117 char *cert2; 118 char *cert3; 119 char *db; 120 uint8_t atr[MAX_ATR_SIZE]; 121 uint8_t atr_length; 122 QSIMPLEQ_HEAD(event_list, EmulEvent) event_list; 123 QemuMutex event_list_mutex; 124 QemuThread event_thread_id; 125 VReader *reader; 126 QSIMPLEQ_HEAD(guest_apdu_list, EmulEvent) guest_apdu_list; 127 QemuMutex vreader_mutex; /* and guest_apdu_list mutex */ 128 QemuMutex handle_apdu_mutex; 129 QemuCond handle_apdu_cond; 130 EventNotifier notifier; 131 int quit_apdu_thread; 132 QemuThread apdu_thread_id; 133 }; 134 135 static void emulated_apdu_from_guest(CCIDCardState *base, 136 const uint8_t *apdu, uint32_t len) 137 { 138 EmulatedState *card = EMULATED_CCID_CARD(base); 139 EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len); 140 141 assert(event); 142 event->p.data.type = EMUL_GUEST_APDU; 143 event->p.data.len = len; 144 memcpy(event->p.data.data, apdu, len); 145 qemu_mutex_lock(&card->vreader_mutex); 146 QSIMPLEQ_INSERT_TAIL(&card->guest_apdu_list, event, entry); 147 qemu_mutex_unlock(&card->vreader_mutex); 148 qemu_mutex_lock(&card->handle_apdu_mutex); 149 qemu_cond_signal(&card->handle_apdu_cond); 150 qemu_mutex_unlock(&card->handle_apdu_mutex); 151 } 152 153 static const uint8_t *emulated_get_atr(CCIDCardState *base, uint32_t *len) 154 { 155 EmulatedState *card = EMULATED_CCID_CARD(base); 156 157 *len = card->atr_length; 158 return card->atr; 159 } 160 161 static void emulated_push_event(EmulatedState *card, EmulEvent *event) 162 { 163 qemu_mutex_lock(&card->event_list_mutex); 164 QSIMPLEQ_INSERT_TAIL(&(card->event_list), event, entry); 165 qemu_mutex_unlock(&card->event_list_mutex); 166 event_notifier_set(&card->notifier); 167 } 168 169 static void emulated_push_type(EmulatedState *card, uint32_t type) 170 { 171 EmulEvent *event = g_new(EmulEvent, 1); 172 173 assert(event); 174 event->p.gen.type = type; 175 emulated_push_event(card, event); 176 } 177 178 static void emulated_push_error(EmulatedState *card, uint64_t code) 179 { 180 EmulEvent *event = g_new(EmulEvent, 1); 181 182 assert(event); 183 event->p.error.type = EMUL_ERROR; 184 event->p.error.code = code; 185 emulated_push_event(card, event); 186 } 187 188 static void emulated_push_data_type(EmulatedState *card, uint32_t type, 189 const uint8_t *data, uint32_t len) 190 { 191 EmulEvent *event = (EmulEvent *)g_malloc(sizeof(EmulEvent) + len); 192 193 assert(event); 194 event->p.data.type = type; 195 event->p.data.len = len; 196 memcpy(event->p.data.data, data, len); 197 emulated_push_event(card, event); 198 } 199 200 static void emulated_push_reader_insert(EmulatedState *card) 201 { 202 emulated_push_type(card, EMUL_READER_INSERT); 203 } 204 205 static void emulated_push_reader_remove(EmulatedState *card) 206 { 207 emulated_push_type(card, EMUL_READER_REMOVE); 208 } 209 210 static void emulated_push_card_insert(EmulatedState *card, 211 const uint8_t *atr, uint32_t len) 212 { 213 emulated_push_data_type(card, EMUL_CARD_INSERT, atr, len); 214 } 215 216 static void emulated_push_card_remove(EmulatedState *card) 217 { 218 emulated_push_type(card, EMUL_CARD_REMOVE); 219 } 220 221 static void emulated_push_response_apdu(EmulatedState *card, 222 const uint8_t *apdu, uint32_t len) 223 { 224 emulated_push_data_type(card, EMUL_RESPONSE_APDU, apdu, len); 225 } 226 227 #define APDU_BUF_SIZE 270 228 static void *handle_apdu_thread(void* arg) 229 { 230 EmulatedState *card = arg; 231 uint8_t recv_data[APDU_BUF_SIZE]; 232 int recv_len; 233 VReaderStatus reader_status; 234 EmulEvent *event; 235 236 while (1) { 237 qemu_mutex_lock(&card->handle_apdu_mutex); 238 qemu_cond_wait(&card->handle_apdu_cond, &card->handle_apdu_mutex); 239 qemu_mutex_unlock(&card->handle_apdu_mutex); 240 if (card->quit_apdu_thread) { 241 card->quit_apdu_thread = 0; /* debugging */ 242 break; 243 } 244 qemu_mutex_lock(&card->vreader_mutex); 245 while (!QSIMPLEQ_EMPTY(&card->guest_apdu_list)) { 246 event = QSIMPLEQ_FIRST(&card->guest_apdu_list); 247 assert((unsigned long)event > 1000); 248 QSIMPLEQ_REMOVE_HEAD(&card->guest_apdu_list, entry); 249 if (event->p.data.type != EMUL_GUEST_APDU) { 250 DPRINTF(card, 1, "unexpected message in handle_apdu_thread\n"); 251 g_free(event); 252 continue; 253 } 254 if (card->reader == NULL) { 255 DPRINTF(card, 1, "reader is NULL\n"); 256 g_free(event); 257 continue; 258 } 259 recv_len = sizeof(recv_data); 260 reader_status = vreader_xfr_bytes(card->reader, 261 event->p.data.data, event->p.data.len, 262 recv_data, &recv_len); 263 DPRINTF(card, 2, "got back apdu of length %d\n", recv_len); 264 if (reader_status == VREADER_OK) { 265 emulated_push_response_apdu(card, recv_data, recv_len); 266 } else { 267 emulated_push_error(card, reader_status); 268 } 269 g_free(event); 270 } 271 qemu_mutex_unlock(&card->vreader_mutex); 272 } 273 return NULL; 274 } 275 276 static void *event_thread(void *arg) 277 { 278 int atr_len = MAX_ATR_SIZE; 279 uint8_t atr[MAX_ATR_SIZE]; 280 VEvent *event = NULL; 281 EmulatedState *card = arg; 282 283 while (1) { 284 const char *reader_name; 285 286 event = vevent_wait_next_vevent(); 287 if (event == NULL || event->type == VEVENT_LAST) { 288 break; 289 } 290 if (event->type != VEVENT_READER_INSERT) { 291 if (card->reader == NULL && event->reader != NULL) { 292 /* Happens after device_add followed by card remove or insert. 293 * XXX: create synthetic add_reader events if vcard_emul_init 294 * already called, which happens if device_del and device_add 295 * are called */ 296 card->reader = vreader_reference(event->reader); 297 } else { 298 if (event->reader != card->reader) { 299 fprintf(stderr, 300 "ERROR: wrong reader: quiting event_thread\n"); 301 break; 302 } 303 } 304 } 305 switch (event->type) { 306 case VEVENT_READER_INSERT: 307 /* TODO: take a specific reader. i.e. track which reader 308 * we are seeing here, check it is the one we want (the first, 309 * or by a particular name), and ignore if we don't want it. 310 */ 311 reader_name = vreader_get_name(event->reader); 312 if (card->reader != NULL) { 313 DPRINTF(card, 2, "READER INSERT - replacing %s with %s\n", 314 vreader_get_name(card->reader), reader_name); 315 qemu_mutex_lock(&card->vreader_mutex); 316 vreader_free(card->reader); 317 qemu_mutex_unlock(&card->vreader_mutex); 318 emulated_push_reader_remove(card); 319 } 320 qemu_mutex_lock(&card->vreader_mutex); 321 DPRINTF(card, 2, "READER INSERT %s\n", reader_name); 322 card->reader = vreader_reference(event->reader); 323 qemu_mutex_unlock(&card->vreader_mutex); 324 emulated_push_reader_insert(card); 325 break; 326 case VEVENT_READER_REMOVE: 327 DPRINTF(card, 2, " READER REMOVE: %s\n", 328 vreader_get_name(event->reader)); 329 qemu_mutex_lock(&card->vreader_mutex); 330 vreader_free(card->reader); 331 card->reader = NULL; 332 qemu_mutex_unlock(&card->vreader_mutex); 333 emulated_push_reader_remove(card); 334 break; 335 case VEVENT_CARD_INSERT: 336 /* get the ATR (intended as a response to a power on from the 337 * reader */ 338 atr_len = MAX_ATR_SIZE; 339 vreader_power_on(event->reader, atr, &atr_len); 340 card->atr_length = (uint8_t)atr_len; 341 DPRINTF(card, 2, " CARD INSERT\n"); 342 emulated_push_card_insert(card, atr, atr_len); 343 break; 344 case VEVENT_CARD_REMOVE: 345 DPRINTF(card, 2, " CARD REMOVE\n"); 346 emulated_push_card_remove(card); 347 break; 348 case VEVENT_LAST: /* quit */ 349 vevent_delete(event); 350 return NULL; 351 break; 352 default: 353 break; 354 } 355 vevent_delete(event); 356 } 357 return NULL; 358 } 359 360 static void card_event_handler(EventNotifier *notifier) 361 { 362 EmulatedState *card = container_of(notifier, EmulatedState, notifier); 363 EmulEvent *event, *next; 364 365 event_notifier_test_and_clear(&card->notifier); 366 qemu_mutex_lock(&card->event_list_mutex); 367 QSIMPLEQ_FOREACH_SAFE(event, &card->event_list, entry, next) { 368 DPRINTF(card, 2, "event %s\n", emul_event_to_string(event->p.gen.type)); 369 switch (event->p.gen.type) { 370 case EMUL_RESPONSE_APDU: 371 ccid_card_send_apdu_to_guest(&card->base, event->p.data.data, 372 event->p.data.len); 373 break; 374 case EMUL_READER_INSERT: 375 ccid_card_ccid_attach(&card->base); 376 break; 377 case EMUL_READER_REMOVE: 378 ccid_card_ccid_detach(&card->base); 379 break; 380 case EMUL_CARD_INSERT: 381 assert(event->p.data.len <= MAX_ATR_SIZE); 382 card->atr_length = event->p.data.len; 383 memcpy(card->atr, event->p.data.data, card->atr_length); 384 ccid_card_card_inserted(&card->base); 385 break; 386 case EMUL_CARD_REMOVE: 387 ccid_card_card_removed(&card->base); 388 break; 389 case EMUL_ERROR: 390 ccid_card_card_error(&card->base, event->p.error.code); 391 break; 392 default: 393 DPRINTF(card, 2, "unexpected event\n"); 394 break; 395 } 396 g_free(event); 397 } 398 QSIMPLEQ_INIT(&card->event_list); 399 qemu_mutex_unlock(&card->event_list_mutex); 400 } 401 402 static int init_event_notifier(EmulatedState *card, Error **errp) 403 { 404 if (event_notifier_init(&card->notifier, false) < 0) { 405 error_setg(errp, "ccid-card-emul: event notifier creation failed"); 406 return -1; 407 } 408 event_notifier_set_handler(&card->notifier, card_event_handler); 409 return 0; 410 } 411 412 #define CERTIFICATES_DEFAULT_DB "/etc/pki/nssdb" 413 #define CERTIFICATES_ARGS_TEMPLATE\ 414 "db=\"%s\" use_hw=no soft=(,Virtual Reader,CAC,,%s,%s,%s)" 415 416 static int wrap_vcard_emul_init(VCardEmulOptions *options) 417 { 418 static int called; 419 static int options_was_null; 420 421 if (called) { 422 if ((options == NULL) != options_was_null) { 423 printf("%s: warning: running emulated with certificates" 424 " and emulated side by side is not supported\n", 425 __func__); 426 return VCARD_EMUL_FAIL; 427 } 428 vcard_emul_replay_insertion_events(); 429 return VCARD_EMUL_OK; 430 } 431 options_was_null = (options == NULL); 432 called = 1; 433 return vcard_emul_init(options); 434 } 435 436 static int emulated_initialize_vcard_from_certificates(EmulatedState *card) 437 { 438 char emul_args[200]; 439 VCardEmulOptions *options = NULL; 440 441 snprintf(emul_args, sizeof(emul_args) - 1, CERTIFICATES_ARGS_TEMPLATE, 442 card->db ? card->db : CERTIFICATES_DEFAULT_DB, 443 card->cert1, card->cert2, card->cert3); 444 options = vcard_emul_options(emul_args); 445 if (options == NULL) { 446 printf("%s: warning: not using certificates due to" 447 " initialization error\n", __func__); 448 } 449 return wrap_vcard_emul_init(options); 450 } 451 452 typedef struct EnumTable { 453 const char *name; 454 uint32_t value; 455 } EnumTable; 456 457 static const EnumTable backend_enum_table[] = { 458 {BACKEND_NSS_EMULATED_NAME, BACKEND_NSS_EMULATED}, 459 {BACKEND_CERTIFICATES_NAME, BACKEND_CERTIFICATES}, 460 {NULL, 0}, 461 }; 462 463 static uint32_t parse_enumeration(char *str, 464 const EnumTable *table, uint32_t not_found_value) 465 { 466 uint32_t ret = not_found_value; 467 468 if (str == NULL) 469 return 0; 470 471 while (table->name != NULL) { 472 if (strcmp(table->name, str) == 0) { 473 ret = table->value; 474 break; 475 } 476 table++; 477 } 478 return ret; 479 } 480 481 static void emulated_realize(CCIDCardState *base, Error **errp) 482 { 483 EmulatedState *card = EMULATED_CCID_CARD(base); 484 VCardEmulError ret; 485 const EnumTable *ptable; 486 487 QSIMPLEQ_INIT(&card->event_list); 488 QSIMPLEQ_INIT(&card->guest_apdu_list); 489 qemu_mutex_init(&card->event_list_mutex); 490 qemu_mutex_init(&card->vreader_mutex); 491 qemu_mutex_init(&card->handle_apdu_mutex); 492 qemu_cond_init(&card->handle_apdu_cond); 493 card->reader = NULL; 494 card->quit_apdu_thread = 0; 495 if (init_event_notifier(card, errp) < 0) { 496 return; 497 } 498 499 card->backend = 0; 500 if (card->backend_str) { 501 card->backend = parse_enumeration(card->backend_str, 502 backend_enum_table, 0); 503 } 504 505 if (card->backend == 0) { 506 error_setg(errp, "backend must be one of:"); 507 for (ptable = backend_enum_table; ptable->name != NULL; ++ptable) { 508 error_append_hint(errp, "%s\n", ptable->name); 509 } 510 return; 511 } 512 513 /* TODO: a passthru backened that works on local machine. third card type?*/ 514 if (card->backend == BACKEND_CERTIFICATES) { 515 if (card->cert1 != NULL && card->cert2 != NULL && card->cert3 != NULL) { 516 ret = emulated_initialize_vcard_from_certificates(card); 517 } else { 518 error_setg(errp, "%s: you must provide all three certs for" 519 " certificates backend", TYPE_EMULATED_CCID); 520 return; 521 } 522 } else { 523 if (card->backend != BACKEND_NSS_EMULATED) { 524 error_setg(errp, "%s: bad backend specified. The options are:%s" 525 " (default), %s.", TYPE_EMULATED_CCID, 526 BACKEND_NSS_EMULATED_NAME, BACKEND_CERTIFICATES_NAME); 527 return; 528 } 529 if (card->cert1 != NULL || card->cert2 != NULL || card->cert3 != NULL) { 530 error_setg(errp, "%s: unexpected cert parameters to nss emulated " 531 "backend", TYPE_EMULATED_CCID); 532 return; 533 } 534 /* default to mirroring the local hardware readers */ 535 ret = wrap_vcard_emul_init(NULL); 536 } 537 if (ret != VCARD_EMUL_OK) { 538 error_setg(errp, "%s: failed to initialize vcard", TYPE_EMULATED_CCID); 539 return; 540 } 541 qemu_thread_create(&card->event_thread_id, "ccid/event", event_thread, 542 card, QEMU_THREAD_JOINABLE); 543 qemu_thread_create(&card->apdu_thread_id, "ccid/apdu", handle_apdu_thread, 544 card, QEMU_THREAD_JOINABLE); 545 } 546 547 static void emulated_unrealize(CCIDCardState *base, Error **errp) 548 { 549 EmulatedState *card = EMULATED_CCID_CARD(base); 550 VEvent *vevent = vevent_new(VEVENT_LAST, NULL, NULL); 551 552 vevent_queue_vevent(vevent); /* stop vevent thread */ 553 qemu_thread_join(&card->event_thread_id); 554 555 card->quit_apdu_thread = 1; /* stop handle_apdu thread */ 556 qemu_cond_signal(&card->handle_apdu_cond); 557 qemu_thread_join(&card->apdu_thread_id); 558 559 /* threads exited, can destroy all condvars/mutexes */ 560 qemu_cond_destroy(&card->handle_apdu_cond); 561 qemu_mutex_destroy(&card->handle_apdu_mutex); 562 qemu_mutex_destroy(&card->vreader_mutex); 563 qemu_mutex_destroy(&card->event_list_mutex); 564 } 565 566 static Property emulated_card_properties[] = { 567 DEFINE_PROP_STRING("backend", EmulatedState, backend_str), 568 DEFINE_PROP_STRING("cert1", EmulatedState, cert1), 569 DEFINE_PROP_STRING("cert2", EmulatedState, cert2), 570 DEFINE_PROP_STRING("cert3", EmulatedState, cert3), 571 DEFINE_PROP_STRING("db", EmulatedState, db), 572 DEFINE_PROP_UINT8("debug", EmulatedState, debug, 0), 573 DEFINE_PROP_END_OF_LIST(), 574 }; 575 576 static void emulated_class_initfn(ObjectClass *klass, void *data) 577 { 578 DeviceClass *dc = DEVICE_CLASS(klass); 579 CCIDCardClass *cc = CCID_CARD_CLASS(klass); 580 581 cc->realize = emulated_realize; 582 cc->unrealize = emulated_unrealize; 583 cc->get_atr = emulated_get_atr; 584 cc->apdu_from_guest = emulated_apdu_from_guest; 585 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 586 dc->desc = "emulated smartcard"; 587 dc->props = emulated_card_properties; 588 } 589 590 static const TypeInfo emulated_card_info = { 591 .name = TYPE_EMULATED_CCID, 592 .parent = TYPE_CCID_CARD, 593 .instance_size = sizeof(EmulatedState), 594 .class_init = emulated_class_initfn, 595 }; 596 597 static void ccid_card_emulated_register_types(void) 598 { 599 type_register_static(&emulated_card_info); 600 } 601 602 type_init(ccid_card_emulated_register_types) 603