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 "glib-compat.h"
13 #include "vcard_emul.h"
14 #include "card_7816.h"
17 * set the status bytes based on the status word
20 vcard_response_set_status(VCardResponse
*response
, vcard_7816_status_t status
)
22 unsigned char sw1
, sw2
;
23 response
->b_status
= status
; /* make sure the status and swX representations
25 sw1
= (status
>> 8) & 0xff;
27 response
->b_sw1
= sw1
;
28 response
->b_sw2
= sw2
;
29 response
->b_data
[response
->b_len
] = sw1
;
30 response
->b_data
[response
->b_len
+1] = sw2
;
34 * set the status bytes in a response buffer
37 vcard_response_set_status_bytes(VCardResponse
*response
,
38 unsigned char sw1
, unsigned char sw2
)
40 response
->b_status
= sw1
<< 8 | sw2
;
41 response
->b_sw1
= sw1
;
42 response
->b_sw2
= sw2
;
43 response
->b_data
[response
->b_len
] = sw1
;
44 response
->b_data
[response
->b_len
+1] = sw2
;
48 * allocate a VCardResponse structure, plus space for the data buffer, and
49 * set up everything but the resonse bytes.
52 vcard_response_new_data(unsigned char *buf
, int len
)
54 VCardResponse
*new_response
;
56 new_response
= g_new(VCardResponse
, 1);
57 new_response
->b_data
= g_malloc(len
+ 2);
58 memcpy(new_response
->b_data
, buf
, len
);
59 new_response
->b_total_len
= len
+2;
60 new_response
->b_len
= len
;
61 new_response
->b_type
= VCARD_MALLOC
;
65 static VCardResponse
*
66 vcard_init_buffer_response(VCard
*card
, unsigned char *buf
, int len
)
68 VCardResponse
*response
;
69 VCardBufferResponse
*buffer_response
;
71 buffer_response
= vcard_get_buffer_response(card
);
72 if (buffer_response
) {
73 vcard_set_buffer_response(card
, NULL
);
74 vcard_buffer_response_delete(buffer_response
);
76 buffer_response
= vcard_buffer_response_new(buf
, len
);
77 if (buffer_response
== NULL
) {
80 response
= vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES
,
82 if (response
== NULL
) {
85 vcard_set_buffer_response(card
, buffer_response
);
90 * general buffer to hold results from APDU calls
93 vcard_response_new(VCard
*card
, unsigned char *buf
,
94 int len
, int Le
, vcard_7816_status_t status
)
96 VCardResponse
*new_response
;
99 return vcard_init_buffer_response(card
, buf
, len
);
101 new_response
= vcard_response_new_data(buf
, len
);
102 if (new_response
== NULL
) {
105 vcard_response_set_status(new_response
, status
);
110 * general buffer to hold results from APDU calls
113 vcard_response_new_bytes(VCard
*card
, unsigned char *buf
, int len
, int Le
,
114 unsigned char sw1
, unsigned char sw2
)
116 VCardResponse
*new_response
;
119 return vcard_init_buffer_response(card
, buf
, len
);
121 new_response
= vcard_response_new_data(buf
, len
);
122 if (new_response
== NULL
) {
125 vcard_response_set_status_bytes(new_response
, sw1
, sw2
);
130 * get a new Response buffer that only has a status.
132 static VCardResponse
*
133 vcard_response_new_status(vcard_7816_status_t status
)
135 VCardResponse
*new_response
;
137 new_response
= g_new(VCardResponse
, 1);
138 new_response
->b_data
= &new_response
->b_sw1
;
139 new_response
->b_len
= 0;
140 new_response
->b_total_len
= 2;
141 new_response
->b_type
= VCARD_MALLOC_STRUCT
;
142 vcard_response_set_status(new_response
, status
);
147 * same as above, but specify the status as separate bytes
150 vcard_response_new_status_bytes(unsigned char sw1
, unsigned char sw2
)
152 VCardResponse
*new_response
;
154 new_response
= g_new(VCardResponse
, 1);
155 new_response
->b_data
= &new_response
->b_sw1
;
156 new_response
->b_len
= 0;
157 new_response
->b_total_len
= 2;
158 new_response
->b_type
= VCARD_MALLOC_STRUCT
;
159 vcard_response_set_status_bytes(new_response
, sw1
, sw2
);
165 * free the response buffer. The Buffer has a type to handle the buffer
166 * allocated in other ways than through malloc.
169 vcard_response_delete(VCardResponse
*response
)
171 if (response
== NULL
) {
174 switch (response
->b_type
) {
176 /* everything was malloc'ed */
177 g_free(response
->b_data
);
180 case VCARD_MALLOC_DATA
:
181 /* only the data buffer was malloc'ed */
182 g_free(response
->b_data
);
184 case VCARD_MALLOC_STRUCT
:
185 /* only the structure was malloc'ed */
194 * decode the class bit and set our generic type field, channel, and
195 * secure messaging values.
197 static vcard_7816_status_t
198 vcard_apdu_set_class(VCardAPDU
*apdu
) {
200 apdu
->a_secure_messaging
= 0;
201 apdu
->a_type
= apdu
->a_cla
& 0xf0;
202 apdu
->a_gen_type
= VCARD_7816_ISO
;
204 /* parse the class tables 8 & 9 of the 7816-4 Part 4 spec */
205 switch (apdu
->a_type
) {
206 /* we only support the basic types */
211 apdu
->a_channel
= apdu
->a_cla
& 3;
212 apdu
->a_secure_messaging
= apdu
->a_cla
& 0xe;
225 /* Reserved for future use */
226 apdu
->a_gen_type
= VCARD_7816_RFU
;
233 (apdu
->a_cla
== 0xff) ? VCARD_7816_PTS
: VCARD_7816_PROPRIETARY
;
236 return VCARD7816_STATUS_SUCCESS
;
240 * set the Le and Lc fields according to table 5 of the
243 static vcard_7816_status_t
244 vcard_apdu_set_length(VCardAPDU
*apdu
)
248 /* process according to table 5 of the 7816-4 Part 4 spec.
249 * variable names match the variables in the spec */
250 L
= apdu
->a_len
-4; /* fixed APDU header */
257 return VCARD7816_STATUS_SUCCESS
;
259 /* 2S only return values apdu */
260 /* zero maps to 256 here */
261 apdu
->a_Le
= apdu
->a_header
->ah_Le
?
262 apdu
->a_header
->ah_Le
: 256;
263 return VCARD7816_STATUS_SUCCESS
;
265 /* if the ah_Le byte is zero and we have more than
266 * 1 byte in the header, then we must be using extended Le and Lc.
267 * process the extended now. */
268 if (apdu
->a_header
->ah_Le
== 0) {
270 /* coding error, need at least 3 bytes */
271 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
273 /* calculate the first extended value. Could be either Le or Lc */
274 Le
= (apdu
->a_header
->ah_body
[0] << 8)
275 || apdu
->a_header
->ah_body
[1];
277 /* 2E extended, return data only */
278 /* zero maps to 65536 */
279 apdu
->a_Le
= Le
? Le
: 65536;
280 return VCARD7816_STATUS_SUCCESS
;
283 /* reserved for future use, probably for next time we need
284 * to extend the lengths */
285 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
287 /* we know that the first extended value is Lc now */
289 apdu
->a_body
= &apdu
->a_header
->ah_body
[2];
291 /* 3E extended, only body parameters */
292 return VCARD7816_STATUS_SUCCESS
;
295 /* 4E extended, parameters and return data */
296 Le
= (apdu
->a_data
[apdu
->a_len
-2] << 8)
297 || apdu
->a_data
[apdu
->a_len
-1];
298 apdu
->a_Le
= Le
? Le
: 65536;
299 return VCARD7816_STATUS_SUCCESS
;
301 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
304 apdu
->a_Lc
= apdu
->a_header
->ah_Le
;
305 apdu
->a_body
= &apdu
->a_header
->ah_body
[0];
306 if (L
== apdu
->a_Lc
+ 1) {
307 /* 3S only body parameters */
308 return VCARD7816_STATUS_SUCCESS
;
310 if (L
== apdu
->a_Lc
+ 2) {
311 /* 4S parameters and return data */
312 Le
= apdu
->a_data
[apdu
->a_len
-1];
313 apdu
->a_Le
= Le
? Le
: 256;
314 return VCARD7816_STATUS_SUCCESS
;
318 return VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
322 * create a new APDU from a raw set of bytes. This will decode all the
323 * above fields. users of VCARDAPDU's can then depend on the already decoded
327 vcard_apdu_new(unsigned char *raw_apdu
, int len
, vcard_7816_status_t
*status
)
331 *status
= VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
;
333 *status
= VCARD7816_STATUS_ERROR_WRONG_LENGTH
;
337 new_apdu
= g_new(VCardAPDU
, 1);
338 new_apdu
->a_data
= g_memdup(raw_apdu
, len
);
339 new_apdu
->a_len
= len
;
340 *status
= vcard_apdu_set_class(new_apdu
);
341 if (*status
!= VCARD7816_STATUS_SUCCESS
) {
345 *status
= vcard_apdu_set_length(new_apdu
);
346 if (*status
!= VCARD7816_STATUS_SUCCESS
) {
354 vcard_apdu_delete(VCardAPDU
*apdu
)
359 g_free(apdu
->a_data
);
365 * declare response buffers for all the 7816 defined error codes
367 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS
)
368 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING
)
369 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT
)
370 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
)
371 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
)
372 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
)
373 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE
)
374 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED
)
375 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR
)
376 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE
)
377 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
)
378 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH
)
379 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
)
380 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
)
381 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
)
382 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
)
383 VCARD_RESPONSE_NEW_STATIC_STATUS(
384 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
)
385 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
)
386 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
)
387 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID
)
388 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
)
389 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF
)
390 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
)
391 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
)
392 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
)
393 VCARD_RESPONSE_NEW_STATIC_STATUS(
394 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
)
395 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
)
396 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
)
397 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
)
398 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
)
399 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
)
400 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
)
401 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
)
402 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
)
403 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
)
404 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID
)
405 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID
)
406 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL
)
409 * return a single response code. This function cannot fail. It will always
413 vcard_make_response(vcard_7816_status_t status
)
415 VCardResponse
*response
;
418 /* known 7816 response codes */
419 case VCARD7816_STATUS_SUCCESS
:
420 return VCARD_RESPONSE_GET_STATIC(
421 VCARD7816_STATUS_SUCCESS
);
422 case VCARD7816_STATUS_WARNING
:
423 return VCARD_RESPONSE_GET_STATIC(
424 VCARD7816_STATUS_WARNING
);
425 case VCARD7816_STATUS_WARNING_RET_CORUPT
:
426 return VCARD_RESPONSE_GET_STATIC(
427 VCARD7816_STATUS_WARNING_RET_CORUPT
);
428 case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
:
429 return VCARD_RESPONSE_GET_STATIC(
430 VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE
);
431 case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
:
432 return VCARD_RESPONSE_GET_STATIC(
433 VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED
);
434 case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
:
435 return VCARD_RESPONSE_GET_STATIC(
436 VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID
);
437 case VCARD7816_STATUS_WARNING_CHANGE
:
438 return VCARD_RESPONSE_GET_STATIC(
439 VCARD7816_STATUS_WARNING_CHANGE
);
440 case VCARD7816_STATUS_WARNING_FILE_FILLED
:
441 return VCARD_RESPONSE_GET_STATIC(
442 VCARD7816_STATUS_WARNING_FILE_FILLED
);
443 case VCARD7816_STATUS_EXC_ERROR
:
444 return VCARD_RESPONSE_GET_STATIC(
445 VCARD7816_STATUS_EXC_ERROR
);
446 case VCARD7816_STATUS_EXC_ERROR_CHANGE
:
447 return VCARD_RESPONSE_GET_STATIC(
448 VCARD7816_STATUS_EXC_ERROR_CHANGE
);
449 case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
:
450 return VCARD_RESPONSE_GET_STATIC(
451 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
452 case VCARD7816_STATUS_ERROR_WRONG_LENGTH
:
453 return VCARD_RESPONSE_GET_STATIC(
454 VCARD7816_STATUS_ERROR_WRONG_LENGTH
);
455 case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
:
456 return VCARD_RESPONSE_GET_STATIC(
457 VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED
);
458 case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
:
459 return VCARD_RESPONSE_GET_STATIC(
460 VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED
);
461 case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
:
462 return VCARD_RESPONSE_GET_STATIC(
463 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
);
464 case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
:
465 return VCARD_RESPONSE_GET_STATIC(
466 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
467 case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
:
468 return VCARD_RESPONSE_GET_STATIC(
469 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE
);
470 case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
:
471 return VCARD_RESPONSE_GET_STATIC(
472 VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED
);
473 case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
:
474 return VCARD_RESPONSE_GET_STATIC(
475 VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED
);
476 case VCARD7816_STATUS_ERROR_DATA_INVALID
:
477 return VCARD_RESPONSE_GET_STATIC(
478 VCARD7816_STATUS_ERROR_DATA_INVALID
);
479 case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
:
480 return VCARD_RESPONSE_GET_STATIC(
481 VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED
);
482 case VCARD7816_STATUS_ERROR_DATA_NO_EF
:
483 return VCARD_RESPONSE_GET_STATIC(
484 VCARD7816_STATUS_ERROR_DATA_NO_EF
);
485 case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
:
486 return VCARD_RESPONSE_GET_STATIC(
487 VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING
);
488 case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
:
489 return VCARD_RESPONSE_GET_STATIC(
490 VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT
);
491 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
:
492 return VCARD_RESPONSE_GET_STATIC(
493 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
);
494 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
:
495 return VCARD_RESPONSE_GET_STATIC(
496 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA
);
497 case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
:
498 return VCARD_RESPONSE_GET_STATIC(
499 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
);
500 case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
:
501 return VCARD_RESPONSE_GET_STATIC(
502 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
);
503 case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
:
504 return VCARD_RESPONSE_GET_STATIC(
505 VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND
);
506 case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
:
507 return VCARD_RESPONSE_GET_STATIC(
508 VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE
);
509 case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
:
510 return VCARD_RESPONSE_GET_STATIC(
511 VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT
);
512 case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
:
513 return VCARD_RESPONSE_GET_STATIC(
514 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT
);
515 case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
:
516 return VCARD_RESPONSE_GET_STATIC(
517 VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT
);
518 case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
:
519 return VCARD_RESPONSE_GET_STATIC(
520 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
521 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
:
522 return VCARD_RESPONSE_GET_STATIC(
523 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2
);
524 case VCARD7816_STATUS_ERROR_INS_CODE_INVALID
:
525 return VCARD_RESPONSE_GET_STATIC(
526 VCARD7816_STATUS_ERROR_INS_CODE_INVALID
);
527 case VCARD7816_STATUS_ERROR_CLA_INVALID
:
528 return VCARD_RESPONSE_GET_STATIC(
529 VCARD7816_STATUS_ERROR_CLA_INVALID
);
530 case VCARD7816_STATUS_ERROR_GENERAL
:
531 return VCARD_RESPONSE_GET_STATIC(
532 VCARD7816_STATUS_ERROR_GENERAL
);
534 /* we don't know this status code, create a response buffer to
536 response
= vcard_response_new_status(status
);
537 if (response
== NULL
) {
538 /* couldn't allocate the buffer, return memmory error */
539 return VCARD_RESPONSE_GET_STATIC(
540 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
547 * Add File card support here if you need it.
550 vcard7816_file_system_process_apdu(VCard
*card
, VCardAPDU
*apdu
,
551 VCardResponse
**response
)
553 /* TODO: if we want to support a virtual file system card, we do it here.
554 * It would probably be a pkcs #15 card type */
555 *response
= vcard_make_response(
556 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
561 * VM card (including java cards)
564 vcard7816_vm_process_apdu(VCard
*card
, VCardAPDU
*apdu
,
565 VCardResponse
**response
)
567 int bytes_to_copy
, next_byte_count
, count
;
568 VCardApplet
*current_applet
;
569 VCardBufferResponse
*buffer_response
;
570 vcard_7816_status_t status
;
572 /* parse the class first */
573 if (apdu
->a_gen_type
!= VCARD_7816_ISO
) {
574 *response
= vcard_make_response(
575 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
579 /* use a switch so that if we need to support secure channel stuff later,
580 * we know where to put it */
581 switch (apdu
->a_secure_messaging
) {
582 case 0x0: /* no SM */
584 case 0x4: /* proprietary SM */
585 case 0x8: /* header not authenticated */
586 case 0xc: /* header authenticated */
588 /* for now, don't try to support secure channel stuff in the
590 *response
= vcard_make_response(
591 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED
);
595 /* now parse the instruction */
596 switch (apdu
->a_ins
) {
597 case VCARD7816_INS_MANAGE_CHANNEL
: /* secure channel op */
598 case VCARD7816_INS_EXTERNAL_AUTHENTICATE
: /* secure channel op */
599 case VCARD7816_INS_GET_CHALLENGE
: /* secure channel op */
600 case VCARD7816_INS_INTERNAL_AUTHENTICATE
: /* secure channel op */
601 case VCARD7816_INS_ERASE_BINARY
: /* applet control op */
602 case VCARD7816_INS_READ_BINARY
: /* applet control op */
603 case VCARD7816_INS_WRITE_BINARY
: /* applet control op */
604 case VCARD7816_INS_UPDATE_BINARY
: /* applet control op */
605 case VCARD7816_INS_READ_RECORD
: /* file op */
606 case VCARD7816_INS_WRITE_RECORD
: /* file op */
607 case VCARD7816_INS_UPDATE_RECORD
: /* file op */
608 case VCARD7816_INS_APPEND_RECORD
: /* file op */
609 case VCARD7816_INS_ENVELOPE
:
610 case VCARD7816_INS_PUT_DATA
:
611 *response
= vcard_make_response(
612 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
615 case VCARD7816_INS_SELECT_FILE
:
616 if (apdu
->a_p1
!= 0x04) {
617 *response
= vcard_make_response(
618 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED
);
622 /* side effect, deselect the current applet if no applet has been found
624 current_applet
= vcard_find_applet(card
, apdu
->a_body
, apdu
->a_Lc
);
625 vcard_select_applet(card
, apdu
->a_channel
, current_applet
);
626 if (current_applet
) {
629 aid
= vcard_applet_get_aid(current_applet
, &aid_len
);
630 *response
= vcard_response_new(card
, aid
, aid_len
, apdu
->a_Le
,
631 VCARD7816_STATUS_SUCCESS
);
633 *response
= vcard_make_response(
634 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND
);
638 case VCARD7816_INS_VERIFY
:
639 if ((apdu
->a_p1
!= 0x00) || (apdu
->a_p2
!= 0x00)) {
640 *response
= vcard_make_response(
641 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS
);
643 if (apdu
->a_Lc
== 0) {
644 /* handle pin count if possible */
645 count
= vcard_emul_get_login_count(card
);
647 *response
= vcard_make_response(
648 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
653 *response
= vcard_response_new_status_bytes(
654 VCARD7816_SW1_WARNING_CHANGE
,
656 if (*response
== NULL
) {
657 *response
= vcard_make_response(
658 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
662 status
= vcard_emul_login(card
, apdu
->a_body
, apdu
->a_Lc
);
663 *response
= vcard_make_response(status
);
668 case VCARD7816_INS_GET_RESPONSE
:
669 buffer_response
= vcard_get_buffer_response(card
);
670 if (!buffer_response
) {
671 *response
= vcard_make_response(
672 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND
);
676 bytes_to_copy
= MIN(buffer_response
->len
, apdu
->a_Le
);
677 next_byte_count
= MIN(256, buffer_response
->len
- bytes_to_copy
);
678 *response
= vcard_response_new_bytes(
679 card
, buffer_response
->current
, bytes_to_copy
,
682 VCARD7816_SW1_RESPONSE_BYTES
: VCARD7816_SW1_SUCCESS
,
684 buffer_response
->current
+= bytes_to_copy
;
685 buffer_response
->len
-= bytes_to_copy
;
686 if (*response
== NULL
|| (next_byte_count
== 0)) {
687 vcard_set_buffer_response(card
, NULL
);
688 vcard_buffer_response_delete(buffer_response
);
690 if (*response
== NULL
) {
692 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE
);
696 case VCARD7816_INS_GET_DATA
:
698 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
703 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);
707 /* response should have been set somewhere */
708 assert(*response
!= NULL
);
714 * APDU processing starts here. This routes the card processing stuff to the
718 vcard_process_apdu(VCard
*card
, VCardAPDU
*apdu
, VCardResponse
**response
)
721 VCardBufferResponse
*buffer_response
;
723 /* first handle any PTS commands, which aren't really APDU's */
724 if (apdu
->a_type
== VCARD_7816_PTS
) {
725 /* the PTS responses aren't really responses either */
726 *response
= vcard_response_new_data(apdu
->a_data
, apdu
->a_len
);
727 /* PTS responses have no status bytes */
728 (*response
)->b_total_len
= (*response
)->b_len
;
731 buffer_response
= vcard_get_buffer_response(card
);
732 if (buffer_response
&& apdu
->a_ins
!= VCARD7816_INS_GET_RESPONSE
) {
733 /* clear out buffer_response, return an error */
734 vcard_set_buffer_response(card
, NULL
);
735 vcard_buffer_response_delete(buffer_response
);
736 *response
= vcard_make_response(VCARD7816_STATUS_EXC_ERROR
);
740 status
= vcard_process_applet_apdu(card
, apdu
, response
);
741 if (status
!= VCARD_NEXT
) {
744 switch (vcard_get_type(card
)) {
745 case VCARD_FILE_SYSTEM
:
746 return vcard7816_file_system_process_apdu(card
, apdu
, response
);
748 return vcard7816_vm_process_apdu(card
, apdu
, response
);
750 /* if we are type direct, then the applet should handle everything */
751 assert(!"VCARD_DIRECT: applet failure");
755 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED
);