]> Git Repo - qemu.git/blob - libcacard/card_7816.c
Merge remote-tracking branch 'pmaydell/armhw-for-upstream' into staging
[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 = (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;
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 Reponse 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 = (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);
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 = (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);
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         if (response->b_data) {
176             g_free(response->b_data);
177         }
178         g_free(response);
179         break;
180     case VCARD_MALLOC_DATA:
181         /* only the data buffer was malloc'ed */
182         if (response->b_data) {
183             g_free(response->b_data);
184         }
185         break;
186     case VCARD_MALLOC_STRUCT:
187         /* only the structure was malloc'ed */
188         g_free(response);
189         break;
190     case VCARD_STATIC:
191         break;
192     }
193 }
194
195 /*
196  * decode the class bit and set our generic type field, channel, and
197  * secure messaging values.
198  */
199 static vcard_7816_status_t
200 vcard_apdu_set_class(VCardAPDU *apdu) {
201     apdu->a_channel = 0;
202     apdu->a_secure_messaging = 0;
203     apdu->a_type = apdu->a_cla & 0xf0;
204     apdu->a_gen_type = VCARD_7816_ISO;
205
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 */
209     case 0x00:
210     case 0x80:
211     case 0x90:
212     case 0xa0:
213         apdu->a_channel = apdu->a_cla & 3;
214         apdu->a_secure_messaging = apdu->a_cla & 0xe;
215         break;
216     case 0xb0:
217     case 0xc0:
218         break;
219
220     case 0x10:
221     case 0x20:
222     case 0x30:
223     case 0x40:
224     case 0x50:
225     case 0x60:
226     case 0x70:
227         /* Reserved for future use */
228         apdu->a_gen_type = VCARD_7816_RFU;
229         break;
230     case 0xd0:
231     case 0xe0:
232     case 0xf0:
233     default:
234         apdu->a_gen_type =
235             (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPIETARY;
236         break;
237     }
238     return VCARD7816_STATUS_SUCCESS;
239 }
240
241 /*
242  * set the Le and Lc fiels according to table 5 of the
243  * 7816-4 part 4 spec
244  */
245 static vcard_7816_status_t
246 vcard_apdu_set_length(VCardAPDU *apdu)
247 {
248     int L, Le;
249
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 */
253     apdu->a_Lc = 0;
254     apdu->a_Le = 0;
255     apdu->a_body = NULL;
256     switch (L) {
257     case 0:
258         /* 1 minimal apdu */
259         return VCARD7816_STATUS_SUCCESS;
260     case 1:
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;
266     default:
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) {
271             if (L < 3) {
272                 /* coding error, need at least 3 bytes */
273                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
274             }
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];
278             if (L == 3) {
279                 /* 2E extended, return data only */
280                 /*   zero maps to 65536 */
281                 apdu->a_Le = Le ? Le : 65536;
282                 return VCARD7816_STATUS_SUCCESS;
283             }
284             if (Le == 0) {
285                 /* reserved for future use, probably for next time we need
286                  * to extend the lengths */
287                 return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
288             }
289             /* we know that the first extended value is Lc now */
290             apdu->a_Lc = Le;
291             apdu->a_body = &apdu->a_header->ah_body[2];
292             if (L == Le+3) {
293                 /* 3E extended, only body parameters */
294                 return VCARD7816_STATUS_SUCCESS;
295             }
296             if (L == Le+5) {
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;
302             }
303             return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
304         }
305         /* not extended */
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;
311         }
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;
317         }
318         break;
319     }
320     return VCARD7816_STATUS_ERROR_WRONG_LENGTH;
321 }
322
323 /*
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
326  * values.
327  */
328 VCardAPDU *
329 vcard_apdu_new(unsigned char *raw_apdu, int len, vcard_7816_status_t *status)
330 {
331     VCardAPDU *new_apdu;
332
333     *status = VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE;
334     if (len < 4) {
335         *status = VCARD7816_STATUS_ERROR_WRONG_LENGTH;
336         return NULL;
337     }
338
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) {
345         g_free(new_apdu);
346         return NULL;
347     }
348     *status = vcard_apdu_set_length(new_apdu);
349     if (*status != VCARD7816_STATUS_SUCCESS) {
350         g_free(new_apdu);
351         new_apdu = NULL;
352     }
353     return new_apdu;
354 }
355
356 void
357 vcard_apdu_delete(VCardAPDU *apdu)
358 {
359     if (apdu == NULL) {
360         return;
361     }
362     if (apdu->a_data) {
363         g_free(apdu->a_data);
364     }
365     g_free(apdu);
366 }
367
368
369 /*
370  * declare response buffers for all the 7816 defined error codes
371  */
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)
412
413 /*
414  * return a single response code. This function cannot fail. It will always
415  * return a response.
416  */
417 VCardResponse *
418 vcard_make_response(vcard_7816_status_t status)
419 {
420     VCardResponse *response = NULL;
421
422     switch (status) {
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);
538     default:
539         /* we don't know this status code, create a response buffer to
540          * hold it */
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);
546         }
547     }
548     assert(response);
549     return response;
550 }
551
552 /*
553  * Add File card support here if you need it.
554  */
555 static VCardStatus
556 vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
557                                    VCardResponse **response)
558 {
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);
563     return VCARD_DONE;
564 }
565
566 /*
567  * VM card (including java cards)
568  */
569 static VCardStatus
570 vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
571                           VCardResponse **response)
572 {
573     int bytes_to_copy, next_byte_count, count;
574     VCardApplet *current_applet;
575     VCardBufferResponse *buffer_response;
576     vcard_7816_status_t status;
577
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);
582         return VCARD_DONE;
583     }
584
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 */
589         break;
590     case 0x4: /* proprietary SM */
591     case 0x8: /* header not authenticated */
592     case 0xc: /* header authenticated */
593     default:
594         /* for now, don't try to support secure channel stuff in the
595          * virtual card. */
596         *response = vcard_make_response(
597                         VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
598         return VCARD_DONE;
599     }
600
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);
619         break;
620
621     case  VCARD7816_INS_SELECT_FILE:
622         if (apdu->a_p1 != 0x04) {
623             *response = vcard_make_response(
624                             VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
625             break;
626         }
627
628         /* side effect, deselect the current applet if no applet has been found
629          * */
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) {
633             unsigned char *aid;
634             int aid_len;
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);
638         } else {
639             *response = vcard_make_response(
640                              VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
641         }
642         break;
643
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);
648         } else {
649             if (apdu->a_Lc == 0) {
650                 /* handle pin count if possible */
651                 count = vcard_emul_get_login_count(card);
652                 if (count < 0) {
653                     *response = vcard_make_response(
654                                     VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
655                 } else {
656                     if (count > 0xf) {
657                         count = 0xf;
658                     }
659                     *response = vcard_response_new_status_bytes(
660                                                 VCARD7816_SW1_WARNING_CHANGE,
661                                                                 0xc0 | count);
662                     if (*response == NULL) {
663                         *response = vcard_make_response(
664                                     VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
665                     }
666                 }
667             } else {
668                     status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
669                 *response = vcard_make_response(status);
670             }
671         }
672         break;
673
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);
679             /* handle error */
680             break;
681         }
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,
686                         apdu->a_Le,
687                         next_byte_count ?
688                         VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
689                         next_byte_count);
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);
695         }
696         if (*response == NULL) {
697             *response =
698                 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
699         }
700         break;
701
702     case VCARD7816_INS_GET_DATA:
703         *response =
704             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
705         break;
706
707     default:
708         *response =
709             vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
710         break;
711     }
712
713     /* response should have been set somewhere */
714     assert(*response != NULL);
715     return VCARD_DONE;
716 }
717
718
719 /*
720  * APDU processing starts here. This routes the card processing stuff to the
721  * right location.
722  */
723 VCardStatus
724 vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
725 {
726     VCardStatus status;
727     VCardBufferResponse *buffer_response;
728
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;
735         return VCARD_DONE;
736     }
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);
743         return VCARD_DONE;
744     }
745
746     status = vcard_process_applet_apdu(card, apdu, response);
747     if (status != VCARD_NEXT) {
748         return status;
749     }
750     switch (vcard_get_type(card)) {
751     case VCARD_FILE_SYSTEM:
752         return vcard7816_file_system_process_apdu(card, apdu, response);
753     case VCARD_VM:
754         return vcard7816_vm_process_apdu(card, apdu, response);
755     case VCARD_DIRECT:
756         /* if we are type direct, then the applet should handle everything */
757         assert("VCARD_DIRECT: applet failure");
758         break;
759     }
760     *response =
761         vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
762     return VCARD_DONE;
763 }
This page took 0.063545 seconds and 4 git commands to generate.