]> Git Repo - qemu.git/blame - libcacard/vreader.c
libcacard: remove useless initializers
[qemu.git] / libcacard / vreader.c
CommitLineData
111a38b0
RR
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
7a685896
AL
8#ifdef G_LOG_DOMAIN
9#undef G_LOG_DOMAIN
10#endif
11#define G_LOG_DOMAIN "libcacard"
12#include <glib.h>
13
111a38b0 14#include "qemu-common.h"
1de7afc9 15#include "qemu/thread.h"
111a38b0
RR
16
17#include "vcard.h"
18#include "vcard_emul.h"
19#include "card_7816.h"
20#include "vreader.h"
21#include "vevent.h"
7a685896
AL
22#include "cac.h" /* just for debugging defines */
23
24#define LIBCACARD_LOG_DOMAIN "libcacard"
111a38b0
RR
25
26struct 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
7a685896
AL
36/*
37 * Debug helpers
38 */
39
40static const char *
41apdu_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
111a38b0
RR
96/* manage locking */
97static inline void
98vreader_lock(VReader *reader)
99{
100 qemu_mutex_lock(&reader->lock);
101}
102
103static inline void
104vreader_unlock(VReader *reader)
105{
106 qemu_mutex_unlock(&reader->lock);
107}
108
109/*
110 * vreader constructor
111 */
112VReader *
113vreader_new(const char *name, VReaderEmul *private,
114 VReaderEmulFree private_free)
115{
116 VReader *reader;
117
78a4b8d2 118 reader = g_new(VReader, 1);
111a38b0
RR
119 qemu_mutex_init(&reader->lock);
120 reader->reference_count = 1;
be168af8 121 reader->name = g_strdup(name);
111a38b0
RR
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 */
130VReader*
131vreader_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 */
143void
144vreader_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) {
7267c094 159 g_free(reader->name);
111a38b0
RR
160 }
161 if (reader->reader_private_free) {
162 reader->reader_private_free(reader->reader_private);
163 }
7267c094 164 g_free(reader);
111a38b0
RR
165}
166
167static VCard *
168vreader_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
178VReaderStatus
179vreader_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
190vreader_id_t
191vreader_get_id(VReader *reader)
192{
193 if (reader == NULL) {
194 return (vreader_id_t)-1;
195 }
196 return reader->id;
197}
198
199VReaderStatus
200vreader_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
209const char *
210vreader_get_name(VReader *reader)
211{
212 if (reader == NULL) {
213 return NULL;
214 }
215 return reader->name;
216}
217
218VReaderEmul *
219vreader_get_private(VReader *reader)
220{
221 return reader->reader_private;
222}
223
224static VReaderStatus
225vreader_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
243VReaderStatus
244vreader_power_on(VReader *reader, unsigned char *atr, int *len)
245{
246 return vreader_reset(reader, VCARD_POWER_ON, atr, len);
247}
248
249VReaderStatus
250vreader_power_off(VReader *reader)
251{
252 return vreader_reset(reader, VCARD_POWER_OFF, NULL, 0);
253}
254
255
256VReaderStatus
257vreader_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 {
8e25c274 276 g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
7a685896
AL
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));
111a38b0 279 card_status = vcard_process_apdu(card, apdu, &response);
7a685896 280 if (response) {
8e25c274 281 g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
7a685896
AL
282 __func__, response->b_status, response->b_sw1,
283 response->b_sw2, response->b_len, response->b_total_len);
284 }
111a38b0 285 }
f33a984d 286 assert(card_status == VCARD_DONE && response);
fa5912a1
MA
287 int size = MIN(*receive_buf_len, response->b_total_len);
288 memcpy(receive_buf, response->b_data, size);
289 *receive_buf_len = size;
111a38b0
RR
290 vcard_response_delete(response);
291 vcard_apdu_delete(apdu);
292 vcard_free(card); /* free our reference */
293 return VREADER_OK;
294}
295
296struct VReaderListStruct {
297 VReaderListEntry *head;
298 VReaderListEntry *tail;
299};
300
301struct VReaderListEntryStruct {
302 VReaderListEntry *next;
303 VReaderListEntry *prev;
304 VReader *reader;
305};
306
307
308static VReaderListEntry *
309vreader_list_entry_new(VReader *reader)
310{
311 VReaderListEntry *new_reader_list_entry;
312
78a4b8d2 313 new_reader_list_entry = g_new0(VReaderListEntry, 1);
111a38b0
RR
314 new_reader_list_entry->reader = vreader_reference(reader);
315 return new_reader_list_entry;
316}
317
318static void
319vreader_list_entry_delete(VReaderListEntry *entry)
320{
321 if (entry == NULL) {
322 return;
323 }
324 vreader_free(entry->reader);
7267c094 325 g_free(entry);
111a38b0
RR
326}
327
328
329static VReaderList *
330vreader_list_new(void)
331{
332 VReaderList *new_reader_list;
333
78a4b8d2 334 new_reader_list = g_new0(VReaderList, 1);
111a38b0
RR
335 return new_reader_list;
336}
337
338void
339vreader_list_delete(VReaderList *list)
340{
341 VReaderListEntry *current_entry;
1687a089 342 VReaderListEntry *next_entry;
111a38b0
RR
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;
7267c094 350 g_free(list);
111a38b0
RR
351}
352
353
354VReaderListEntry *
355vreader_list_get_first(VReaderList *list)
356{
357 return list ? list->head : NULL;
358}
359
360VReaderListEntry *
361vreader_list_get_next(VReaderListEntry *current)
362{
363 return current ? current->next : NULL;
364}
365
366VReader *
367vreader_list_get_reader(VReaderListEntry *entry)
368{
369 return entry ? vreader_reference(entry->reader) : NULL;
370}
371
372static void
373vreader_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
388static void
389vreader_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
408static VReaderList *vreader_list;
409static QemuMutex vreader_list_mutex;
410
411static void
412vreader_list_init(void)
413{
414 vreader_list = vreader_list_new();
415 qemu_mutex_init(&vreader_list_mutex);
416}
417
418static void
419vreader_list_lock(void)
420{
421 qemu_mutex_lock(&vreader_list_mutex);
422}
423
424static void
425vreader_list_unlock(void)
426{
427 qemu_mutex_unlock(&vreader_list_mutex);
428}
429
430static VReaderList *
431vreader_copy_list(VReaderList *list)
432{
1687a089
MT
433 VReaderList *new_list;
434 VReaderListEntry *current_entry;
111a38b0
RR
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
451VReaderList *
452vreader_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
462VReader *
463vreader_get_reader_by_id(vreader_id_t id)
464{
465 VReader *reader = NULL;
1687a089 466 VReaderListEntry *current_entry;
111a38b0
RR
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
486VReader *
487vreader_get_reader_by_name(const char *name)
488{
489 VReader *reader = NULL;
1687a089 490 VReaderListEntry *current_entry;
111a38b0
RR
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 */
507VReaderStatus
508vreader_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
524VReaderStatus
525vreader_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 */
548void
549vreader_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 */
559VReaderStatus
560vreader_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 */
577void
578vreader_init(void)
579{
580 vreader_list_init();
581}
582
This page took 0.282229 seconds and 4 git commands to generate.