]> Git Repo - qemu.git/blame - libcacard/card_7816.c
Merge remote-tracking branch 'remotes/xtensa/tags/20140526-xtensa' into staging
[qemu.git] / libcacard / card_7816.c
CommitLineData
111a38b0
RR
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 */
17static void
18vcard_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 */
34static void
35vcard_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 */
49VCardResponse *
50vcard_response_new_data(unsigned char *buf, int len)
51{
52 VCardResponse *new_response;
53
78a4b8d2 54 new_response = g_new(VCardResponse, 1);
7267c094 55 new_response->b_data = g_malloc(len + 2);
111a38b0
RR
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
63static VCardResponse *
64vcard_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 */
90VCardResponse *
91vcard_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 */
110VCardResponse *
111vcard_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/*
cba919da 128 * get a new Response buffer that only has a status.
111a38b0
RR
129 */
130static VCardResponse *
131vcard_response_new_status(vcard_7816_status_t status)
132{
133 VCardResponse *new_response;
134
78a4b8d2 135 new_response = g_new(VCardResponse, 1);
111a38b0
RR
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 */
147VCardResponse *
148vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
149{
150 VCardResponse *new_response;
151
78a4b8d2 152 new_response = g_new(VCardResponse, 1);
111a38b0
RR
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 */
166void
167vcard_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) {
7267c094 176 g_free(response->b_data);
111a38b0 177 }
7267c094 178 g_free(response);
111a38b0
RR
179 break;
180 case VCARD_MALLOC_DATA:
181 /* only the data buffer was malloc'ed */
182 if (response->b_data) {
7267c094 183 g_free(response->b_data);
111a38b0
RR
184 }
185 break;
186 case VCARD_MALLOC_STRUCT:
187 /* only the structure was malloc'ed */
7267c094 188 g_free(response);
111a38b0
RR
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 */
199static vcard_7816_status_t
200vcard_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 =
4c293dc6 235 (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
111a38b0
RR
236 break;
237 }
238 return VCARD7816_STATUS_SUCCESS;
239}
240
241/*
cba919da 242 * set the Le and Lc fields according to table 5 of the
111a38b0
RR
243 * 7816-4 part 4 spec
244 */
245static vcard_7816_status_t
246vcard_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 */
328VCardAPDU *
329vcard_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
78a4b8d2
MT
339 new_apdu = g_new(VCardAPDU, 1);
340 new_apdu->a_data = g_memdup(raw_apdu, len);
111a38b0
RR
341 new_apdu->a_len = len;
342 *status = vcard_apdu_set_class(new_apdu);
343 if (*status != VCARD7816_STATUS_SUCCESS) {
7267c094 344 g_free(new_apdu);
111a38b0
RR
345 return NULL;
346 }
347 *status = vcard_apdu_set_length(new_apdu);
348 if (*status != VCARD7816_STATUS_SUCCESS) {
7267c094 349 g_free(new_apdu);
111a38b0
RR
350 new_apdu = NULL;
351 }
352 return new_apdu;
353}
354
355void
356vcard_apdu_delete(VCardAPDU *apdu)
357{
358 if (apdu == NULL) {
359 return;
360 }
361 if (apdu->a_data) {
7267c094 362 g_free(apdu->a_data);
111a38b0 363 }
7267c094 364 g_free(apdu);
111a38b0
RR
365}
366
367
368/*
369 * declare response buffers for all the 7816 defined error codes
370 */
371VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
372VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
373VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
374VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
375VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
376VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
377VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
378VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
379VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
380VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
381VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
382VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
383VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
384VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
385VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
386VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
387VCARD_RESPONSE_NEW_STATIC_STATUS(
388 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
389VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
390VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
391VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
392VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
393VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
394VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
395VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
396VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
397VCARD_RESPONSE_NEW_STATIC_STATUS(
398 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
399VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
400VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
401VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
402VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
403VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
404VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
405VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
406VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
407VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
408VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
409VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
410VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_GENERAL)
411
412/*
413 * return a single response code. This function cannot fail. It will always
414 * return a response.
415 */
416VCardResponse *
417vcard_make_response(vcard_7816_status_t status)
418{
1687a089 419 VCardResponse *response;
111a38b0
RR
420
421 switch (status) {
422 /* known 7816 response codes */
423 case VCARD7816_STATUS_SUCCESS:
424 return VCARD_RESPONSE_GET_STATIC(
425 VCARD7816_STATUS_SUCCESS);
426 case VCARD7816_STATUS_WARNING:
427 return VCARD_RESPONSE_GET_STATIC(
428 VCARD7816_STATUS_WARNING);
429 case VCARD7816_STATUS_WARNING_RET_CORUPT:
430 return VCARD_RESPONSE_GET_STATIC(
431 VCARD7816_STATUS_WARNING_RET_CORUPT);
432 case VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE:
433 return VCARD_RESPONSE_GET_STATIC(
434 VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE);
435 case VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED:
436 return VCARD_RESPONSE_GET_STATIC(
437 VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED);
438 case VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID:
439 return VCARD_RESPONSE_GET_STATIC(
440 VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID);
441 case VCARD7816_STATUS_WARNING_CHANGE:
442 return VCARD_RESPONSE_GET_STATIC(
443 VCARD7816_STATUS_WARNING_CHANGE);
444 case VCARD7816_STATUS_WARNING_FILE_FILLED:
445 return VCARD_RESPONSE_GET_STATIC(
446 VCARD7816_STATUS_WARNING_FILE_FILLED);
447 case VCARD7816_STATUS_EXC_ERROR:
448 return VCARD_RESPONSE_GET_STATIC(
449 VCARD7816_STATUS_EXC_ERROR);
450 case VCARD7816_STATUS_EXC_ERROR_CHANGE:
451 return VCARD_RESPONSE_GET_STATIC(
452 VCARD7816_STATUS_EXC_ERROR_CHANGE);
453 case VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE:
454 return VCARD_RESPONSE_GET_STATIC(
455 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
456 case VCARD7816_STATUS_ERROR_WRONG_LENGTH:
457 return VCARD_RESPONSE_GET_STATIC(
458 VCARD7816_STATUS_ERROR_WRONG_LENGTH);
459 case VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED:
460 return VCARD_RESPONSE_GET_STATIC(
461 VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED);
462 case VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED:
463 return VCARD_RESPONSE_GET_STATIC(
464 VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED);
465 case VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED:
466 return VCARD_RESPONSE_GET_STATIC(
467 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
468 case VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED:
469 return VCARD_RESPONSE_GET_STATIC(
470 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
471 case VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE:
472 return VCARD_RESPONSE_GET_STATIC(
473 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE);
474 case VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED:
475 return VCARD_RESPONSE_GET_STATIC(
476 VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED);
477 case VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED:
478 return VCARD_RESPONSE_GET_STATIC(
479 VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED);
480 case VCARD7816_STATUS_ERROR_DATA_INVALID:
481 return VCARD_RESPONSE_GET_STATIC(
482 VCARD7816_STATUS_ERROR_DATA_INVALID);
483 case VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED:
484 return VCARD_RESPONSE_GET_STATIC(
485 VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED);
486 case VCARD7816_STATUS_ERROR_DATA_NO_EF:
487 return VCARD_RESPONSE_GET_STATIC(
488 VCARD7816_STATUS_ERROR_DATA_NO_EF);
489 case VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING:
490 return VCARD_RESPONSE_GET_STATIC(
491 VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING);
492 case VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT:
493 return VCARD_RESPONSE_GET_STATIC(
494 VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT);
495 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS:
496 return VCARD_RESPONSE_GET_STATIC(
497 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
498 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA:
499 return VCARD_RESPONSE_GET_STATIC(
500 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA);
501 case VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED:
502 return VCARD_RESPONSE_GET_STATIC(
503 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
504 case VCARD7816_STATUS_ERROR_FILE_NOT_FOUND:
505 return VCARD_RESPONSE_GET_STATIC(
506 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
507 case VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND:
508 return VCARD_RESPONSE_GET_STATIC(
509 VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND);
510 case VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE:
511 return VCARD_RESPONSE_GET_STATIC(
512 VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE);
513 case VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT:
514 return VCARD_RESPONSE_GET_STATIC(
515 VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT);
516 case VCARD7816_STATUS_ERROR_P1_P2_INCORRECT:
517 return VCARD_RESPONSE_GET_STATIC(
518 VCARD7816_STATUS_ERROR_P1_P2_INCORRECT);
519 case VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT:
520 return VCARD_RESPONSE_GET_STATIC(
521 VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT);
522 case VCARD7816_STATUS_ERROR_DATA_NOT_FOUND:
523 return VCARD_RESPONSE_GET_STATIC(
524 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
525 case VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2:
526 return VCARD_RESPONSE_GET_STATIC(
527 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2);
528 case VCARD7816_STATUS_ERROR_INS_CODE_INVALID:
529 return VCARD_RESPONSE_GET_STATIC(
530 VCARD7816_STATUS_ERROR_INS_CODE_INVALID);
531 case VCARD7816_STATUS_ERROR_CLA_INVALID:
532 return VCARD_RESPONSE_GET_STATIC(
533 VCARD7816_STATUS_ERROR_CLA_INVALID);
534 case VCARD7816_STATUS_ERROR_GENERAL:
535 return VCARD_RESPONSE_GET_STATIC(
536 VCARD7816_STATUS_ERROR_GENERAL);
537 default:
538 /* we don't know this status code, create a response buffer to
539 * hold it */
540 response = vcard_response_new_status(status);
541 if (response == NULL) {
542 /* couldn't allocate the buffer, return memmory error */
543 return VCARD_RESPONSE_GET_STATIC(
544 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
545 }
1687a089 546 return response;
111a38b0 547 }
111a38b0
RR
548}
549
550/*
551 * Add File card support here if you need it.
552 */
553static VCardStatus
554vcard7816_file_system_process_apdu(VCard *card, VCardAPDU *apdu,
555 VCardResponse **response)
556{
557 /* TODO: if we want to support a virtual file system card, we do it here.
558 * It would probably be a pkcs #15 card type */
559 *response = vcard_make_response(
560 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
561 return VCARD_DONE;
562}
563
564/*
565 * VM card (including java cards)
566 */
567static VCardStatus
568vcard7816_vm_process_apdu(VCard *card, VCardAPDU *apdu,
569 VCardResponse **response)
570{
571 int bytes_to_copy, next_byte_count, count;
572 VCardApplet *current_applet;
573 VCardBufferResponse *buffer_response;
574 vcard_7816_status_t status;
575
576 /* parse the class first */
577 if (apdu->a_gen_type != VCARD_7816_ISO) {
578 *response = vcard_make_response(
579 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
580 return VCARD_DONE;
581 }
582
583 /* use a switch so that if we need to support secure channel stuff later,
584 * we know where to put it */
585 switch (apdu->a_secure_messaging) {
586 case 0x0: /* no SM */
587 break;
588 case 0x4: /* proprietary SM */
589 case 0x8: /* header not authenticated */
590 case 0xc: /* header authenticated */
591 default:
592 /* for now, don't try to support secure channel stuff in the
593 * virtual card. */
594 *response = vcard_make_response(
595 VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED);
596 return VCARD_DONE;
597 }
598
599 /* now parse the instruction */
600 switch (apdu->a_ins) {
601 case VCARD7816_INS_MANAGE_CHANNEL: /* secure channel op */
602 case VCARD7816_INS_EXTERNAL_AUTHENTICATE: /* secure channel op */
603 case VCARD7816_INS_GET_CHALLENGE: /* secure channel op */
604 case VCARD7816_INS_INTERNAL_AUTHENTICATE: /* secure channel op */
605 case VCARD7816_INS_ERASE_BINARY: /* applet control op */
606 case VCARD7816_INS_READ_BINARY: /* applet control op */
607 case VCARD7816_INS_WRITE_BINARY: /* applet control op */
608 case VCARD7816_INS_UPDATE_BINARY: /* applet control op */
609 case VCARD7816_INS_READ_RECORD: /* file op */
610 case VCARD7816_INS_WRITE_RECORD: /* file op */
611 case VCARD7816_INS_UPDATE_RECORD: /* file op */
612 case VCARD7816_INS_APPEND_RECORD: /* file op */
613 case VCARD7816_INS_ENVELOPE:
614 case VCARD7816_INS_PUT_DATA:
615 *response = vcard_make_response(
616 VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
617 break;
618
619 case VCARD7816_INS_SELECT_FILE:
620 if (apdu->a_p1 != 0x04) {
621 *response = vcard_make_response(
622 VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED);
623 break;
624 }
625
626 /* side effect, deselect the current applet if no applet has been found
627 * */
628 current_applet = vcard_find_applet(card, apdu->a_body, apdu->a_Lc);
629 vcard_select_applet(card, apdu->a_channel, current_applet);
630 if (current_applet) {
631 unsigned char *aid;
632 int aid_len;
633 aid = vcard_applet_get_aid(current_applet, &aid_len);
634 *response = vcard_response_new(card, aid, aid_len, apdu->a_Le,
635 VCARD7816_STATUS_SUCCESS);
636 } else {
637 *response = vcard_make_response(
638 VCARD7816_STATUS_ERROR_FILE_NOT_FOUND);
639 }
640 break;
641
642 case VCARD7816_INS_VERIFY:
643 if ((apdu->a_p1 != 0x00) || (apdu->a_p2 != 0x00)) {
644 *response = vcard_make_response(
645 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS);
646 } else {
647 if (apdu->a_Lc == 0) {
648 /* handle pin count if possible */
649 count = vcard_emul_get_login_count(card);
650 if (count < 0) {
651 *response = vcard_make_response(
652 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
653 } else {
654 if (count > 0xf) {
655 count = 0xf;
656 }
657 *response = vcard_response_new_status_bytes(
658 VCARD7816_SW1_WARNING_CHANGE,
659 0xc0 | count);
660 if (*response == NULL) {
661 *response = vcard_make_response(
662 VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
663 }
664 }
665 } else {
666 status = vcard_emul_login(card, apdu->a_body, apdu->a_Lc);
667 *response = vcard_make_response(status);
668 }
669 }
670 break;
671
672 case VCARD7816_INS_GET_RESPONSE:
673 buffer_response = vcard_get_buffer_response(card);
674 if (!buffer_response) {
675 *response = vcard_make_response(
676 VCARD7816_STATUS_ERROR_DATA_NOT_FOUND);
677 /* handle error */
678 break;
679 }
680 bytes_to_copy = MIN(buffer_response->len, apdu->a_Le);
681 next_byte_count = MIN(256, buffer_response->len - bytes_to_copy);
682 *response = vcard_response_new_bytes(
683 card, buffer_response->current, bytes_to_copy,
684 apdu->a_Le,
685 next_byte_count ?
686 VCARD7816_SW1_RESPONSE_BYTES : VCARD7816_SW1_SUCCESS,
687 next_byte_count);
688 buffer_response->current += bytes_to_copy;
689 buffer_response->len -= bytes_to_copy;
690 if (*response == NULL || (next_byte_count == 0)) {
691 vcard_set_buffer_response(card, NULL);
692 vcard_buffer_response_delete(buffer_response);
693 }
694 if (*response == NULL) {
695 *response =
696 vcard_make_response(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE);
697 }
698 break;
699
700 case VCARD7816_INS_GET_DATA:
701 *response =
702 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
703 break;
704
705 default:
706 *response =
707 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
708 break;
709 }
710
711 /* response should have been set somewhere */
712 assert(*response != NULL);
713 return VCARD_DONE;
714}
715
716
717/*
718 * APDU processing starts here. This routes the card processing stuff to the
719 * right location.
720 */
721VCardStatus
722vcard_process_apdu(VCard *card, VCardAPDU *apdu, VCardResponse **response)
723{
724 VCardStatus status;
725 VCardBufferResponse *buffer_response;
726
727 /* first handle any PTS commands, which aren't really APDU's */
728 if (apdu->a_type == VCARD_7816_PTS) {
729 /* the PTS responses aren't really responses either */
730 *response = vcard_response_new_data(apdu->a_data, apdu->a_len);
731 /* PTS responses have no status bytes */
732 (*response)->b_total_len = (*response)->b_len;
733 return VCARD_DONE;
734 }
735 buffer_response = vcard_get_buffer_response(card);
736 if (buffer_response && apdu->a_ins != VCARD7816_INS_GET_RESPONSE) {
737 /* clear out buffer_response, return an error */
738 vcard_set_buffer_response(card, NULL);
739 vcard_buffer_response_delete(buffer_response);
740 *response = vcard_make_response(VCARD7816_STATUS_EXC_ERROR);
741 return VCARD_DONE;
742 }
743
744 status = vcard_process_applet_apdu(card, apdu, response);
745 if (status != VCARD_NEXT) {
746 return status;
747 }
748 switch (vcard_get_type(card)) {
749 case VCARD_FILE_SYSTEM:
750 return vcard7816_file_system_process_apdu(card, apdu, response);
751 case VCARD_VM:
752 return vcard7816_vm_process_apdu(card, apdu, response);
753 case VCARD_DIRECT:
754 /* if we are type direct, then the applet should handle everything */
d9676f82 755 assert(!"VCARD_DIRECT: applet failure");
111a38b0
RR
756 break;
757 }
758 *response =
759 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
760 return VCARD_DONE;
761}
This page took 0.337948 seconds and 4 git commands to generate.