2 * Implement the 7816 portion of the card spec
4 * This code is licensed under the GNU LGPL, version 2.1 or later.
5 * See the COPYING.LIB file in the top-level directory.
8 #include "qemu-common.h"
11 #include "vcard_emul.h"
12 #include "card_7816.h"
15 * set the status bytes based on the status word
18 vcard_response_set_status(VCardResponse
*response
, vcard_7816_status_t status
)
20 unsigned char sw1
, sw2
;
21 response
->b_status
= status
; /* make sure the status and swX representations
23 sw1
= (status
>> 8) & 0xff;
25 response
->b_sw1
= sw1
;
26 response
->b_sw2
= sw2
;
27 response
->b_data
[response
->b_len
] = sw1
;
28 response
->b_data
[response
->b_len
+1] = sw2
;
32 * set the status bytes in a response buffer
35 vcard_response_set_status_bytes(VCardResponse
*response
,
36 unsigned char sw1
, unsigned char sw2
)
38 response
->b_status
= sw1
<< 8 | sw2
;
39 response
->b_sw1
= sw1
;
40 response
->b_sw2
= sw2
;
41 response
->b_data
[response
->b_len
] = sw1
;
42 response
->b_data
[response
->b_len
+1] = sw2
;
46 * allocate a VCardResponse structure, plus space for the data buffer, and
47 * set up everything but the resonse bytes.
50 vcard_response_new_data(unsigned char *buf
, int len
)
52 VCardResponse
*new_response
;
54 new_response
= (VCardResponse
*)g_malloc(sizeof(VCardResponse
));
55 new_response
->b_data
= g_malloc(len
+ 2);
56 memcpy(new_response
->b_data
, buf
, len
);
57 new_response
->b_total_len
= len
+2;
58 new_response
->b_len
= len
;
59 new_response
->b_type
= VCARD_MALLOC
;
63 static VCardResponse
*
64 vcard_init_buffer_response(VCard
*card
, unsigned char *buf
, int len
)
66 VCardResponse
*response
;
67 VCardBufferResponse
*buffer_response
;
69 buffer_response
= vcard_get_buffer_response(card
);
70 if (buffer_response
) {
71 vcard_set_buffer_response(card
, NULL
);
72 vcard_buffer_response_delete(buffer_response
);
74 buffer_response
= vcard_buffer_response_new(buf
, len
);
75 if (buffer_response
== NULL
) {
78 response
= vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES
,
80 if (response
== NULL
) {
83 vcard_set_buffer_response(card
, buffer_response
);
88 * general buffer to hold results from APDU calls
91 vcard_response_new(VCard
*card
, unsigned char *buf
,
92 int len
, int Le
, vcard_7816_status_t status
)
94 VCardResponse
*new_response
;
97 return vcard_init_buffer_response(card
, buf
, len
);
99 new_response
= vcard_response_new_data(buf
, len
);
100 if (new_response
== NULL
) {
103 vcard_response_set_status(new_response
, status
);
108 * general buffer to hold results from APDU calls
111 vcard_response_new_bytes(VCard
*card
, unsigned char *buf
, int len
, int Le
,
112 unsigned char sw1
, unsigned char sw2
)
114 VCardResponse
*new_response
;
117 return vcard_init_buffer_response(card
, buf
, len
);
119 new_response
= vcard_response_new_data(buf
, len
);
120 if (new_response
== NULL
) {
123 vcard_response_set_status_bytes(new_response
, sw1
, sw2
);
128 * get a new Reponse buffer that only has a status.
130 static VCardResponse
*
131 vcard_response_new_status(vcard_7816_status_t status
)
133 VCardResponse
*new_response
;
135 new_response
= (VCardResponse
*)g_malloc(sizeof(VCardResponse
));
136 new_response
->b_data
= &new_response
->b_sw1
;
137 new_response
->b_len
= 0;
138 new_response
->b_total_len
= 2;
139 new_response
->b_type
= VCARD_MALLOC_STRUCT
;
140 vcard_response_set_status(new_response
, status
);
145 * same as above, but specify the status as separate bytes
148 vcard_response_new_status_bytes(unsigned char sw1
, unsigned char sw2
)
150 VCardResponse
*new_response
;
152 new_response
= (VCardResponse
*)g_malloc(sizeof(VCardResponse
));
153 new_response
->b_data
= &new_response
->b_sw1
;
154 new_response
->b_len
= 0;
155 new_response
->b_total_len
= 2;
156 new_response
->b_type
= VCARD_MALLOC_STRUCT
;
157 vcard_response_set_status_bytes(new_response
, sw1
, sw2
);
163 * free the response buffer. The Buffer has a type to handle the buffer
164 * allocated in other ways than through malloc.
167 vcard_response_delete(VCardResponse
*response
)
169 if (response
== NULL
) {
172 switch (response
->b_type
) {
174 /* everything was malloc'ed */
175 if (response
->b_data
) {
176 g_free(response
->b_data
);
180 case VCARD_MALLOC_DATA
:
181 /* only the data buffer was malloc'ed */
182 if (response
->b_data
) {
183 g_free(response
->b_data
);
186 case VCARD_MALLOC_STRUCT
:
187 /* only the structure was malloc'ed */
196 * decode the class bit and set our generic type field, channel, and
197 * secure messaging values.
199 static vcard_7816_status_t
200 vcard_apdu_set_class(VCardAPDU
*apdu
) {
202 apdu
->a_secure_messaging
= 0;
203 apdu
->a_type
= apdu
->a_cla
& 0xf0;
204 apdu
->a_gen_type
= VCARD_7816_ISO
;
206 /* parse the class tables 8 & 9 of the 7816-4 Part 4 spec */
207 switch (apdu
->a_type
) {
208 /* we only support the basic types */
213 apdu
->a_channel
= apdu
->a_cla
& 3;
214 apdu
->a_secure_messaging
= apdu
->a_cla
& 0xe;
227 /* Reserved for future use */
228 apdu
->a_gen_type
= VCARD_7816_RFU
;
235 (apdu
->a_cla
== 0xff) ? VCARD_7816_PTS
: VCARD_7816_PROPIETARY
;
238 return VCARD7816_STATUS_SUCCESS
;
242 * set the Le and Lc fiels according to table 5 of the
245 static vcard_7816_status_t
246 vcard_apdu_set_length(VCardAPDU
*apdu
)
250 /* process according to table 5 of the 7816-4 Part 4 spec.
251 * variable names match the variables in the spec */
252 L
= apdu
->a_len
-4; /* fixed APDU header */
259 return VCARD7816_STATUS_SUCCESS
;
261 /* 2S only return values apdu */
262 /* zero maps to 256 here */
263 apdu
->a_Le
= apdu
->a_header
->ah_Le
?
264 apdu
->a_header
->ah_Le
: 256;
265 return VCARD7816_STATUS_SUCCESS
;
267 /* if the ah_Le byte is zero and we have more than
268 * 1 byte in the header, then we must be using extended Le and Lc.
269 * process the extended now. */
270 if (apdu
->a_header
->ah_Le
== 0) {
272 /* coding error, need at least 3 bytes */
273 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
275 /* calculate the first extended value. Could be either Le or Lc */
276 Le
= (apdu
->a_header
->ah_body
[0] << 8)
277 || apdu
->a_header
->ah_body
[1];
279 /* 2E extended, return data only */
280 /* zero maps to 65536 */
281 apdu
->a_Le
= Le
? Le
: 65536;
282 return VCARD7816_STATUS_SUCCESS
;
285 /* reserved for future use, probably for next time we need
286 * to extend the lengths */
287 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
289 /* we know that the first extended value is Lc now */
291 apdu
->a_body
= &apdu
->a_header
->ah_body
[2];
293 /* 3E extended, only body parameters */
294 return VCARD7816_STATUS_SUCCESS
;
297 /* 4E extended, parameters and return data */
298 Le
= (apdu
->a_data
[apdu
->a_len
-2] << 8)
299 || apdu
->a_data
[apdu
->a_len
-1];
300 apdu
->a_Le
= Le
? Le
: 65536;
301 return VCARD7816_STATUS_SUCCESS
;
303 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
306 apdu
->a_Lc
= apdu
->a_header
->ah_Le
;
307 apdu
->a_body
= &apdu
->a_header
->ah_body
[0];
308 if (L
== apdu
->a_Lc
+ 1) {
309 /* 3S only body parameters */
310 return VCARD7816_STATUS_SUCCESS
;
312 if (L
== apdu
->a_Lc
+ 2) {
313 /* 4S parameters and return data */
314 Le
= apdu
->a_data
[apdu
->a_len
-1];
315 apdu
->a_Le
= Le
? Le
: 256;
316 return VCARD7816_STATUS_SUCCESS
;
320 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
324 * create a new APDU from a raw set of bytes. This will decode all the
325 * above fields. users of VCARDAPDU's can then depend on the already decoded
329 vcard_apdu_new(unsigned char *raw_apdu
, int len
, vcard_7816_status_t
*status
)
333 *status
= VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
;
335 *status
= VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
339 new_apdu
= (VCardAPDU
*)g_malloc(sizeof(VCardAPDU
));
340 new_apdu
->a_data
= g_malloc(len
);
341 memcpy(new_apdu
->a_data
, raw_apdu
, len
);
342 new_apdu
->a_len
= len
;
343 *status
= vcard_apdu_set_class(new_apdu
);
344 if (*status
!= VCARD7816_STATUS_SUCCESS
) {
348 *status
= vcard_apdu_set_length(new_apdu
);
349 if (*status
!= VCARD7816_STATUS_SUCCESS
) {
357 vcard_apdu_delete(VCardAPDU
*apdu
)
363 g_free(apdu
->a_data
);
370 * declare response buffers for all the 7816 defined error codes
372 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS
)
373 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING
)
374 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT
)
375 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
)
376 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
)
377 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
)
378 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE
)
379 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED
)
380 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR
)
381 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE
)
382 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
)
383 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH
)
384 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
)
385 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
)
386 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
)
387 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
)
388 VCARD_RESPONSE_NEW_STATIC_STATUS(
389 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
)
390 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
)
391 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
)
392 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID
)
393 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
)
394 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF
)
395 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
)
396 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
)
397 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
)
398 VCARD_RESPONSE_NEW_STATIC_STATUS(
399 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
)
400 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
)
401 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
)
402 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
)
403 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
)
404 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
)
405 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
)
406 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
)
407 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
)
408 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
)
409 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID
)
410 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID
)
411 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL
)
414 * return a single response code. This function cannot fail. It will always
418 vcard_make_response(vcard_7816_status_t status
)
420 VCardResponse
*response
= NULL
;
423 /* known 7816 response codes */
424 case VCARD7816_STATUS_SUCCESS
:
425 return VCARD_RESPONSE_GET_STATIC(
426 VCARD7816_STATUS_SUCCESS
);
427 case VCARD7816_STATUS_WARNING
:
428 return VCARD_RESPONSE_GET_STATIC(
429 VCARD7816_STATUS_WARNING
);
430 case VCARD7816_STATUS_WARNING_RET_CORUPT
:
431 return VCARD_RESPONSE_GET_STATIC(
432 VCARD7816_STATUS_WARNING_RET_CORUPT
);
433 case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
:
434 return VCARD_RESPONSE_GET_STATIC(
435 VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
);
436 case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
:
437 return VCARD_RESPONSE_GET_STATIC(
438 VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
);
439 case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
:
440 return VCARD_RESPONSE_GET_STATIC(
441 VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
);
442 case VCARD7816_STATUS_WARNING_CHANGE
:
443 return VCARD_RESPONSE_GET_STATIC(
444 VCARD7816_STATUS_WARNING_CHANGE
);
445 case VCARD7816_STATUS_WARNING_FILE_FILLED
:
446 return VCARD_RESPONSE_GET_STATIC(
447 VCARD7816_STATUS_WARNING_FILE_FILLED
);
448 case VCARD7816_STATUS_EXC_ERROR
:
449 return VCARD_RESPONSE_GET_STATIC(
450 VCARD7816_STATUS_EXC_ERROR
);
451 case VCARD7816_STATUS_EXC_ERROR_CHANGE
:
452 return VCARD_RESPONSE_GET_STATIC(
453 VCARD7816_STATUS_EXC_ERROR_CHANGE
);
454 case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
:
455 return VCARD_RESPONSE_GET_STATIC(
456 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
457 case VCARD7816_STATUS_ERROR_WRONG_LENGTH
:
458 return VCARD_RESPONSE_GET_STATIC(
459 VCARD7816_STATUS_ERROR_WRONG_LENGTH
);
460 case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
:
461 return VCARD_RESPONSE_GET_STATIC(
462 VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
);
463 case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
:
464 return VCARD_RESPONSE_GET_STATIC(
465 VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
);
466 case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
:
467 return VCARD_RESPONSE_GET_STATIC(
468 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
);
469 case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
:
470 return VCARD_RESPONSE_GET_STATIC(
471 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
472 case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
:
473 return VCARD_RESPONSE_GET_STATIC(
474 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
);
475 case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
:
476 return VCARD_RESPONSE_GET_STATIC(
477 VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
);
478 case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
:
479 return VCARD_RESPONSE_GET_STATIC(
480 VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
);
481 case VCARD7816_STATUS_ERROR_DATA_INVALID
:
482 return VCARD_RESPONSE_GET_STATIC(
483 VCARD7816_STATUS_ERROR_DATA_INVALID
);
484 case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
:
485 return VCARD_RESPONSE_GET_STATIC(
486 VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
);
487 case VCARD7816_STATUS_ERROR_DATA_NO_EF
:
488 return VCARD_RESPONSE_GET_STATIC(
489 VCARD7816_STATUS_ERROR_DATA_NO_EF
);
490 case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
:
491 return VCARD_RESPONSE_GET_STATIC(
492 VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
);
493 case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
:
494 return VCARD_RESPONSE_GET_STATIC(
495 VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
);
496 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
:
497 return VCARD_RESPONSE_GET_STATIC(
498 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
);
499 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
:
500 return VCARD_RESPONSE_GET_STATIC(
501 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
);
502 case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
:
503 return VCARD_RESPONSE_GET_STATIC(
504 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
);
505 case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
:
506 return VCARD_RESPONSE_GET_STATIC(
507 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
);
508 case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
:
509 return VCARD_RESPONSE_GET_STATIC(
510 VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
);
511 case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
:
512 return VCARD_RESPONSE_GET_STATIC(
513 VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
);
514 case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
:
515 return VCARD_RESPONSE_GET_STATIC(
516 VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
);
517 case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
:
518 return VCARD_RESPONSE_GET_STATIC(
519 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
);
520 case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
:
521 return VCARD_RESPONSE_GET_STATIC(
522 VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
);
523 case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
:
524 return VCARD_RESPONSE_GET_STATIC(
525 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
526 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
:
527 return VCARD_RESPONSE_GET_STATIC(
528 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
);
529 case VCARD7816_STATUS_ERROR_INS_CODE_INVALID
:
530 return VCARD_RESPONSE_GET_STATIC(
531 VCARD7816_STATUS_ERROR_INS_CODE_INVALID
);
532 case VCARD7816_STATUS_ERROR_CLA_INVALID
:
533 return VCARD_RESPONSE_GET_STATIC(
534 VCARD7816_STATUS_ERROR_CLA_INVALID
);
535 case VCARD7816_STATUS_ERROR_GENERAL
:
536 return VCARD_RESPONSE_GET_STATIC(
537 VCARD7816_STATUS_ERROR_GENERAL
);
539 /* we don't know this status code, create a response buffer to
541 response
= vcard_response_new_status(status
);
542 if (response
== NULL
) {
543 /* couldn't allocate the buffer, return memmory error */
544 return VCARD_RESPONSE_GET_STATIC(
545 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
553 * Add File card support here if you need it.
556 vcard7816_file_system_process_apdu(VCard
*card
, VCardAPDU
*apdu
,
557 VCardResponse
**response
)
559 /* TODO: if we want to support a virtual file system card, we do it here.
560 * It would probably be a pkcs #15 card type */
561 *response
= vcard_make_response(
562 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
567 * VM card (including java cards)
570 vcard7816_vm_process_apdu(VCard
*card
, VCardAPDU
*apdu
,
571 VCardResponse
**response
)
573 int bytes_to_copy
, next_byte_count
, count
;
574 VCardApplet
*current_applet
;
575 VCardBufferResponse
*buffer_response
;
576 vcard_7816_status_t status
;
578 /* parse the class first */
579 if (apdu
->a_gen_type
!= VCARD_7816_ISO
) {
580 *response
= vcard_make_response(
581 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
585 /* use a switch so that if we need to support secure channel stuff later,
586 * we know where to put it */
587 switch (apdu
->a_secure_messaging
) {
588 case 0x0: /* no SM */
590 case 0x4: /* proprietary SM */
591 case 0x8: /* header not authenticated */
592 case 0xc: /* header authenticated */
594 /* for now, don't try to support secure channel stuff in the
596 *response
= vcard_make_response(
597 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
);
601 /* now parse the instruction */
602 switch (apdu
->a_ins
) {
603 case VCARD7816_INS_MANAGE_CHANNEL
: /* secure channel op */
604 case VCARD7816_INS_EXTERNAL_AUTHENTICATE
: /* secure channel op */
605 case VCARD7816_INS_GET_CHALLENGE
: /* secure channel op */
606 case VCARD7816_INS_INTERNAL_AUTHENTICATE
: /* secure channel op */
607 case VCARD7816_INS_ERASE_BINARY
: /* applet control op */
608 case VCARD7816_INS_READ_BINARY
: /* applet control op */
609 case VCARD7816_INS_WRITE_BINARY
: /* applet control op */
610 case VCARD7816_INS_UPDATE_BINARY
: /* applet control op */
611 case VCARD7816_INS_READ_RECORD
: /* file op */
612 case VCARD7816_INS_WRITE_RECORD
: /* file op */
613 case VCARD7816_INS_UPDATE_RECORD
: /* file op */
614 case VCARD7816_INS_APPEND_RECORD
: /* file op */
615 case VCARD7816_INS_ENVELOPE
:
616 case VCARD7816_INS_PUT_DATA
:
617 *response
= vcard_make_response(
618 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
621 case VCARD7816_INS_SELECT_FILE
:
622 if (apdu
->a_p1
!= 0x04) {
623 *response
= vcard_make_response(
624 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
);
628 /* side effect, deselect the current applet if no applet has been found
630 current_applet
= vcard_find_applet(card
, apdu
->a_body
, apdu
->a_Lc
);
631 vcard_select_applet(card
, apdu
->a_channel
, current_applet
);
632 if (current_applet
) {
635 aid
= vcard_applet_get_aid(current_applet
, &aid_len
);
636 *response
= vcard_response_new(card
, aid
, aid_len
, apdu
->a_Le
,
637 VCARD7816_STATUS_SUCCESS
);
639 *response
= vcard_make_response(
640 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
);
644 case VCARD7816_INS_VERIFY
:
645 if ((apdu
->a_p1
!= 0x00) || (apdu
->a_p2
!= 0x00)) {
646 *response
= vcard_make_response(
647 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
);
649 if (apdu
->a_Lc
== 0) {
650 /* handle pin count if possible */
651 count
= vcard_emul_get_login_count(card
);
653 *response
= vcard_make_response(
654 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
659 *response
= vcard_response_new_status_bytes(
660 VCARD7816_SW1_WARNING_CHANGE
,
662 if (*response
== NULL
) {
663 *response
= vcard_make_response(
664 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
668 status
= vcard_emul_login(card
, apdu
->a_body
, apdu
->a_Lc
);
669 *response
= vcard_make_response(status
);
674 case VCARD7816_INS_GET_RESPONSE
:
675 buffer_response
= vcard_get_buffer_response(card
);
676 if (!buffer_response
) {
677 *response
= vcard_make_response(
678 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
682 bytes_to_copy
= MIN(buffer_response
->len
, apdu
->a_Le
);
683 next_byte_count
= MIN(256, buffer_response
->len
- bytes_to_copy
);
684 *response
= vcard_response_new_bytes(
685 card
, buffer_response
->current
, bytes_to_copy
,
688 VCARD7816_SW1_RESPONSE_BYTES
: VCARD7816_SW1_SUCCESS
,
690 buffer_response
->current
+= bytes_to_copy
;
691 buffer_response
->len
-= bytes_to_copy
;
692 if (*response
== NULL
|| (next_byte_count
== 0)) {
693 vcard_set_buffer_response(card
, NULL
);
694 vcard_buffer_response_delete(buffer_response
);
696 if (*response
== NULL
) {
698 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
702 case VCARD7816_INS_GET_DATA
:
704 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
709 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
713 /* response should have been set somewhere */
714 assert(*response
!= NULL
);
720 * APDU processing starts here. This routes the card processing stuff to the
724 vcard_process_apdu(VCard
*card
, VCardAPDU
*apdu
, VCardResponse
**response
)
727 VCardBufferResponse
*buffer_response
;
729 /* first handle any PTS commands, which aren't really APDU's */
730 if (apdu
->a_type
== VCARD_7816_PTS
) {
731 /* the PTS responses aren't really responses either */
732 *response
= vcard_response_new_data(apdu
->a_data
, apdu
->a_len
);
733 /* PTS responses have no status bytes */
734 (*response
)->b_total_len
= (*response
)->b_len
;
737 buffer_response
= vcard_get_buffer_response(card
);
738 if (buffer_response
&& apdu
->a_ins
!= VCARD7816_INS_GET_RESPONSE
) {
739 /* clear out buffer_response, return an error */
740 vcard_set_buffer_response(card
, NULL
);
741 vcard_buffer_response_delete(buffer_response
);
742 *response
= vcard_make_response(VCARD7816_STATUS_EXC_ERROR
);
746 status
= vcard_process_applet_apdu(card
, apdu
, response
);
747 if (status
!= VCARD_NEXT
) {
750 switch (vcard_get_type(card
)) {
751 case VCARD_FILE_SYSTEM
:
752 return vcard7816_file_system_process_apdu(card
, apdu
, response
);
754 return vcard7816_vm_process_apdu(card
, apdu
, response
);
756 /* if we are type direct, then the applet should handle everything */
757 assert("VCARD_DIRECT: applet failure");
761 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);