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 "glib-compat.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 g_mutex_lock(&reader
->lock
);
104 vreader_unlock(VReader
*reader
)
106 g_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 g_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
);
155 g_mutex_clear(&reader
->lock
);
157 vcard_free(reader
->card
);
159 g_free(reader
->name
);
160 if (reader
->reader_private_free
) {
161 reader
->reader_private_free(reader
->reader_private
);
167 vreader_get_card(VReader
*reader
)
171 vreader_lock(reader
);
172 card
= vcard_reference(reader
->card
);
173 vreader_unlock(reader
);
178 vreader_card_is_present(VReader
*reader
)
180 VCard
*card
= vreader_get_card(reader
);
183 return VREADER_NO_CARD
;
190 vreader_get_id(VReader
*reader
)
192 if (reader
== NULL
) {
193 return (vreader_id_t
)-1;
199 vreader_set_id(VReader
*reader
, vreader_id_t id
)
201 if (reader
== NULL
) {
202 return VREADER_NO_CARD
;
209 vreader_get_name(VReader
*reader
)
211 if (reader
== NULL
) {
218 vreader_get_private(VReader
*reader
)
220 return reader
->reader_private
;
224 vreader_reset(VReader
*reader
, VCardPower power
, unsigned char *atr
, int *len
)
226 VCard
*card
= vreader_get_card(reader
);
229 return VREADER_NO_CARD
;
234 vcard_reset(card
, power
);
236 vcard_get_atr(card
, atr
, len
);
238 vcard_free(card
); /* free our reference */
243 vreader_power_on(VReader
*reader
, unsigned char *atr
, int *len
)
245 return vreader_reset(reader
, VCARD_POWER_ON
, atr
, len
);
249 vreader_power_off(VReader
*reader
)
251 return vreader_reset(reader
, VCARD_POWER_OFF
, NULL
, 0);
256 vreader_xfr_bytes(VReader
*reader
,
257 unsigned char *send_buf
, int send_buf_len
,
258 unsigned char *receive_buf
, int *receive_buf_len
)
261 VCardResponse
*response
= NULL
;
262 VCardStatus card_status
;
263 unsigned short status
;
264 VCard
*card
= vreader_get_card(reader
);
267 return VREADER_NO_CARD
;
270 apdu
= vcard_apdu_new(send_buf
, send_buf_len
, &status
);
272 response
= vcard_make_response(status
);
273 card_status
= VCARD_DONE
;
275 g_debug("%s: CLS=0x%x,INS=0x%x,P1=0x%x,P2=0x%x,Lc=%d,Le=%d %s",
276 __func__
, apdu
->a_cla
, apdu
->a_ins
, apdu
->a_p1
, apdu
->a_p2
,
277 apdu
->a_Lc
, apdu
->a_Le
, apdu_ins_to_string(apdu
->a_ins
));
278 card_status
= vcard_process_apdu(card
, apdu
, &response
);
280 g_debug("%s: status=%d sw1=0x%x sw2=0x%x len=%d (total=%d)",
281 __func__
, response
->b_status
, response
->b_sw1
,
282 response
->b_sw2
, response
->b_len
, response
->b_total_len
);
285 assert(card_status
== VCARD_DONE
&& response
);
286 int size
= MIN(*receive_buf_len
, response
->b_total_len
);
287 memcpy(receive_buf
, response
->b_data
, size
);
288 *receive_buf_len
= size
;
289 vcard_response_delete(response
);
290 vcard_apdu_delete(apdu
);
291 vcard_free(card
); /* free our reference */
295 struct VReaderListStruct
{
296 VReaderListEntry
*head
;
297 VReaderListEntry
*tail
;
300 struct VReaderListEntryStruct
{
301 VReaderListEntry
*next
;
302 VReaderListEntry
*prev
;
307 static VReaderListEntry
*
308 vreader_list_entry_new(VReader
*reader
)
310 VReaderListEntry
*new_reader_list_entry
;
312 new_reader_list_entry
= g_new0(VReaderListEntry
, 1);
313 new_reader_list_entry
->reader
= vreader_reference(reader
);
314 return new_reader_list_entry
;
318 vreader_list_entry_delete(VReaderListEntry
*entry
)
323 vreader_free(entry
->reader
);
329 vreader_list_new(void)
331 VReaderList
*new_reader_list
;
333 new_reader_list
= g_new0(VReaderList
, 1);
334 return new_reader_list
;
338 vreader_list_delete(VReaderList
*list
)
340 VReaderListEntry
*current_entry
;
341 VReaderListEntry
*next_entry
;
342 for (current_entry
= vreader_list_get_first(list
); current_entry
;
343 current_entry
= next_entry
) {
344 next_entry
= vreader_list_get_next(current_entry
);
345 vreader_list_entry_delete(current_entry
);
352 vreader_list_get_first(VReaderList
*list
)
354 return list
? list
->head
: NULL
;
358 vreader_list_get_next(VReaderListEntry
*current
)
360 return current
? current
->next
: NULL
;
364 vreader_list_get_reader(VReaderListEntry
*entry
)
366 return entry
? vreader_reference(entry
->reader
) : NULL
;
370 vreader_queue(VReaderList
*list
, VReaderListEntry
*entry
)
376 entry
->prev
= list
->tail
;
378 list
->tail
->next
= entry
;
386 vreader_dequeue(VReaderList
*list
, VReaderListEntry
*entry
)
391 if (entry
->next
== NULL
) {
392 list
->tail
= entry
->prev
;
393 } else if (entry
->prev
== NULL
) {
394 list
->head
= entry
->next
;
396 entry
->prev
->next
= entry
->next
;
397 entry
->next
->prev
= entry
->prev
;
399 if ((list
->tail
== NULL
) || (list
->head
== NULL
)) {
400 list
->head
= list
->tail
= NULL
;
402 entry
->next
= entry
->prev
= NULL
;
405 static VReaderList
*vreader_list
;
406 static CompatGMutex vreader_list_mutex
;
409 vreader_list_init(void)
411 vreader_list
= vreader_list_new();
415 vreader_list_lock(void)
417 g_mutex_lock(&vreader_list_mutex
);
421 vreader_list_unlock(void)
423 g_mutex_unlock(&vreader_list_mutex
);
427 vreader_copy_list(VReaderList
*list
)
429 VReaderList
*new_list
;
430 VReaderListEntry
*current_entry
;
432 new_list
= vreader_list_new();
433 if (new_list
== NULL
) {
436 for (current_entry
= vreader_list_get_first(list
); current_entry
;
437 current_entry
= vreader_list_get_next(current_entry
)) {
438 VReader
*reader
= vreader_list_get_reader(current_entry
);
439 VReaderListEntry
*new_entry
= vreader_list_entry_new(reader
);
441 vreader_free(reader
);
442 vreader_queue(new_list
, new_entry
);
448 vreader_get_reader_list(void)
450 VReaderList
*new_reader_list
;
453 new_reader_list
= vreader_copy_list(vreader_list
);
454 vreader_list_unlock();
455 return new_reader_list
;
459 vreader_get_reader_by_id(vreader_id_t id
)
461 VReader
*reader
= NULL
;
462 VReaderListEntry
*current_entry
;
464 if (id
== (vreader_id_t
) -1) {
469 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
470 current_entry
= vreader_list_get_next(current_entry
)) {
471 VReader
*creader
= vreader_list_get_reader(current_entry
);
472 if (creader
->id
== id
) {
476 vreader_free(creader
);
478 vreader_list_unlock();
483 vreader_get_reader_by_name(const char *name
)
485 VReader
*reader
= NULL
;
486 VReaderListEntry
*current_entry
;
489 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
490 current_entry
= vreader_list_get_next(current_entry
)) {
491 VReader
*creader
= vreader_list_get_reader(current_entry
);
492 if (strcmp(creader
->name
, name
) == 0) {
496 vreader_free(creader
);
498 vreader_list_unlock();
502 /* called from card_emul to initialize the readers */
504 vreader_add_reader(VReader
*reader
)
506 VReaderListEntry
*reader_entry
;
508 reader_entry
= vreader_list_entry_new(reader
);
509 if (reader_entry
== NULL
) {
510 return VREADER_OUT_OF_MEMORY
;
513 vreader_queue(vreader_list
, reader_entry
);
514 vreader_list_unlock();
515 vevent_queue_vevent(vevent_new(VEVENT_READER_INSERT
, reader
, NULL
));
521 vreader_remove_reader(VReader
*reader
)
523 VReaderListEntry
*current_entry
;
526 for (current_entry
= vreader_list_get_first(vreader_list
); current_entry
;
527 current_entry
= vreader_list_get_next(current_entry
)) {
528 if (current_entry
->reader
== reader
) {
532 vreader_dequeue(vreader_list
, current_entry
);
533 vreader_list_unlock();
534 vreader_list_entry_delete(current_entry
);
535 vevent_queue_vevent(vevent_new(VEVENT_READER_REMOVE
, reader
, NULL
));
540 * Generate VEVENT_CARD_INSERT or VEVENT_CARD_REMOVE based on vreader
541 * state. Separated from vreader_insert_card to allow replaying events
545 vreader_queue_card_event(VReader
*reader
)
547 vevent_queue_vevent(vevent_new(
548 reader
->card
? VEVENT_CARD_INSERT
: VEVENT_CARD_REMOVE
, reader
,
553 * insert/remove a new card. for removal, card == NULL
556 vreader_insert_card(VReader
*reader
, VCard
*card
)
558 vreader_lock(reader
);
560 /* decrement reference count */
561 vcard_free(reader
->card
);
564 reader
->card
= vcard_reference(card
);
565 vreader_unlock(reader
);
566 vreader_queue_card_event(reader
);
571 * initialize all the static reader structures