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