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