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