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.
11 #define G_LOG_DOMAIN "libcacard"
14 #include "qemu-common.h"
15 #include "qemu/thread.h"
18 #include "vcard_emul.h"
19 #include "card_7816.h"
22 #include "cac.h" /* just for debugging defines */
24 #define LIBCACARD_LOG_DOMAIN "libcacard"
26 struct VReaderStruct
{
32 VReaderEmul
*reader_private
;
33 VReaderEmulFree reader_private_free
;
41 apdu_ins_to_string(int 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
:
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
:
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
:
70 case VCARD7816_INS_PUT_DATA
:
72 case VCARD7816_INS_GET_DATA
:
74 case VCARD7816_INS_SELECT_FILE
:
76 case VCARD7816_INS_VERIFY
:
78 case VCARD7816_INS_GET_RESPONSE
:
79 return "get response";
80 case CAC_GET_PROPERTIES
:
81 return "get properties";
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";
98 vreader_lock(VReader
*reader
)
100 qemu_mutex_lock(&reader
->lock
);
104 vreader_unlock(VReader
*reader
)
106 qemu_mutex_unlock(&reader
->lock
);
110 * vreader constructor
113 vreader_new(const char *name
, VReaderEmul
*private,
114 VReaderEmulFree private_free
)
118 reader
= g_new(VReader
, 1);
119 qemu_mutex_init(&reader
->lock
);
120 reader
->reference_count
= 1;
121 reader
->name
= g_strdup(name
);
123 reader
->id
= (vreader_id_t
)-1;
124 reader
->reader_private
= private;
125 reader
->reader_private_free
= private_free
;
129 /* get a reference */
131 vreader_reference(VReader
*reader
)
133 if (reader
== NULL
) {
136 vreader_lock(reader
);
137 reader
->reference_count
++;
138 vreader_unlock(reader
);
142 /* free a reference */
144 vreader_free(VReader
*reader
)
146 if (reader
== NULL
) {
149 vreader_lock(reader
);
150 if (reader
->reference_count
-- > 1) {
151 vreader_unlock(reader
);
154 vreader_unlock(reader
);
156 vcard_free(reader
->card
);
159 g_free(reader
->name
);
161 if (reader
->reader_private_free
) {
162 reader
->reader_private_free(reader
->reader_private
);
168 vreader_get_card(VReader
*reader
)
172 vreader_lock(reader
);
173 card
= vcard_reference(reader
->card
);
174 vreader_unlock(reader
);
179 vreader_card_is_present(VReader
*reader
)
181 VCard
*card
= vreader_get_card(reader
);
184 return VREADER_NO_CARD
;
191 vreader_get_id(VReader
*reader
)
193 if (reader
== NULL
) {
194 return (vreader_id_t
)-1;
200 vreader_set_id(VReader
*reader
, vreader_id_t id
)
202 if (reader
== NULL
) {
203 return VREADER_NO_CARD
;
210 vreader_get_name(VReader
*reader
)
212 if (reader
== NULL
) {
219 vreader_get_private(VReader
*reader
)
221 return reader
->reader_private
;
225 vreader_reset(VReader
*reader
, VCardPower power
, unsigned char *atr
, int *len
)
227 VCard
*card
= vreader_get_card(reader
);
230 return VREADER_NO_CARD
;
235 vcard_reset(card
, power
);
237 vcard_get_atr(card
, atr
, len
);
239 vcard_free(card
); /* free our reference */
244 vreader_power_on(VReader
*reader
, unsigned char *atr
, int *len
)
246 return vreader_reset(reader
, VCARD_POWER_ON
, atr
, len
);
250 vreader_power_off(VReader
*reader
)
252 return vreader_reset(reader
, VCARD_POWER_OFF
, NULL
, 0);
257 vreader_xfr_bytes(VReader
*reader
,
258 unsigned char *send_buf
, int send_buf_len
,
259 unsigned char *receive_buf
, int *receive_buf_len
)
262 VCardResponse
*response
= NULL
;
263 VCardStatus card_status
;
264 unsigned short status
;
265 VCard
*card
= vreader_get_card(reader
);
268 return VREADER_NO_CARD
;
271 apdu
= vcard_apdu_new(send_buf
, send_buf_len
, &status
);
273 response
= vcard_make_response(status
);
274 card_status
= VCARD_DONE
;
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
);
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
);
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 */
296 struct VReaderListStruct
{
297 VReaderListEntry
*head
;
298 VReaderListEntry
*tail
;
301 struct VReaderListEntryStruct
{
302 VReaderListEntry
*next
;
303 VReaderListEntry
*prev
;
308 static VReaderListEntry
*
309 vreader_list_entry_new(VReader
*reader
)
311 VReaderListEntry
*new_reader_list_entry
;
313 new_reader_list_entry
= g_new0(VReaderListEntry
, 1);
314 new_reader_list_entry
->reader
= vreader_reference(reader
);
315 return new_reader_list_entry
;
319 vreader_list_entry_delete(VReaderListEntry
*entry
)
324 vreader_free(entry
->reader
);
330 vreader_list_new(void)
332 VReaderList
*new_reader_list
;
334 new_reader_list
= g_new0(VReaderList
, 1);
335 return new_reader_list
;
339 vreader_list_delete(VReaderList
*list
)
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
);
355 vreader_list_get_first(VReaderList
*list
)
357 return list
? list
->head
: NULL
;
361 vreader_list_get_next(VReaderListEntry
*current
)
363 return current
? current
->next
: NULL
;
367 vreader_list_get_reader(VReaderListEntry
*entry
)
369 return entry
? vreader_reference(entry
->reader
) : NULL
;
373 vreader_queue(VReaderList
*list
, VReaderListEntry
*entry
)
379 entry
->prev
= list
->tail
;
381 list
->tail
->next
= entry
;
389 vreader_dequeue(VReaderList
*list
, VReaderListEntry
*entry
)
394 if (entry
->next
== NULL
) {
395 list
->tail
= entry
->prev
;
396 } else if (entry
->prev
== NULL
) {
397 list
->head
= entry
->next
;
399 entry
->prev
->next
= entry
->next
;
400 entry
->next
->prev
= entry
->prev
;
402 if ((list
->tail
== NULL
) || (list
->head
== NULL
)) {
403 list
->head
= list
->tail
= NULL
;
405 entry
->next
= entry
->prev
= NULL
;
408 static VReaderList
*vreader_list
;
409 static QemuMutex vreader_list_mutex
;
412 vreader_list_init(void)
414 vreader_list
= vreader_list_new();
415 qemu_mutex_init(&vreader_list_mutex
);
419 vreader_list_lock(void)
421 qemu_mutex_lock(&vreader_list_mutex
);
425 vreader_list_unlock(void)
427 qemu_mutex_unlock(&vreader_list_mutex
);
431 vreader_copy_list(VReaderList
*list
)
433 VReaderList
*new_list
;
434 VReaderListEntry
*current_entry
;
436 new_list
= vreader_list_new();
437 if (new_list
== NULL
) {
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
);
445 vreader_free(reader
);
446 vreader_queue(new_list
, new_entry
);
452 vreader_get_reader_list(void)
454 VReaderList
*new_reader_list
;
457 new_reader_list
= vreader_copy_list(vreader_list
);
458 vreader_list_unlock();
459 return new_reader_list
;
463 vreader_get_reader_by_id(vreader_id_t id
)
465 VReader
*reader
= NULL
;
466 VReaderListEntry
*current_entry
;
468 if (id
== (vreader_id_t
) -1) {
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
) {
480 vreader_free(creader
);
482 vreader_list_unlock();
487 vreader_get_reader_by_name(const char *name
)
489 VReader
*reader
= NULL
;
490 VReaderListEntry
*current_entry
;
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) {
500 vreader_free(creader
);
502 vreader_list_unlock();
506 /* called from card_emul to initialize the readers */
508 vreader_add_reader(VReader
*reader
)
510 VReaderListEntry
*reader_entry
;
512 reader_entry
= vreader_list_entry_new(reader
);
513 if (reader_entry
== NULL
) {
514 return VREADER_OUT_OF_MEMORY
;
517 vreader_queue(vreader_list
, reader_entry
);
518 vreader_list_unlock();
519 vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT
, reader
, NULL
));
525 vreader_remove_reader(VReader
*reader
)
527 VReaderListEntry
*current_entry
;
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
) {
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
));
544 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
545 * state. Separated from vreader_insert_card to allow replaying events
549 vreader_queue_card_event(VReader
*reader
)
551 vevent_queue_vevent(vevent_new(
552 reader
->card
? VEVENT_CARD_INSERT
: VEVENT_CARD_REMOVE
, reader
,
557 * insert/remove a new card. for removal, card == NULL
560 vreader_insert_card(VReader
*reader
, VCard
*card
)
562 vreader_lock(reader
);
564 /* decrement reference count */
565 vcard_free(reader
->card
);
568 reader
->card
= vcard_reference(card
);
569 vreader_unlock(reader
);
570 vreader_queue_card_event(reader
);
575 * initialize all the static reader structures