Add qemu 2.4.0
[kvmfornfv.git] / qemu / libcacard / vreader.c
1 /*
2  * emulate the reader
3  *
4  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
5  * See the COPYING.LIB file in the top-level directory.
6  */
7
8 #ifdef G_LOG_DOMAIN
9 #undef G_LOG_DOMAIN
10 #endif
11 #define G_LOG_DOMAIN "libcacard"
12
13 #include "glib-compat.h"
14
15 #include <string.h>
16
17 #include "vcard.h"
18 #include "vcard_emul.h"
19 #include "card_7816.h"
20 #include "vreader.h"
21 #include "vevent.h"
22 #include "cac.h" /* just for debugging defines */
23
24 #define LIBCACARD_LOG_DOMAIN "libcacard"
25
26 struct VReaderStruct {
27     int    reference_count;
28     VCard *card;
29     char *name;
30     vreader_id_t id;
31     CompatGMutex lock;
32     VReaderEmul  *reader_private;
33     VReaderEmulFree reader_private_free;
34 };
35
36 /*
37  * Debug helpers
38  */
39
40 static const char *
41 apdu_ins_to_string(int ins)
42 {
43     switch (ins) {
44     case VCARD7816_INS_MANAGE_CHANNEL:
45         return "manage channel";
46     case VCARD7816_INS_EXTERNAL_AUTHENTICATE:
47         return "external authenticate";
48     case VCARD7816_INS_GET_CHALLENGE:
49         return "get challenge";
50     case VCARD7816_INS_INTERNAL_AUTHENTICATE:
51         return "internal authenticate";
52     case VCARD7816_INS_ERASE_BINARY:
53         return "erase binary";
54     case VCARD7816_INS_READ_BINARY:
55         return "read binary";
56     case VCARD7816_INS_WRITE_BINARY:
57         return "write binary";
58     case VCARD7816_INS_UPDATE_BINARY:
59         return "update binary";
60     case VCARD7816_INS_READ_RECORD:
61         return "read record";
62     case VCARD7816_INS_WRITE_RECORD:
63         return "write record";
64     case VCARD7816_INS_UPDATE_RECORD:
65         return "update record";
66     case VCARD7816_INS_APPEND_RECORD:
67         return "append record";
68     case VCARD7816_INS_ENVELOPE:
69         return "envelope";
70     case VCARD7816_INS_PUT_DATA:
71         return "put data";
72     case VCARD7816_INS_GET_DATA:
73         return "get data";
74     case VCARD7816_INS_SELECT_FILE:
75         return "select file";
76     case VCARD7816_INS_VERIFY:
77         return "verify";
78     case VCARD7816_INS_GET_RESPONSE:
79         return "get response";
80     case CAC_GET_PROPERTIES:
81         return "get properties";
82     case CAC_GET_ACR:
83         return "get acr";
84     case CAC_READ_BUFFER:
85         return "read buffer";
86     case CAC_UPDATE_BUFFER:
87         return "update buffer";
88     case CAC_SIGN_DECRYPT:
89         return "sign decrypt";
90     case CAC_GET_CERTIFICATE:
91         return "get certificate";
92     }
93     return "unknown";
94 }
95
96 /* manage locking */
97 static inline void
98 vreader_lock(VReader *reader)
99 {
100     g_mutex_lock(&reader->lock);
101 }
102
103 static inline void
104 vreader_unlock(VReader *reader)
105 {
106     g_mutex_unlock(&reader->lock);
107 }
108
109 /*
110  * vreader constructor
111  */
112 VReader *
113 vreader_new(const char *name, VReaderEmul *private,
114             VReaderEmulFree private_free)
115 {
116     VReader *reader;
117
118     reader = g_new(VReader, 1);
119     g_mutex_init(&reader->lock);
120     reader->reference_count = 1;
121     reader->name = g_strdup(name);
122     reader->card = NULL;
123     reader->id = (vreader_id_t)-1;
124     reader->reader_private = private;
125     reader->reader_private_free = private_free;
126     return reader;
127 }
128
129 /* get a reference */
130 VReader*
131 vreader_reference(VReader *reader)
132 {
133     if (reader == NULL) {
134         return NULL;
135     }
136     vreader_lock(reader);
137     reader->reference_count++;
138     vreader_unlock(reader);
139     return reader;
140 }
141
142 /* free a reference */
143 void
144 vreader_free(VReader *reader)
145 {
146     if (reader == NULL) {
147         return;
148     }
149     vreader_lock(reader);
150     if (reader->reference_count-- > 1) {
151         vreader_unlock(reader);
152         return;
153     }
154     vreader_unlock(reader);
155     g_mutex_clear(&reader->lock);
156     if (reader->card) {
157         vcard_free(reader->card);
158     }
159     g_free(reader->name);
160     if (reader->reader_private_free) {
161         reader->reader_private_free(reader->reader_private);
162     }
163     g_free(reader);
164 }
165
166 static VCard *
167 vreader_get_card(VReader *reader)
168 {
169     VCard *card;
170
171     vreader_lock(reader);
172     card = vcard_reference(reader->card);
173     vreader_unlock(reader);
174     return card;
175 }
176
177 VReaderStatus
178 vreader_card_is_present(VReader *reader)
179 {
180     VCard *card = vreader_get_card(reader);
181
182     if (card == NULL) {
183         return VREADER_NO_CARD;
184     }
185     vcard_free(card);
186     return VREADER_OK;
187 }
188
189 vreader_id_t
190 vreader_get_id(VReader *reader)
191 {
192     if (reader == NULL) {
193         return (vreader_id_t)-1;
194     }
195     return reader->id;
196 }
197
198 VReaderStatus
199 vreader_set_id(VReader *reader, vreader_id_t id)
200 {
201     if (reader == NULL) {
202         return VREADER_NO_CARD;
203     }
204     reader->id = id;
205     return VREADER_OK;
206 }
207
208 const char *
209 vreader_get_name(VReader *reader)
210 {
211     if (reader == NULL) {
212         return NULL;
213     }
214     return reader->name;
215 }
216
217 VReaderEmul *
218 vreader_get_private(VReader *reader)
219 {
220     return reader->reader_private;
221 }
222
223 static VReaderStatus
224 vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
225 {
226     VCard *card = vreader_get_card(reader);
227
228     if (card == NULL) {
229         return VREADER_NO_CARD;
230     }
231     /*
232      * clean up our state
233      */
234     vcard_reset(card, power);
235     if (atr) {
236         vcard_get_atr(card, atr, len);
237     }
238     vcard_free(card); /* free our reference */
239     return VREADER_OK;
240 }
241
242 VReaderStatus
243 vreader_power_on(VReader *reader, unsigned char *atr, int *len)
244 {
245     return vreader_reset(reader, VCARD_POWER_ON, atr, len);
246 }
247
248 VReaderStatus
249 vreader_power_off(VReader *reader)
250 {
251     return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
252 }
253
254
255 VReaderStatus
256 vreader_xfr_bytes(VReader *reader,
257                   unsigned char *send_buf, int send_buf_len,
258                   unsigned char *receive_buf, int *receive_buf_len)
259 {
260     VCardAPDU *apdu;
261     VCardResponse *response = NULL;
262     VCardStatus card_status;
263     unsigned short status;
264     VCard *card = vreader_get_card(reader);
265
266     if (card == NULL) {
267         return VREADER_NO_CARD;
268     }
269
270     apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
271     if (apdu == NULL) {
272         response = vcard_make_response(status);
273         card_status = VCARD_DONE;
274     } else {
275         g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
276               __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
277               apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
278         card_status = vcard_process_apdu(card, apdu, &response);
279         if (response) {
280             g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
281                   __func__, response->b_status, response->b_sw1,
282                   response->b_sw2, response->b_len, response->b_total_len);
283         }
284     }
285     assert(card_status == VCARD_DONE && response);
286     int size = MIN(*receive_buf_len, response->b_total_len);
287     memcpy(receive_buf, response->b_data, size);
288     *receive_buf_len = size;
289     vcard_response_delete(response);
290     vcard_apdu_delete(apdu);
291     vcard_free(card); /* free our reference */
292     return VREADER_OK;
293 }
294
295 struct VReaderListStruct {
296     VReaderListEntry *head;
297     VReaderListEntry *tail;
298 };
299
300 struct VReaderListEntryStruct {
301     VReaderListEntry *next;
302     VReaderListEntry *prev;
303     VReader *reader;
304 };
305
306
307 static VReaderListEntry *
308 vreader_list_entry_new(VReader *reader)
309 {
310     VReaderListEntry *new_reader_list_entry;
311
312     new_reader_list_entry = g_new0(VReaderListEntry, 1);
313     new_reader_list_entry->reader = vreader_reference(reader);
314     return new_reader_list_entry;
315 }
316
317 static void
318 vreader_list_entry_delete(VReaderListEntry *entry)
319 {
320     if (entry == NULL) {
321         return;
322     }
323     vreader_free(entry->reader);
324     g_free(entry);
325 }
326
327
328 static VReaderList *
329 vreader_list_new(void)
330 {
331     VReaderList *new_reader_list;
332
333     new_reader_list = g_new0(VReaderList, 1);
334     return new_reader_list;
335 }
336
337 void
338 vreader_list_delete(VReaderList *list)
339 {
340     VReaderListEntry *current_entry;
341     VReaderListEntry *next_entry;
342     for (current_entry = vreader_list_get_first(list); current_entry;
343          current_entry = next_entry) {
344         next_entry = vreader_list_get_next(current_entry);
345         vreader_list_entry_delete(current_entry);
346     }
347     g_free(list);
348 }
349
350
351 VReaderListEntry *
352 vreader_list_get_first(VReaderList *list)
353 {
354     return list ? list->head : NULL;
355 }
356
357 VReaderListEntry *
358 vreader_list_get_next(VReaderListEntry *current)
359 {
360     return current ? current->next : NULL;
361 }
362
363 VReader *
364 vreader_list_get_reader(VReaderListEntry *entry)
365 {
366     return entry ? vreader_reference(entry->reader) : NULL;
367 }
368
369 static void
370 vreader_queue(VReaderList *list, VReaderListEntry *entry)
371 {
372     if (entry == NULL) {
373         return;
374     }
375     entry->next = NULL;
376     entry->prev = list->tail;
377     if (list->head) {
378         list->tail->next = entry;
379     } else {
380         list->head = entry;
381     }
382     list->tail = entry;
383 }
384
385 static void
386 vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
387 {
388     if (entry == NULL) {
389         return;
390     }
391     if (entry->next == NULL) {
392         list->tail = entry->prev;
393     } else if (entry->prev == NULL) {
394         list->head = entry->next;
395     } else {
396         entry->prev->next = entry->next;
397         entry->next->prev = entry->prev;
398     }
399     if ((list->tail == NULL) || (list->head == NULL)) {
400         list->head = list->tail = NULL;
401     }
402     entry->next = entry->prev = NULL;
403 }
404
405 static VReaderList *vreader_list;
406 static CompatGMutex vreader_list_mutex;
407
408 static void
409 vreader_list_init(void)
410 {
411     vreader_list = vreader_list_new();
412 }
413
414 static void
415 vreader_list_lock(void)
416 {
417     g_mutex_lock(&vreader_list_mutex);
418 }
419
420 static void
421 vreader_list_unlock(void)
422 {
423     g_mutex_unlock(&vreader_list_mutex);
424 }
425
426 static VReaderList *
427 vreader_copy_list(VReaderList *list)
428 {
429     VReaderList *new_list;
430     VReaderListEntry *current_entry;
431
432     new_list = vreader_list_new();
433     if (new_list == NULL) {
434         return NULL;
435     }
436     for (current_entry = vreader_list_get_first(list); current_entry;
437          current_entry = vreader_list_get_next(current_entry)) {
438         VReader *reader = vreader_list_get_reader(current_entry);
439         VReaderListEntry *new_entry = vreader_list_entry_new(reader);
440
441         vreader_free(reader);
442         vreader_queue(new_list, new_entry);
443     }
444     return new_list;
445 }
446
447 VReaderList *
448 vreader_get_reader_list(void)
449 {
450     VReaderList *new_reader_list;
451
452     vreader_list_lock();
453     new_reader_list = vreader_copy_list(vreader_list);
454     vreader_list_unlock();
455     return new_reader_list;
456 }
457
458 VReader *
459 vreader_get_reader_by_id(vreader_id_t id)
460 {
461     VReader *reader = NULL;
462     VReaderListEntry *current_entry;
463
464     if (id == (vreader_id_t) -1) {
465         return NULL;
466     }
467
468     vreader_list_lock();
469     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
470             current_entry = vreader_list_get_next(current_entry)) {
471         VReader *creader = vreader_list_get_reader(current_entry);
472         if (creader->id == id) {
473             reader = creader;
474             break;
475         }
476         vreader_free(creader);
477     }
478     vreader_list_unlock();
479     return reader;
480 }
481
482 VReader *
483 vreader_get_reader_by_name(const char *name)
484 {
485     VReader *reader = NULL;
486     VReaderListEntry *current_entry;
487
488     vreader_list_lock();
489     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
490             current_entry = vreader_list_get_next(current_entry)) {
491         VReader *creader = vreader_list_get_reader(current_entry);
492         if (strcmp(creader->name, name) == 0) {
493             reader = creader;
494             break;
495         }
496         vreader_free(creader);
497     }
498     vreader_list_unlock();
499     return reader;
500 }
501
502 /* called from card_emul to initialize the readers */
503 VReaderStatus
504 vreader_add_reader(VReader *reader)
505 {
506     VReaderListEntry *reader_entry;
507
508     reader_entry = vreader_list_entry_new(reader);
509     if (reader_entry == NULL) {
510         return VREADER_OUT_OF_MEMORY;
511     }
512     vreader_list_lock();
513     vreader_queue(vreader_list, reader_entry);
514     vreader_list_unlock();
515     vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
516     return VREADER_OK;
517 }
518
519
520 VReaderStatus
521 vreader_remove_reader(VReader *reader)
522 {
523     VReaderListEntry *current_entry;
524
525     vreader_list_lock();
526     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
527          current_entry = vreader_list_get_next(current_entry)) {
528         if (current_entry->reader == reader) {
529             break;
530         }
531     }
532     vreader_dequeue(vreader_list, current_entry);
533     vreader_list_unlock();
534     vreader_list_entry_delete(current_entry);
535     vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
536     return VREADER_OK;
537 }
538
539 /*
540  * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
541  * state. Separated from vreader_insert_card to allow replaying events
542  * for a given state.
543  */
544 void
545 vreader_queue_card_event(VReader *reader)
546 {
547     vevent_queue_vevent(vevent_new(
548         reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
549         reader->card));
550 }
551
552 /*
553  * insert/remove a new card. for removal, card == NULL
554  */
555 VReaderStatus
556 vreader_insert_card(VReader *reader, VCard *card)
557 {
558     vreader_lock(reader);
559     if (reader->card) {
560         /* decrement reference count */
561         vcard_free(reader->card);
562         reader->card = NULL;
563     }
564     reader->card = vcard_reference(card);
565     vreader_unlock(reader);
566     vreader_queue_card_event(reader);
567     return VREADER_OK;
568 }
569
570 /*
571  * initialize all the static reader structures
572  */
573 void
574 vreader_init(void)
575 {
576     vreader_list_init();
577 }
578