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"
13 #include "qemu-common.h"
16 #include "vcard_emul.h"
17 #include "card_7816.h"
20 #include "cac.h" /* just for debugging defines */
22 #define LIBCACARD_LOG_DOMAIN "libcacard"
24 struct VReaderStruct
{
30 VReaderEmul
*reader_private
;
31 VReaderEmulFree reader_private_free
;
39 apdu_ins_to_string(int ins
)
42 case VCARD7816_INS_MANAGE_CHANNEL
:
43 return "manage channel";
44 case VCARD7816_INS_EXTERNAL_AUTHENTICATE
:
45 return "external authenticate";
46 case VCARD7816_INS_GET_CHALLENGE
:
47 return "get challenge";
48 case VCARD7816_INS_INTERNAL_AUTHENTICATE
:
49 return "internal authenticate";
50 case VCARD7816_INS_ERASE_BINARY
:
51 return "erase binary";
52 case VCARD7816_INS_READ_BINARY
:
54 case VCARD7816_INS_WRITE_BINARY
:
55 return "write binary";
56 case VCARD7816_INS_UPDATE_BINARY
:
57 return "update binary";
58 case VCARD7816_INS_READ_RECORD
:
60 case VCARD7816_INS_WRITE_RECORD
:
61 return "write record";
62 case VCARD7816_INS_UPDATE_RECORD
:
63 return "update record";
64 case VCARD7816_INS_APPEND_RECORD
:
65 return "append record";
66 case VCARD7816_INS_ENVELOPE
:
68 case VCARD7816_INS_PUT_DATA
:
70 case VCARD7816_INS_GET_DATA
:
72 case VCARD7816_INS_SELECT_FILE
:
74 case VCARD7816_INS_VERIFY
:
76 case VCARD7816_INS_GET_RESPONSE
:
77 return "get response";
78 case CAC_GET_PROPERTIES
:
79 return "get properties";
84 case CAC_UPDATE_BUFFER
:
85 return "update buffer";
86 case CAC_SIGN_DECRYPT
:
87 return "sign decrypt";
88 case CAC_GET_CERTIFICATE
:
89 return "get certificate";
96 vreader_lock(VReader
*reader
)
98 g_mutex_lock(&reader
->lock
);
102 vreader_unlock(VReader
*reader
)
104 g_mutex_unlock(&reader
->lock
);
108 * vreader constructor
111 vreader_new(const char *name
, VReaderEmul
*private,
112 VReaderEmulFree private_free
)
116 reader
= g_new(VReader
, 1);
117 g_mutex_init(&reader
->lock
);
118 reader
->reference_count
= 1;
119 reader
->name
= g_strdup(name
);
121 reader
->id
= (vreader_id_t
)-1;
122 reader
->reader_private
= private;
123 reader
->reader_private_free
= private_free
;
127 /* get a reference */
129 vreader_reference(VReader
*reader
)
131 if (reader
== NULL
) {
134 vreader_lock(reader
);
135 reader
->reference_count
++;
136 vreader_unlock(reader
);
140 /* free a reference */
142 vreader_free(VReader
*reader
)
144 if (reader
== NULL
) {
147 vreader_lock(reader
);
148 if (reader
->reference_count
-- > 1) {
149 vreader_unlock(reader
);
152 vreader_unlock(reader
);
153 g_mutex_clear(&reader
->lock
);
155 vcard_free(reader
->card
);
157 g_free(reader
->name
);
158 if (reader
->reader_private_free
) {
159 reader
->reader_private_free(reader
->reader_private
);
165 vreader_get_card(VReader
*reader
)
169 vreader_lock(reader
);
170 card
= vcard_reference(reader
->card
);
171 vreader_unlock(reader
);
176 vreader_card_is_present(VReader
*reader
)
178 VCard
*card
= vreader_get_card(reader
);
181 return VREADER_NO_CARD
;
188 vreader_get_id(VReader
*reader
)
190 if (reader
== NULL
) {
191 return (vreader_id_t
)-1;
197 vreader_set_id(VReader
*reader
, vreader_id_t id
)
199 if (reader
== NULL
) {
200 return VREADER_NO_CARD
;
207 vreader_get_name(VReader
*reader
)
209 if (reader
== NULL
) {
216 vreader_get_private(VReader
*reader
)
218 return reader
->reader_private
;
222 vreader_reset(VReader
*reader
, VCardPower power
, unsigned char *atr
, int *len
)
224 VCard
*card
= vreader_get_card(reader
);
227 return VREADER_NO_CARD
;
232 vcard_reset(card
, power
);
234 vcard_get_atr(card
, atr
, len
);
236 vcard_free(card
); /* free our reference */
241 vreader_power_on(VReader
*reader
, unsigned char *atr
, int *len
)
243 return vreader_reset(reader
, VCARD_POWER_ON
, atr
, len
);
247 vreader_power_off(VReader
*reader
)
249 return vreader_reset(reader
, VCARD_POWER_OFF
, NULL
, 0);
254 vreader_xfr_bytes(VReader
*reader
,
255 unsigned char *send_buf
, int send_buf_len
,
256 unsigned char *receive_buf
, int *receive_buf_len
)
259 VCardResponse
*response
= NULL
;
260 VCardStatus card_status
;
261 unsigned short status
;
262 VCard
*card
= vreader_get_card(reader
);
265 return VREADER_NO_CARD
;
268 apdu
= vcard_apdu_new(send_buf
, send_buf_len
, &status
);
270 response
= vcard_make_response(status
);
271 card_status
= VCARD_DONE
;
273 g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
274 __func__
, apdu
->a_cla
, apdu
->a_ins
, apdu
->a_p1
, apdu
->a_p2
,
275 apdu
->a_Lc
, apdu
->a_Le
, apdu_ins_to_string(apdu
->a_ins
));
276 card_status
= vcard_process_apdu(card
, apdu
, &response
);
278 g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
279 __func__
, response
->b_status
, response
->b_sw1
,
280 response
->b_sw2
, response
->b_len
, response
->b_total_len
);
283 assert(card_status
== VCARD_DONE
&& response
);
284 int size
= MIN(*receive_buf_len
, response
->b_total_len
);
285 memcpy(receive_buf
, response
->b_data
, size
);
286 *receive_buf_len
= size
;
287 vcard_response_delete(response
);
288 vcard_apdu_delete(apdu
);
289 vcard_free(card
); /* free our reference */
293 struct VReaderListStruct
{
294 VReaderListEntry
*head
;
295 VReaderListEntry
*tail
;
298 struct VReaderListEntryStruct
{
299 VReaderListEntry
*next
;
300 VReaderListEntry
*prev
;
305 static VReaderListEntry
*
306 vreader_list_entry_new(VReader
*reader
)
308 VReaderListEntry
*new_reader_list_entry
;
310 new_reader_list_entry
= g_new0(VReaderListEntry
, 1);
311 new_reader_list_entry
->reader
= vreader_reference(reader
);
312 return new_reader_list_entry
;
316 vreader_list_entry_delete(VReaderListEntry
*entry
)
321 vreader_free(entry
->reader
);
327 vreader_list_new(void)
329 VReaderList
*new_reader_list
;
331 new_reader_list
= g_new0(VReaderList
, 1);
332 return new_reader_list
;
336 vreader_list_delete(VReaderList
*list
)
338 VReaderListEntry
*current_entry
;
339 VReaderListEntry
*next_entry
;
340 for (current_entry
= vreader_list_get_first(list
); current_entry
;
341 current_entry
= next_entry
) {
342 next_entry
= vreader_list_get_next(current_entry
);
343 vreader_list_entry_delete(current_entry
);
350 vreader_list_get_first(VReaderList
*list
)
352 return list
? list
->head
: NULL
;
356 vreader_list_get_next(VReaderListEntry
*current
)
358 return current
? current
->next
: NULL
;
362 vreader_list_get_reader(VReaderListEntry
*entry
)
364 return entry
? vreader_reference(entry
->reader
) : NULL
;
368 vreader_queue(VReaderList
*list
, VReaderListEntry
*entry
)
374 entry
->prev
= list
->tail
;
376 list
->tail
->next
= entry
;
384 vreader_dequeue(VReaderList
*list
, VReaderListEntry
*entry
)
389 if (entry
->next
== NULL
) {
390 list
->tail
= entry
->prev
;
391 } else if (entry
->prev
== NULL
) {
392 list
->head
= entry
->next
;
394 entry
->prev
->next
= entry
->next
;
395 entry
->next
->prev
= entry
->prev
;
397 if ((list
->tail
== NULL
) || (list
->head
== NULL
)) {
398 list
->head
= list
->tail
= NULL
;
400 entry
->next
= entry
->prev
= NULL
;
403 static VReaderList
*vreader_list
;
404 static CompatGMutex vreader_list_mutex
;
407 vreader_list_init(void)
409 vreader_list
= vreader_list_new();
413 vreader_list_lock(void)
415 g_mutex_lock(&vreader_list_mutex
);
419 vreader_list_unlock(void)
421 g_mutex_unlock(&vreader_list_mutex
);
425 vreader_copy_list(VReaderList
*list
)
427 VReaderList
*new_list
;
428 VReaderListEntry
*current_entry
;
430 new_list
= vreader_list_new();
431 if (new_list
== NULL
) {
434 for (current_entry
= vreader_list_get_first(list
); current_entry
;
435 current_entry
= vreader_list_get_next(current_entry
)) {
436 VReader
*reader
= vreader_list_get_reader(current_entry
);
437 VReaderListEntry
*new_entry
= vreader_list_entry_new(reader
);
439 vreader_free(reader
);
440 vreader_queue(new_list
, new_entry
);
446 vreader_get_reader_list(void)
448 VReaderList
*new_reader_list
;
451 new_reader_list
= vreader_copy_list(vreader_list
);
452 vreader_list_unlock();
453 return new_reader_list
;
457 vreader_get_reader_by_id(vreader_id_t id
)
459 VReader
*reader
= NULL
;
460 VReaderListEntry
*current_entry
;
462 if (id
== (vreader_id_t
) -1) {
467 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
468 current_entry
= vreader_list_get_next(current_entry
)) {
469 VReader
*creader
= vreader_list_get_reader(current_entry
);
470 if (creader
->id
== id
) {
474 vreader_free(creader
);
476 vreader_list_unlock();
481 vreader_get_reader_by_name(const char *name
)
483 VReader
*reader
= NULL
;
484 VReaderListEntry
*current_entry
;
487 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
488 current_entry
= vreader_list_get_next(current_entry
)) {
489 VReader
*creader
= vreader_list_get_reader(current_entry
);
490 if (strcmp(creader
->name
, name
) == 0) {
494 vreader_free(creader
);
496 vreader_list_unlock();
500 /* called from card_emul to initialize the readers */
502 vreader_add_reader(VReader
*reader
)
504 VReaderListEntry
*reader_entry
;
506 reader_entry
= vreader_list_entry_new(reader
);
507 if (reader_entry
== NULL
) {
508 return VREADER_OUT_OF_MEMORY
;
511 vreader_queue(vreader_list
, reader_entry
);
512 vreader_list_unlock();
513 vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT
, reader
, NULL
));
519 vreader_remove_reader(VReader
*reader
)
521 VReaderListEntry
*current_entry
;
524 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
525 current_entry
= vreader_list_get_next(current_entry
)) {
526 if (current_entry
->reader
== reader
) {
530 vreader_dequeue(vreader_list
, current_entry
);
531 vreader_list_unlock();
532 vreader_list_entry_delete(current_entry
);
533 vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE
, reader
, NULL
));
538 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
539 * state. Separated from vreader_insert_card to allow replaying events
543 vreader_queue_card_event(VReader
*reader
)
545 vevent_queue_vevent(vevent_new(
546 reader
->card
? VEVENT_CARD_INSERT
: VEVENT_CARD_REMOVE
, reader
,
551 * insert/remove a new card. for removal, card == NULL
554 vreader_insert_card(VReader
*reader
, VCard
*card
)
556 vreader_lock(reader
);
558 /* decrement reference count */
559 vcard_free(reader
->card
);
562 reader
->card
= vcard_reference(card
);
563 vreader_unlock(reader
);
564 vreader_queue_card_event(reader
);
569 * initialize all the static reader structures