]> Git Repo - qemu.git/blob - libcacard/vreader.c
rbd: Fix leaks in rbd_start_aio() error path
[qemu.git] / 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 #include <glib.h>
13
14 #include "qemu-common.h"
15 #include "qemu/thread.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     QemuMutex 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     qemu_mutex_lock(&reader->lock);
101 }
102
103 static inline void
104 vreader_unlock(VReader *reader)
105 {
106     qemu_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     qemu_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     if (reader->card) {
156         vcard_free(reader->card);
157     }
158     if (reader->name) {
159         g_free(reader->name);
160     }
161     if (reader->reader_private_free) {
162         reader->reader_private_free(reader->reader_private);
163     }
164     g_free(reader);
165 }
166
167 static VCard *
168 vreader_get_card(VReader *reader)
169 {
170     VCard *card;
171
172     vreader_lock(reader);
173     card = vcard_reference(reader->card);
174     vreader_unlock(reader);
175     return card;
176 }
177
178 VReaderStatus
179 vreader_card_is_present(VReader *reader)
180 {
181     VCard *card = vreader_get_card(reader);
182
183     if (card == NULL) {
184         return VREADER_NO_CARD;
185     }
186     vcard_free(card);
187     return VREADER_OK;
188 }
189
190 vreader_id_t
191 vreader_get_id(VReader *reader)
192 {
193     if (reader == NULL) {
194         return (vreader_id_t)-1;
195     }
196     return reader->id;
197 }
198
199 VReaderStatus
200 vreader_set_id(VReader *reader, vreader_id_t id)
201 {
202     if (reader == NULL) {
203         return VREADER_NO_CARD;
204     }
205     reader->id = id;
206     return VREADER_OK;
207 }
208
209 const char *
210 vreader_get_name(VReader *reader)
211 {
212     if (reader == NULL) {
213         return NULL;
214     }
215     return reader->name;
216 }
217
218 VReaderEmul *
219 vreader_get_private(VReader *reader)
220 {
221     return reader->reader_private;
222 }
223
224 static VReaderStatus
225 vreader_reset(VReader *reader, VCardPower power, unsigned char *atr, int *len)
226 {
227     VCard *card = vreader_get_card(reader);
228
229     if (card == NULL) {
230         return VREADER_NO_CARD;
231     }
232     /*
233      * clean up our state
234      */
235     vcard_reset(card, power);
236     if (atr) {
237         vcard_get_atr(card, atr, len);
238     }
239     vcard_free(card); /* free our reference */
240     return VREADER_OK;
241 }
242
243 VReaderStatus
244 vreader_power_on(VReader *reader, unsigned char *atr, int *len)
245 {
246     return vreader_reset(reader, VCARD_POWER_ON, atr, len);
247 }
248
249 VReaderStatus
250 vreader_power_off(VReader *reader)
251 {
252     return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
253 }
254
255
256 VReaderStatus
257 vreader_xfr_bytes(VReader *reader,
258                   unsigned char *send_buf, int send_buf_len,
259                   unsigned char *receive_buf, int *receive_buf_len)
260 {
261     VCardAPDU *apdu;
262     VCardResponse *response = NULL;
263     VCardStatus card_status;
264     unsigned short status;
265     VCard *card = vreader_get_card(reader);
266
267     if (card == NULL) {
268         return VREADER_NO_CARD;
269     }
270
271     apdu = vcard_apdu_new(send_buf, send_buf_len, &status);
272     if (apdu == NULL) {
273         response = vcard_make_response(status);
274         card_status = VCARD_DONE;
275     } else {
276         g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
277               __func__, apdu->a_cla, apdu->a_ins, apdu->a_p1, apdu->a_p2,
278               apdu->a_Lc, apdu->a_Le, apdu_ins_to_string(apdu->a_ins));
279         card_status = vcard_process_apdu(card, apdu, &response);
280         if (response) {
281             g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
282                   __func__, response->b_status, response->b_sw1,
283                   response->b_sw2, response->b_len, response->b_total_len);
284         }
285     }
286     assert(card_status == VCARD_DONE && response);
287     int size = MIN(*receive_buf_len, response->b_total_len);
288     memcpy(receive_buf, response->b_data, size);
289     *receive_buf_len = size;
290     vcard_response_delete(response);
291     vcard_apdu_delete(apdu);
292     vcard_free(card); /* free our reference */
293     return VREADER_OK;
294 }
295
296 struct VReaderListStruct {
297     VReaderListEntry *head;
298     VReaderListEntry *tail;
299 };
300
301 struct VReaderListEntryStruct {
302     VReaderListEntry *next;
303     VReaderListEntry *prev;
304     VReader *reader;
305 };
306
307
308 static VReaderListEntry *
309 vreader_list_entry_new(VReader *reader)
310 {
311     VReaderListEntry *new_reader_list_entry;
312
313     new_reader_list_entry = g_new0(VReaderListEntry, 1);
314     new_reader_list_entry->reader = vreader_reference(reader);
315     return new_reader_list_entry;
316 }
317
318 static void
319 vreader_list_entry_delete(VReaderListEntry *entry)
320 {
321     if (entry == NULL) {
322         return;
323     }
324     vreader_free(entry->reader);
325     g_free(entry);
326 }
327
328
329 static VReaderList *
330 vreader_list_new(void)
331 {
332     VReaderList *new_reader_list;
333
334     new_reader_list = g_new0(VReaderList, 1);
335     return new_reader_list;
336 }
337
338 void
339 vreader_list_delete(VReaderList *list)
340 {
341     VReaderListEntry *current_entry;
342     VReaderListEntry *next_entry;
343     for (current_entry = vreader_list_get_first(list); current_entry;
344          current_entry = next_entry) {
345         next_entry = vreader_list_get_next(current_entry);
346         vreader_list_entry_delete(current_entry);
347     }
348     list->head = NULL;
349     list->tail = NULL;
350     g_free(list);
351 }
352
353
354 VReaderListEntry *
355 vreader_list_get_first(VReaderList *list)
356 {
357     return list ? list->head : NULL;
358 }
359
360 VReaderListEntry *
361 vreader_list_get_next(VReaderListEntry *current)
362 {
363     return current ? current->next : NULL;
364 }
365
366 VReader *
367 vreader_list_get_reader(VReaderListEntry *entry)
368 {
369     return entry ? vreader_reference(entry->reader) : NULL;
370 }
371
372 static void
373 vreader_queue(VReaderList *list, VReaderListEntry *entry)
374 {
375     if (entry == NULL) {
376         return;
377     }
378     entry->next = NULL;
379     entry->prev = list->tail;
380     if (list->head) {
381         list->tail->next = entry;
382     } else {
383         list->head = entry;
384     }
385     list->tail = entry;
386 }
387
388 static void
389 vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
390 {
391     if (entry == NULL) {
392         return;
393     }
394     if (entry->next == NULL) {
395         list->tail = entry->prev;
396     } else if (entry->prev == NULL) {
397         list->head = entry->next;
398     } else {
399         entry->prev->next = entry->next;
400         entry->next->prev = entry->prev;
401     }
402     if ((list->tail == NULL) || (list->head == NULL)) {
403         list->head = list->tail = NULL;
404     }
405     entry->next = entry->prev = NULL;
406 }
407
408 static VReaderList *vreader_list;
409 static QemuMutex vreader_list_mutex;
410
411 static void
412 vreader_list_init(void)
413 {
414     vreader_list = vreader_list_new();
415     qemu_mutex_init(&vreader_list_mutex);
416 }
417
418 static void
419 vreader_list_lock(void)
420 {
421     qemu_mutex_lock(&vreader_list_mutex);
422 }
423
424 static void
425 vreader_list_unlock(void)
426 {
427     qemu_mutex_unlock(&vreader_list_mutex);
428 }
429
430 static VReaderList *
431 vreader_copy_list(VReaderList *list)
432 {
433     VReaderList *new_list;
434     VReaderListEntry *current_entry;
435
436     new_list = vreader_list_new();
437     if (new_list == NULL) {
438         return NULL;
439     }
440     for (current_entry = vreader_list_get_first(list); current_entry;
441          current_entry = vreader_list_get_next(current_entry)) {
442         VReader *reader = vreader_list_get_reader(current_entry);
443         VReaderListEntry *new_entry = vreader_list_entry_new(reader);
444
445         vreader_free(reader);
446         vreader_queue(new_list, new_entry);
447     }
448     return new_list;
449 }
450
451 VReaderList *
452 vreader_get_reader_list(void)
453 {
454     VReaderList *new_reader_list;
455
456     vreader_list_lock();
457     new_reader_list = vreader_copy_list(vreader_list);
458     vreader_list_unlock();
459     return new_reader_list;
460 }
461
462 VReader *
463 vreader_get_reader_by_id(vreader_id_t id)
464 {
465     VReader *reader = NULL;
466     VReaderListEntry *current_entry;
467
468     if (id == (vreader_id_t) -1) {
469         return NULL;
470     }
471
472     vreader_list_lock();
473     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
474             current_entry = vreader_list_get_next(current_entry)) {
475         VReader *creader = vreader_list_get_reader(current_entry);
476         if (creader->id == id) {
477             reader = creader;
478             break;
479         }
480         vreader_free(creader);
481     }
482     vreader_list_unlock();
483     return reader;
484 }
485
486 VReader *
487 vreader_get_reader_by_name(const char *name)
488 {
489     VReader *reader = NULL;
490     VReaderListEntry *current_entry;
491
492     vreader_list_lock();
493     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
494             current_entry = vreader_list_get_next(current_entry)) {
495         VReader *creader = vreader_list_get_reader(current_entry);
496         if (strcmp(creader->name, name) == 0) {
497             reader = creader;
498             break;
499         }
500         vreader_free(creader);
501     }
502     vreader_list_unlock();
503     return reader;
504 }
505
506 /* called from card_emul to initialize the readers */
507 VReaderStatus
508 vreader_add_reader(VReader *reader)
509 {
510     VReaderListEntry *reader_entry;
511
512     reader_entry = vreader_list_entry_new(reader);
513     if (reader_entry == NULL) {
514         return VREADER_OUT_OF_MEMORY;
515     }
516     vreader_list_lock();
517     vreader_queue(vreader_list, reader_entry);
518     vreader_list_unlock();
519     vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
520     return VREADER_OK;
521 }
522
523
524 VReaderStatus
525 vreader_remove_reader(VReader *reader)
526 {
527     VReaderListEntry *current_entry;
528
529     vreader_list_lock();
530     for (current_entry = vreader_list_get_first(vreader_list); current_entry;
531          current_entry = vreader_list_get_next(current_entry)) {
532         if (current_entry->reader == reader) {
533             break;
534         }
535     }
536     vreader_dequeue(vreader_list, current_entry);
537     vreader_list_unlock();
538     vreader_list_entry_delete(current_entry);
539     vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
540     return VREADER_OK;
541 }
542
543 /*
544  * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
545  * state. Separated from vreader_insert_card to allow replaying events
546  * for a given state.
547  */
548 void
549 vreader_queue_card_event(VReader *reader)
550 {
551     vevent_queue_vevent(vevent_new(
552         reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
553         reader->card));
554 }
555
556 /*
557  * insert/remove a new card. for removal, card == NULL
558  */
559 VReaderStatus
560 vreader_insert_card(VReader *reader, VCard *card)
561 {
562     vreader_lock(reader);
563     if (reader->card) {
564         /* decrement reference count */
565         vcard_free(reader->card);
566         reader->card = NULL;
567     }
568     reader->card = vcard_reference(card);
569     vreader_unlock(reader);
570     vreader_queue_card_event(reader);
571     return VREADER_OK;
572 }
573
574 /*
575  * initialize all the static reader structures
576  */
577 void
578 vreader_init(void)
579 {
580     vreader_list_init();
581 }
582
This page took 0.054509 seconds and 4 git commands to generate.