]> git.proxmox.com Git - mirror_qemu.git/blob - libcacard/vreader.c
libcacard/vscclient: Bury some dead code
[mirror_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);
287 if (card_status == VCARD_DONE) {
288 int size = MIN(*receive_buf_len, response->b_total_len);
289 memcpy(receive_buf, response->b_data, size);
290 *receive_buf_len = size;
291 }
292 vcard_response_delete(response);
293 vcard_apdu_delete(apdu);
294 vcard_free(card); /* free our reference */
295 return VREADER_OK;
296 }
297
298 struct VReaderListStruct {
299 VReaderListEntry *head;
300 VReaderListEntry *tail;
301 };
302
303 struct VReaderListEntryStruct {
304 VReaderListEntry *next;
305 VReaderListEntry *prev;
306 VReader *reader;
307 };
308
309
310 static VReaderListEntry *
311 vreader_list_entry_new(VReader *reader)
312 {
313 VReaderListEntry *new_reader_list_entry;
314
315 new_reader_list_entry = g_new0(VReaderListEntry, 1);
316 new_reader_list_entry->reader = vreader_reference(reader);
317 return new_reader_list_entry;
318 }
319
320 static void
321 vreader_list_entry_delete(VReaderListEntry *entry)
322 {
323 if (entry == NULL) {
324 return;
325 }
326 vreader_free(entry->reader);
327 g_free(entry);
328 }
329
330
331 static VReaderList *
332 vreader_list_new(void)
333 {
334 VReaderList *new_reader_list;
335
336 new_reader_list = g_new0(VReaderList, 1);
337 return new_reader_list;
338 }
339
340 void
341 vreader_list_delete(VReaderList *list)
342 {
343 VReaderListEntry *current_entry;
344 VReaderListEntry *next_entry = NULL;
345 for (current_entry = vreader_list_get_first(list); current_entry;
346 current_entry = next_entry) {
347 next_entry = vreader_list_get_next(current_entry);
348 vreader_list_entry_delete(current_entry);
349 }
350 list->head = NULL;
351 list->tail = NULL;
352 g_free(list);
353 }
354
355
356 VReaderListEntry *
357 vreader_list_get_first(VReaderList *list)
358 {
359 return list ? list->head : NULL;
360 }
361
362 VReaderListEntry *
363 vreader_list_get_next(VReaderListEntry *current)
364 {
365 return current ? current->next : NULL;
366 }
367
368 VReader *
369 vreader_list_get_reader(VReaderListEntry *entry)
370 {
371 return entry ? vreader_reference(entry->reader) : NULL;
372 }
373
374 static void
375 vreader_queue(VReaderList *list, VReaderListEntry *entry)
376 {
377 if (entry == NULL) {
378 return;
379 }
380 entry->next = NULL;
381 entry->prev = list->tail;
382 if (list->head) {
383 list->tail->next = entry;
384 } else {
385 list->head = entry;
386 }
387 list->tail = entry;
388 }
389
390 static void
391 vreader_dequeue(VReaderList *list, VReaderListEntry *entry)
392 {
393 if (entry == NULL) {
394 return;
395 }
396 if (entry->next == NULL) {
397 list->tail = entry->prev;
398 } else if (entry->prev == NULL) {
399 list->head = entry->next;
400 } else {
401 entry->prev->next = entry->next;
402 entry->next->prev = entry->prev;
403 }
404 if ((list->tail == NULL) || (list->head == NULL)) {
405 list->head = list->tail = NULL;
406 }
407 entry->next = entry->prev = NULL;
408 }
409
410 static VReaderList *vreader_list;
411 static QemuMutex vreader_list_mutex;
412
413 static void
414 vreader_list_init(void)
415 {
416 vreader_list = vreader_list_new();
417 qemu_mutex_init(&vreader_list_mutex);
418 }
419
420 static void
421 vreader_list_lock(void)
422 {
423 qemu_mutex_lock(&vreader_list_mutex);
424 }
425
426 static void
427 vreader_list_unlock(void)
428 {
429 qemu_mutex_unlock(&vreader_list_mutex);
430 }
431
432 static VReaderList *
433 vreader_copy_list(VReaderList *list)
434 {
435 VReaderList *new_list = NULL;
436 VReaderListEntry *current_entry = NULL;
437
438 new_list = vreader_list_new();
439 if (new_list == NULL) {
440 return NULL;
441 }
442 for (current_entry = vreader_list_get_first(list); current_entry;
443 current_entry = vreader_list_get_next(current_entry)) {
444 VReader *reader = vreader_list_get_reader(current_entry);
445 VReaderListEntry *new_entry = vreader_list_entry_new(reader);
446
447 vreader_free(reader);
448 vreader_queue(new_list, new_entry);
449 }
450 return new_list;
451 }
452
453 VReaderList *
454 vreader_get_reader_list(void)
455 {
456 VReaderList *new_reader_list;
457
458 vreader_list_lock();
459 new_reader_list = vreader_copy_list(vreader_list);
460 vreader_list_unlock();
461 return new_reader_list;
462 }
463
464 VReader *
465 vreader_get_reader_by_id(vreader_id_t id)
466 {
467 VReader *reader = NULL;
468 VReaderListEntry *current_entry = NULL;
469
470 if (id == (vreader_id_t) -1) {
471 return NULL;
472 }
473
474 vreader_list_lock();
475 for (current_entry = vreader_list_get_first(vreader_list); current_entry;
476 current_entry = vreader_list_get_next(current_entry)) {
477 VReader *creader = vreader_list_get_reader(current_entry);
478 if (creader->id == id) {
479 reader = creader;
480 break;
481 }
482 vreader_free(creader);
483 }
484 vreader_list_unlock();
485 return reader;
486 }
487
488 VReader *
489 vreader_get_reader_by_name(const char *name)
490 {
491 VReader *reader = NULL;
492 VReaderListEntry *current_entry = NULL;
493
494 vreader_list_lock();
495 for (current_entry = vreader_list_get_first(vreader_list); current_entry;
496 current_entry = vreader_list_get_next(current_entry)) {
497 VReader *creader = vreader_list_get_reader(current_entry);
498 if (strcmp(creader->name, name) == 0) {
499 reader = creader;
500 break;
501 }
502 vreader_free(creader);
503 }
504 vreader_list_unlock();
505 return reader;
506 }
507
508 /* called from card_emul to initialize the readers */
509 VReaderStatus
510 vreader_add_reader(VReader *reader)
511 {
512 VReaderListEntry *reader_entry;
513
514 reader_entry = vreader_list_entry_new(reader);
515 if (reader_entry == NULL) {
516 return VREADER_OUT_OF_MEMORY;
517 }
518 vreader_list_lock();
519 vreader_queue(vreader_list, reader_entry);
520 vreader_list_unlock();
521 vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT, reader, NULL));
522 return VREADER_OK;
523 }
524
525
526 VReaderStatus
527 vreader_remove_reader(VReader *reader)
528 {
529 VReaderListEntry *current_entry;
530
531 vreader_list_lock();
532 for (current_entry = vreader_list_get_first(vreader_list); current_entry;
533 current_entry = vreader_list_get_next(current_entry)) {
534 if (current_entry->reader == reader) {
535 break;
536 }
537 }
538 vreader_dequeue(vreader_list, current_entry);
539 vreader_list_unlock();
540 vreader_list_entry_delete(current_entry);
541 vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE, reader, NULL));
542 return VREADER_OK;
543 }
544
545 /*
546 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
547 * state. Separated from vreader_insert_card to allow replaying events
548 * for a given state.
549 */
550 void
551 vreader_queue_card_event(VReader *reader)
552 {
553 vevent_queue_vevent(vevent_new(
554 reader->card ? VEVENT_CARD_INSERT : VEVENT_CARD_REMOVE, reader,
555 reader->card));
556 }
557
558 /*
559 * insert/remove a new card. for removal, card == NULL
560 */
561 VReaderStatus
562 vreader_insert_card(VReader *reader, VCard *card)
563 {
564 vreader_lock(reader);
565 if (reader->card) {
566 /* decrement reference count */
567 vcard_free(reader->card);
568 reader->card = NULL;
569 }
570 reader->card = vcard_reference(card);
571 vreader_unlock(reader);
572 vreader_queue_card_event(reader);
573 return VREADER_OK;
574 }
575
576 /*
577 * initialize all the static reader structures
578 */
579 void
580 vreader_init(void)
581 {
582 vreader_list_init();
583 }
584