Add qemu 2.4.0
[kvmfornfv.git] / qemu / libcacard / card_7816.c
1 /*
2  * Implement the 7816 portion of the card spec
3  *
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.
6  */
7
8 #include "glib-compat.h"
9
10 #include <string.h>
11
12 #include "vcard.h"
13 #include "vcard_emul.h"
14 #include "card_7816.h"
15
16 /*
17  * set the status bytes based on the status word
18  */
19 static void
20 vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
21 {
22     unsigned char sw1, sw2;
23     response->b_status = status; /* make sure the status and swX representations
24                                   * are consistent */
25     sw1 = (status >> 8) & 0xff;
26     sw2 = status & 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;
31 }
32
33 /*
34  * set the status bytes in a response buffer
35  */
36 static void
37 vcard_response_set_status_bytes(VCardResponse *response,
38                                unsigned char sw1, unsigned char sw2)
39 {
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;
45 }
46
47 /*
48  * allocate a VCardResponse structure, plus space for the data buffer, and
49  * set up everything but the resonse bytes.
50  */
51 VCardResponse *
52 vcard_response_new_data(unsigned char *buf, int len)
53 {
54     VCardResponse *new_response;
55
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;
62     return new_response;
63 }
64
65 static VCardResponse *
66 vcard_init_buffer_response(VCard *card, unsigned char *buf, int len)
67 {
68     VCardResponse *response;
69     VCardBufferResponse *buffer_response;
70
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);
75     }
76     buffer_response = vcard_buffer_response_new(buf, len);
77     if (buffer_response == NULL) {
78         return NULL;
79     }
80     response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
81                                                len > 255 ? 0 : len);
82     if (response == NULL) {
83         return NULL;
84     }
85     vcard_set_buffer_response(card, buffer_response);
86     return response;
87 }
88
89 /*
90  * general buffer to hold results from APDU calls
91  */
92 VCardResponse *
93 vcard_response_new(VCard *card, unsigned char *buf,
94                    int len, int Le, vcard_7816_status_t status)
95 {
96     VCardResponse *new_response;
97
98     if (len > Le) {
99         return vcard_init_buffer_response(card, buf, len);
100     }
101     new_response = vcard_response_new_data(buf, len);
102     if (new_response == NULL) {
103         return NULL;
104     }
105     vcard_response_set_status(new_response, status);
106     return new_response;
107 }
108
109 /*
110  * general buffer to hold results from APDU calls
111  */
112 VCardResponse *
113 vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
114                          unsigned char sw1, unsigned char sw2)
115 {
116     VCardResponse *new_response;
117
118     if (len > Le) {
119         return vcard_init_buffer_response(card, buf, len);
120     }
121     new_response = vcard_response_new_data(buf, len);
122     if (new_response == NULL) {
123         return NULL;
124     }
125     vcard_response_set_status_bytes(new_response, sw1, sw2);
126     return new_response;
127 }
128
129 /*
130  * get a new Response buffer that only has a status.
131  */
132 static VCardResponse *
133 vcard_response_new_status(vcard_7816_status_t status)
134 {
135     VCardResponse *new_response;
136
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);
143     return new_response;
144 }
145
146 /*
147  * same as above, but specify the status as separate bytes
148  */
149 VCardResponse *
150 vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
151 {
152     VCardResponse *new_response;
153
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);
160     return new_response;
161 }
162
163
164 /*
165  * free the response buffer. The Buffer has a type to handle the buffer
166  * allocated in other ways than through malloc.
167  */
168 void
169 vcard_response_delete(VCardResponse *response)
170 {
171     if (response == NULL) {
172         return;
173     }
174     switch (response->b_type) {
175     case VCARD_MALLOC:
176         /* everything was malloc'ed */
177         g_free(response->b_data);
178         g_free(response);
179         break;
180     case VCARD_MALLOC_DATA:
181         /* only the data buffer was malloc'ed */
182         g_free(response->b_data);
183         break;
184     case VCARD_MALLOC_STRUCT:
185         /* only the structure was malloc'ed */
186         g_free(response);
187         break;
188     case VCARD_STATIC:
189         break;
190     }
191 }
192
193 /*
194  * decode the class bit and set our generic type field, channel, and
195  * secure messaging values.
196  */
197 static vcard_7816_status_t
198 vcard_apdu_set_class(VCardAPDU *apdu) {
199     apdu->a_channel = 0;
200     apdu->a_secure_messaging = 0;
201     apdu->a_type = apdu->a_cla & 0xf0;
202     apdu->a_gen_type = VCARD_7816_ISO;
203
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 */
207     case 0x00:
208     case 0x80:
209     case 0x90:
210     case 0xa0:
211         apdu->a_channel = apdu->a_cla & 3;
212         apdu->a_secure_messaging = apdu->a_cla & 0xe;
213         break;
214     case 0xb0:
215     case 0xc0:
216         break;
217
218     case 0x10:
219     case 0x20:
220     case 0x30:
221     case 0x40:
222     case 0x50:
223     case 0x60:
224     case 0x70:
225         /* Reserved for future use */
226         apdu->a_gen_type = VCARD_7816_RFU;
227         break;
228     case 0xd0:
229     case 0xe0:
230     case 0xf0:
231     default:
232         apdu->a_gen_type =
233             (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
234         break;
235     }
236     return VCARD7816_STATUS_SUCCESS;
237 }
238
239 /*
240  * set the Le and Lc fields according to table 5 of the
241  * 7816-4 part 4 spec
242  */
243 static vcard_7816_status_t
244 vcard_apdu_set_length(VCardAPDU *apdu)
245 {
246     int L, Le;
247
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 */
251     apdu->a_Lc = 0;
252     apdu->a_Le = 0;
253     apdu->a_body = NULL;
254     switch (L) {
255     case 0:
256         /* 1 minimal apdu */
257         return VCARD7816_STATUS_SUCCESS;
258     case 1:
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;
264     default:
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) {
269             if (L < 3) {
270                 /* coding error, need at least 3 bytes */
271                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
272             }
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];
276             if (L == 3) {
277                 /* 2E extended, return data only */
278                 /*   zero maps to 65536 */
279                 apdu->a_Le = Le ? Le : 65536;
280                 return VCARD7816_STATUS_SUCCESS;
281             }
282             if (Le == 0) {
283                 /* reserved for future use, probably for next time we need
284                  * to extend the lengths */
285                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
286             }
287             /* we know that the first extended value is Lc now */
288             apdu->a_Lc = Le;
289             apdu->a_body = &apdu->a_header->ah_body[2];
290             if (L == Le+3) {
291                 /* 3E extended, only body parameters */
292                 return VCARD7816_STATUS_SUCCESS;
293             }
294             if (L == Le+5) {
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;
300             }
301             return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
302         }
303         /* not extended */
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;
309         }
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;
315         }
316         break;
317     }
318     return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
319 }
320
321 /*
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
324  * values.
325  */
326 VCardAPDU *
327 vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
328 {
329     VCardAPDU *new_apdu;
330
331     *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
332     if (len < 4) {
333         *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
334         return NULL;
335     }
336
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) {
342         g_free(new_apdu);
343         return NULL;
344     }
345     *status = vcard_apdu_set_length(new_apdu);
346     if (*status != VCARD7816_STATUS_SUCCESS) {
347         g_free(new_apdu);
348         new_apdu = NULL;
349     }
350     return new_apdu;
351 }
352
353 void
354 vcard_apdu_delete(VCardAPDU *apdu)
355 {
356     if (apdu == NULL) {
357         return;
358     }
359     g_free(apdu->a_data);
360     g_free(apdu);
361 }
362
363
364 /*
365  * declare response buffers for all the 7816 defined error codes
366  */
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)
407
408 /*
409  * return a single response code. This function cannot fail. It will always
410  * return a response.
411  */
412 VCardResponse *
413 vcard_make_response(vcard_7816_status_t status)
414 {
415     VCardResponse *response;
416
417     switch (status) {
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);
533     default:
534         /* we don't know this status code, create a response buffer to
535          * hold it */
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);
541         }
542         return response;
543     }
544 }
545
546 /*
547  * Add File card support here if you need it.
548  */
549 static VCardStatus
550 vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
551                                    VCardResponse **response)
552 {
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);
557     return VCARD_DONE;
558 }
559
560 /*
561  * VM card (including java cards)
562  */
563 static VCardStatus
564 vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
565                           VCardResponse **response)
566 {
567     int bytes_to_copy, next_byte_count, count;
568     VCardApplet *current_applet;
569     VCardBufferResponse *buffer_response;
570     vcard_7816_status_t status;
571
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);
576         return VCARD_DONE;
577     }
578
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 */
583         break;
584     case 0x4: /* proprietary SM */
585     case 0x8: /* header not authenticated */
586     case 0xc: /* header authenticated */
587     default:
588         /* for now, don't try to support secure channel stuff in the
589          * virtual card. */
590         *response = vcard_make_response(
591                         VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
592         return VCARD_DONE;
593     }
594
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);
613         break;
614
615     case  VCARD7816_INS_SELECT_FILE:
616         if (apdu->a_p1 != 0x04) {
617             *response = vcard_make_response(
618                             VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
619             break;
620         }
621
622         /* side effect, deselect the current applet if no applet has been found
623          * */
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) {
627             unsigned char *aid;
628             int aid_len;
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);
632         } else {
633             *response = vcard_make_response(
634                              VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
635         }
636         break;
637
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);
642         } else {
643             if (apdu->a_Lc == 0) {
644                 /* handle pin count if possible */
645                 count = vcard_emul_get_login_count(card);
646                 if (count < 0) {
647                     *response = vcard_make_response(
648                                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
649                 } else {
650                     if (count > 0xf) {
651                         count = 0xf;
652                     }
653                     *response = vcard_response_new_status_bytes(
654                                                 VCARD7816_SW1_WARNING_CHANGE,
655                                                                 0xc0 | count);
656                     if (*response == NULL) {
657                         *response = vcard_make_response(
658                                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
659                     }
660                 }
661             } else {
662                     status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
663                 *response = vcard_make_response(status);
664             }
665         }
666         break;
667
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);
673             /* handle error */
674             break;
675         }
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,
680                         apdu->a_Le,
681                         next_byte_count ?
682                         VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
683                         next_byte_count);
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);
689         }
690         if (*response == NULL) {
691             *response =
692                 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
693         }
694         break;
695
696     case VCARD7816_INS_GET_DATA:
697         *response =
698             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
699         break;
700
701     default:
702         *response =
703             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
704         break;
705     }
706
707     /* response should have been set somewhere */
708     assert(*response != NULL);
709     return VCARD_DONE;
710 }
711
712
713 /*
714  * APDU processing starts here. This routes the card processing stuff to the
715  * right location.
716  */
717 VCardStatus
718 vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
719 {
720     VCardStatus status;
721     VCardBufferResponse *buffer_response;
722
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;
729         return VCARD_DONE;
730     }
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);
737         return VCARD_DONE;
738     }
739
740     status = vcard_process_applet_apdu(card, apdu, response);
741     if (status != VCARD_NEXT) {
742         return status;
743     }
744     switch (vcard_get_type(card)) {
745     case VCARD_FILE_SYSTEM:
746         return vcard7816_file_system_process_apdu(card, apdu, response);
747     case VCARD_VM:
748         return vcard7816_vm_process_apdu(card, apdu, response);
749     case VCARD_DIRECT:
750         /* if we are type direct, then the applet should handle everything */
751         assert(!"VCARD_DIRECT: applet failure");
752         break;
753     }
754     *response =
755         vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
756     return VCARD_DONE;
757 }