]> Git Repo - qemu.git/blob - libcacard/card_7816.c
target-arm: Correct condition for taking VIRQ and VFIQ
[qemu.git] / 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 "qemu-common.h"
9
10 #include "vcard.h"
11 #include "vcard_emul.h"
12 #include "card_7816.h"
13
14 /*
15  * set the status bytes based on the status word
16  */
17 static void
18 vcard_response_set_status(VCardResponse *response, vcard_7816_status_t status)
19 {
20     unsigned char sw1, sw2;
21     response->b_status = status; /* make sure the status and swX representations
22                                   * are consistent */
23     sw1 = (status >> 8) & 0xff;
24     sw2 = status & 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;
29 }
30
31 /*
32  * set the status bytes in a response buffer
33  */
34 static void
35 vcard_response_set_status_bytes(VCardResponse *response,
36                                unsigned char sw1, unsigned char sw2)
37 {
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;
43 }
44
45 /*
46  * allocate a VCardResponse structure, plus space for the data buffer, and
47  * set up everything but the resonse bytes.
48  */
49 VCardResponse *
50 vcard_response_new_data(unsigned char *buf, int len)
51 {
52     VCardResponse *new_response;
53
54     new_response = g_new(VCardResponse, 1);
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;
60     return new_response;
61 }
62
63 static VCardResponse *
64 vcard_init_buffer_response(VCard *card, unsigned char *buf, int len)
65 {
66     VCardResponse *response;
67     VCardBufferResponse *buffer_response;
68
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);
73     }
74     buffer_response = vcard_buffer_response_new(buf, len);
75     if (buffer_response == NULL) {
76         return NULL;
77     }
78     response = vcard_response_new_status_bytes(VCARD7816_SW1_RESPONSE_BYTES,
79                                                len > 255 ? 0 : len);
80     if (response == NULL) {
81         return NULL;
82     }
83     vcard_set_buffer_response(card, buffer_response);
84     return response;
85 }
86
87 /*
88  * general buffer to hold results from APDU calls
89  */
90 VCardResponse *
91 vcard_response_new(VCard *card, unsigned char *buf,
92                    int len, int Le, vcard_7816_status_t status)
93 {
94     VCardResponse *new_response;
95
96     if (len > Le) {
97         return vcard_init_buffer_response(card, buf, len);
98     }
99     new_response = vcard_response_new_data(buf, len);
100     if (new_response == NULL) {
101         return NULL;
102     }
103     vcard_response_set_status(new_response, status);
104     return new_response;
105 }
106
107 /*
108  * general buffer to hold results from APDU calls
109  */
110 VCardResponse *
111 vcard_response_new_bytes(VCard *card, unsigned char *buf, int len, int Le,
112                          unsigned char sw1, unsigned char sw2)
113 {
114     VCardResponse *new_response;
115
116     if (len > Le) {
117         return vcard_init_buffer_response(card, buf, len);
118     }
119     new_response = vcard_response_new_data(buf, len);
120     if (new_response == NULL) {
121         return NULL;
122     }
123     vcard_response_set_status_bytes(new_response, sw1, sw2);
124     return new_response;
125 }
126
127 /*
128  * get a new Response buffer that only has a status.
129  */
130 static VCardResponse *
131 vcard_response_new_status(vcard_7816_status_t status)
132 {
133     VCardResponse *new_response;
134
135     new_response = g_new(VCardResponse, 1);
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);
141     return new_response;
142 }
143
144 /*
145  * same as above, but specify the status as separate bytes
146  */
147 VCardResponse *
148 vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
149 {
150     VCardResponse *new_response;
151
152     new_response = g_new(VCardResponse, 1);
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);
158     return new_response;
159 }
160
161
162 /*
163  * free the response buffer. The Buffer has a type to handle the buffer
164  * allocated in other ways than through malloc.
165  */
166 void
167 vcard_response_delete(VCardResponse *response)
168 {
169     if (response == NULL) {
170         return;
171     }
172     switch (response->b_type) {
173     case VCARD_MALLOC:
174         /* everything was malloc'ed */
175         g_free(response->b_data);
176         g_free(response);
177         break;
178     case VCARD_MALLOC_DATA:
179         /* only the data buffer was malloc'ed */
180         g_free(response->b_data);
181         break;
182     case VCARD_MALLOC_STRUCT:
183         /* only the structure was malloc'ed */
184         g_free(response);
185         break;
186     case VCARD_STATIC:
187         break;
188     }
189 }
190
191 /*
192  * decode the class bit and set our generic type field, channel, and
193  * secure messaging values.
194  */
195 static vcard_7816_status_t
196 vcard_apdu_set_class(VCardAPDU *apdu) {
197     apdu->a_channel = 0;
198     apdu->a_secure_messaging = 0;
199     apdu->a_type = apdu->a_cla & 0xf0;
200     apdu->a_gen_type = VCARD_7816_ISO;
201
202     /* parse the class  tables 8 & 9 of the 7816-4 Part 4 spec */
203     switch (apdu->a_type) {
204         /* we only support the basic types */
205     case 0x00:
206     case 0x80:
207     case 0x90:
208     case 0xa0:
209         apdu->a_channel = apdu->a_cla & 3;
210         apdu->a_secure_messaging = apdu->a_cla & 0xe;
211         break;
212     case 0xb0:
213     case 0xc0:
214         break;
215
216     case 0x10:
217     case 0x20:
218     case 0x30:
219     case 0x40:
220     case 0x50:
221     case 0x60:
222     case 0x70:
223         /* Reserved for future use */
224         apdu->a_gen_type = VCARD_7816_RFU;
225         break;
226     case 0xd0:
227     case 0xe0:
228     case 0xf0:
229     default:
230         apdu->a_gen_type =
231             (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
232         break;
233     }
234     return VCARD7816_STATUS_SUCCESS;
235 }
236
237 /*
238  * set the Le and Lc fields according to table 5 of the
239  * 7816-4 part 4 spec
240  */
241 static vcard_7816_status_t
242 vcard_apdu_set_length(VCardAPDU *apdu)
243 {
244     int L, Le;
245
246     /* process according to table 5 of the 7816-4 Part 4 spec.
247      * variable names match the variables in the spec */
248     L = apdu->a_len-4; /* fixed APDU header */
249     apdu->a_Lc = 0;
250     apdu->a_Le = 0;
251     apdu->a_body = NULL;
252     switch (L) {
253     case 0:
254         /* 1 minimal apdu */
255         return VCARD7816_STATUS_SUCCESS;
256     case 1:
257         /* 2S only return values apdu */
258         /*   zero maps to 256 here */
259         apdu->a_Le = apdu->a_header->ah_Le ?
260                          apdu->a_header->ah_Le : 256;
261         return VCARD7816_STATUS_SUCCESS;
262     default:
263         /* if the ah_Le byte is zero and we have more than
264          * 1 byte in the header, then we must be using extended Le and Lc.
265          * process the extended now. */
266         if (apdu->a_header->ah_Le == 0) {
267             if (L < 3) {
268                 /* coding error, need at least 3 bytes */
269                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
270             }
271             /* calculate the first extended value. Could be either Le or Lc */
272             Le = (apdu->a_header->ah_body[0] << 8)
273                || apdu->a_header->ah_body[1];
274             if (L == 3) {
275                 /* 2E extended, return data only */
276                 /*   zero maps to 65536 */
277                 apdu->a_Le = Le ? Le : 65536;
278                 return VCARD7816_STATUS_SUCCESS;
279             }
280             if (Le == 0) {
281                 /* reserved for future use, probably for next time we need
282                  * to extend the lengths */
283                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
284             }
285             /* we know that the first extended value is Lc now */
286             apdu->a_Lc = Le;
287             apdu->a_body = &apdu->a_header->ah_body[2];
288             if (L == Le+3) {
289                 /* 3E extended, only body parameters */
290                 return VCARD7816_STATUS_SUCCESS;
291             }
292             if (L == Le+5) {
293                 /* 4E extended, parameters and return data */
294                 Le = (apdu->a_data[apdu->a_len-2] << 8)
295                    || apdu->a_data[apdu->a_len-1];
296                 apdu->a_Le = Le ? Le : 65536;
297                 return VCARD7816_STATUS_SUCCESS;
298             }
299             return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
300         }
301         /* not extended */
302         apdu->a_Lc = apdu->a_header->ah_Le;
303         apdu->a_body = &apdu->a_header->ah_body[0];
304         if (L ==  apdu->a_Lc + 1) {
305             /* 3S only body parameters */
306             return VCARD7816_STATUS_SUCCESS;
307         }
308         if (L ==  apdu->a_Lc + 2) {
309             /* 4S parameters and return data */
310             Le = apdu->a_data[apdu->a_len-1];
311             apdu->a_Le = Le ?  Le : 256;
312             return VCARD7816_STATUS_SUCCESS;
313         }
314         break;
315     }
316     return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
317 }
318
319 /*
320  * create a new APDU from a raw set of bytes. This will decode all the
321  * above fields. users of VCARDAPDU's can then depend on the already decoded
322  * values.
323  */
324 VCardAPDU *
325 vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
326 {
327     VCardAPDU *new_apdu;
328
329     *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
330     if (len < 4) {
331         *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
332         return NULL;
333     }
334
335     new_apdu = g_new(VCardAPDU, 1);
336     new_apdu->a_data = g_memdup(raw_apdu, len);
337     new_apdu->a_len = len;
338     *status = vcard_apdu_set_class(new_apdu);
339     if (*status != VCARD7816_STATUS_SUCCESS) {
340         g_free(new_apdu);
341         return NULL;
342     }
343     *status = vcard_apdu_set_length(new_apdu);
344     if (*status != VCARD7816_STATUS_SUCCESS) {
345         g_free(new_apdu);
346         new_apdu = NULL;
347     }
348     return new_apdu;
349 }
350
351 void
352 vcard_apdu_delete(VCardAPDU *apdu)
353 {
354     if (apdu == NULL) {
355         return;
356     }
357     g_free(apdu->a_data);
358     g_free(apdu);
359 }
360
361
362 /*
363  * declare response buffers for all the 7816 defined error codes
364  */
365 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
366 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
367 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
368 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
369 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
370 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
371 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
372 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
373 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
374 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
375 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
376 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
377 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
378 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
379 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
380 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
381 VCARD_RESPONSE_NEW_STATIC_STATUS(
382                     VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
383 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
384 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
385 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
386 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
387 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
388 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
389 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
390 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
391 VCARD_RESPONSE_NEW_STATIC_STATUS(
392                             VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
393 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
394 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
395 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
396 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
397 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
398 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
399 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
400 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
401 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
402 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
403 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
404 VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
405
406 /*
407  * return a single response code. This function cannot fail. It will always
408  * return a response.
409  */
410 VCardResponse *
411 vcard_make_response(vcard_7816_status_t status)
412 {
413     VCardResponse *response;
414
415     switch (status) {
416     /* known 7816 response codes */
417     case VCARD7816_STATUS_SUCCESS:
418         return VCARD_RESPONSE_GET_STATIC(
419                     VCARD7816_STATUS_SUCCESS);
420     case VCARD7816_STATUS_WARNING:
421         return VCARD_RESPONSE_GET_STATIC(
422                     VCARD7816_STATUS_WARNING);
423     case VCARD7816_STATUS_WARNING_RET_CORUPT:
424         return VCARD_RESPONSE_GET_STATIC(
425                     VCARD7816_STATUS_WARNING_RET_CORUPT);
426     case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
427         return VCARD_RESPONSE_GET_STATIC(
428                     VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
429     case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
430         return VCARD_RESPONSE_GET_STATIC(
431                     VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
432     case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
433         return VCARD_RESPONSE_GET_STATIC(
434                     VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
435     case VCARD7816_STATUS_WARNING_CHANGE:
436         return VCARD_RESPONSE_GET_STATIC(
437                     VCARD7816_STATUS_WARNING_CHANGE);
438     case VCARD7816_STATUS_WARNING_FILE_FILLED:
439         return VCARD_RESPONSE_GET_STATIC(
440                     VCARD7816_STATUS_WARNING_FILE_FILLED);
441     case VCARD7816_STATUS_EXC_ERROR:
442         return VCARD_RESPONSE_GET_STATIC(
443                     VCARD7816_STATUS_EXC_ERROR);
444     case VCARD7816_STATUS_EXC_ERROR_CHANGE:
445         return VCARD_RESPONSE_GET_STATIC(
446                     VCARD7816_STATUS_EXC_ERROR_CHANGE);
447     case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
448         return VCARD_RESPONSE_GET_STATIC(
449                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
450     case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
451         return VCARD_RESPONSE_GET_STATIC(
452                     VCARD7816_STATUS_ERROR_WRONG_LENGTH);
453     case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
454         return VCARD_RESPONSE_GET_STATIC(
455                     VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
456     case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
457         return VCARD_RESPONSE_GET_STATIC(
458                     VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
459     case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
460         return VCARD_RESPONSE_GET_STATIC(
461                     VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
462     case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
463         return VCARD_RESPONSE_GET_STATIC(
464                     VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
465     case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
466         return VCARD_RESPONSE_GET_STATIC(
467                     VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
468     case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
469         return VCARD_RESPONSE_GET_STATIC(
470                     VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
471     case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
472         return VCARD_RESPONSE_GET_STATIC(
473                     VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
474     case VCARD7816_STATUS_ERROR_DATA_INVALID:
475         return VCARD_RESPONSE_GET_STATIC(
476                     VCARD7816_STATUS_ERROR_DATA_INVALID);
477     case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
478         return VCARD_RESPONSE_GET_STATIC(
479                     VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
480     case VCARD7816_STATUS_ERROR_DATA_NO_EF:
481         return VCARD_RESPONSE_GET_STATIC(
482                     VCARD7816_STATUS_ERROR_DATA_NO_EF);
483     case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
484         return VCARD_RESPONSE_GET_STATIC(
485                     VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
486     case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
487         return VCARD_RESPONSE_GET_STATIC(
488                     VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
489     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
490         return VCARD_RESPONSE_GET_STATIC(
491                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
492     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
493         return VCARD_RESPONSE_GET_STATIC(
494                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
495     case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
496         return VCARD_RESPONSE_GET_STATIC(
497                     VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
498     case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
499         return VCARD_RESPONSE_GET_STATIC(
500                     VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
501     case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
502         return VCARD_RESPONSE_GET_STATIC(
503                     VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
504     case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
505         return VCARD_RESPONSE_GET_STATIC(
506                     VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
507     case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
508         return VCARD_RESPONSE_GET_STATIC(
509                     VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
510     case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
511         return VCARD_RESPONSE_GET_STATIC(
512                     VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
513     case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
514         return VCARD_RESPONSE_GET_STATIC(
515                     VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
516     case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
517         return VCARD_RESPONSE_GET_STATIC(
518                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
519     case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
520         return VCARD_RESPONSE_GET_STATIC(
521                     VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
522     case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
523         return VCARD_RESPONSE_GET_STATIC(
524                     VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
525     case VCARD7816_STATUS_ERROR_CLA_INVALID:
526         return VCARD_RESPONSE_GET_STATIC(
527                     VCARD7816_STATUS_ERROR_CLA_INVALID);
528     case VCARD7816_STATUS_ERROR_GENERAL:
529         return VCARD_RESPONSE_GET_STATIC(
530                     VCARD7816_STATUS_ERROR_GENERAL);
531     default:
532         /* we don't know this status code, create a response buffer to
533          * hold it */
534         response = vcard_response_new_status(status);
535         if (response == NULL) {
536             /* couldn't allocate the buffer, return memmory error */
537             return VCARD_RESPONSE_GET_STATIC(
538                         VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
539         }
540         return response;
541     }
542 }
543
544 /*
545  * Add File card support here if you need it.
546  */
547 static VCardStatus
548 vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
549                                    VCardResponse **response)
550 {
551     /* TODO: if we want to support a virtual file system card, we do it here.
552      * It would probably be a pkcs #15 card type */
553     *response = vcard_make_response(
554                     VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
555     return VCARD_DONE;
556 }
557
558 /*
559  * VM card (including java cards)
560  */
561 static VCardStatus
562 vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
563                           VCardResponse **response)
564 {
565     int bytes_to_copy, next_byte_count, count;
566     VCardApplet *current_applet;
567     VCardBufferResponse *buffer_response;
568     vcard_7816_status_t status;
569
570     /* parse the class first */
571     if (apdu->a_gen_type !=  VCARD_7816_ISO) {
572         *response = vcard_make_response(
573                         VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
574         return VCARD_DONE;
575     }
576
577     /* use a switch so that if we need to support secure channel stuff later,
578      * we know where to put it */
579     switch (apdu->a_secure_messaging) {
580     case 0x0: /* no SM */
581         break;
582     case 0x4: /* proprietary SM */
583     case 0x8: /* header not authenticated */
584     case 0xc: /* header authenticated */
585     default:
586         /* for now, don't try to support secure channel stuff in the
587          * virtual card. */
588         *response = vcard_make_response(
589                         VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
590         return VCARD_DONE;
591     }
592
593     /* now parse the instruction */
594     switch (apdu->a_ins) {
595     case  VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
596     case  VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
597     case  VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
598     case  VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
599     case  VCARD7816_INS_ERASE_BINARY: /* applet control op */
600     case  VCARD7816_INS_READ_BINARY: /* applet control op */
601     case  VCARD7816_INS_WRITE_BINARY: /* applet control op */
602     case  VCARD7816_INS_UPDATE_BINARY: /* applet control op */
603     case  VCARD7816_INS_READ_RECORD: /* file op */
604     case  VCARD7816_INS_WRITE_RECORD: /* file op */
605     case  VCARD7816_INS_UPDATE_RECORD: /* file op */
606     case  VCARD7816_INS_APPEND_RECORD: /* file op */
607     case  VCARD7816_INS_ENVELOPE:
608     case  VCARD7816_INS_PUT_DATA:
609         *response = vcard_make_response(
610                             VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
611         break;
612
613     case  VCARD7816_INS_SELECT_FILE:
614         if (apdu->a_p1 != 0x04) {
615             *response = vcard_make_response(
616                             VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
617             break;
618         }
619
620         /* side effect, deselect the current applet if no applet has been found
621          * */
622         current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
623         vcard_select_applet(card, apdu->a_channel, current_applet);
624         if (current_applet) {
625             unsigned char *aid;
626             int aid_len;
627             aid = vcard_applet_get_aid(current_applet, &aid_len);
628             *response = vcard_response_new(card, aid, aid_len, apdu->a_Le,
629                                           VCARD7816_STATUS_SUCCESS);
630         } else {
631             *response = vcard_make_response(
632                              VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
633         }
634         break;
635
636     case  VCARD7816_INS_VERIFY:
637         if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
638             *response = vcard_make_response(
639                             VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
640         } else {
641             if (apdu->a_Lc == 0) {
642                 /* handle pin count if possible */
643                 count = vcard_emul_get_login_count(card);
644                 if (count < 0) {
645                     *response = vcard_make_response(
646                                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
647                 } else {
648                     if (count > 0xf) {
649                         count = 0xf;
650                     }
651                     *response = vcard_response_new_status_bytes(
652                                                 VCARD7816_SW1_WARNING_CHANGE,
653                                                                 0xc0 | count);
654                     if (*response == NULL) {
655                         *response = vcard_make_response(
656                                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
657                     }
658                 }
659             } else {
660                     status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
661                 *response = vcard_make_response(status);
662             }
663         }
664         break;
665
666     case VCARD7816_INS_GET_RESPONSE:
667         buffer_response = vcard_get_buffer_response(card);
668         if (!buffer_response) {
669             *response = vcard_make_response(
670                             VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
671             /* handle error */
672             break;
673         }
674         bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
675         next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
676         *response = vcard_response_new_bytes(
677                         card, buffer_response->current, bytes_to_copy,
678                         apdu->a_Le,
679                         next_byte_count ?
680                         VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
681                         next_byte_count);
682         buffer_response->current += bytes_to_copy;
683         buffer_response->len -= bytes_to_copy;
684         if (*response == NULL || (next_byte_count == 0)) {
685             vcard_set_buffer_response(card, NULL);
686             vcard_buffer_response_delete(buffer_response);
687         }
688         if (*response == NULL) {
689             *response =
690                 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
691         }
692         break;
693
694     case VCARD7816_INS_GET_DATA:
695         *response =
696             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
697         break;
698
699     default:
700         *response =
701             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
702         break;
703     }
704
705     /* response should have been set somewhere */
706     assert(*response != NULL);
707     return VCARD_DONE;
708 }
709
710
711 /*
712  * APDU processing starts here. This routes the card processing stuff to the
713  * right location.
714  */
715 VCardStatus
716 vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
717 {
718     VCardStatus status;
719     VCardBufferResponse *buffer_response;
720
721     /* first handle any PTS commands, which aren't really APDU's */
722     if (apdu->a_type == VCARD_7816_PTS) {
723         /* the PTS responses aren't really responses either */
724         *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
725         /* PTS responses have no status bytes */
726         (*response)->b_total_len = (*response)->b_len;
727         return VCARD_DONE;
728     }
729     buffer_response = vcard_get_buffer_response(card);
730     if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
731         /* clear out buffer_response, return an error */
732         vcard_set_buffer_response(card, NULL);
733         vcard_buffer_response_delete(buffer_response);
734         *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR);
735         return VCARD_DONE;
736     }
737
738     status = vcard_process_applet_apdu(card, apdu, response);
739     if (status != VCARD_NEXT) {
740         return status;
741     }
742     switch (vcard_get_type(card)) {
743     case VCARD_FILE_SYSTEM:
744         return vcard7816_file_system_process_apdu(card, apdu, response);
745     case VCARD_VM:
746         return vcard7816_vm_process_apdu(card, apdu, response);
747     case VCARD_DIRECT:
748         /* if we are type direct, then the applet should handle everything */
749         assert(!"VCARD_DIRECT: applet failure");
750         break;
751     }
752     *response =
753         vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
754     return VCARD_DONE;
755 }
This page took 0.07515 seconds and 4 git commands to generate.