]> Git Repo - qemu.git/blame - libcacard/card_7816.c
microblaze: cpu: delete unused cpu_interrupts_enabled
[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
28507a41
PB
8#include "glib-compat.h"
9
10#include <string.h>
111a38b0
RR
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 */
19static void
20vcard_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 */
36static void
37vcard_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 */
51VCardResponse *
52vcard_response_new_data(unsigned char *buf, int len)
53{
54 VCardResponse *new_response;
55
78a4b8d2 56 new_response = g_new(VCardResponse, 1);
7267c094 57 new_response->b_data = g_malloc(len + 2);
111a38b0
RR
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
65static VCardResponse *
66vcard_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 */
92VCardResponse *
93vcard_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 */
112VCardResponse *
113vcard_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/*
cba919da 130 * get a new Response buffer that only has a status.
111a38b0
RR
131 */
132static VCardResponse *
133vcard_response_new_status(vcard_7816_status_t status)
134{
135 VCardResponse *new_response;
136
78a4b8d2 137 new_response = g_new(VCardResponse, 1);
111a38b0
RR
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 */
149VCardResponse *
150vcard_response_new_status_bytes(unsigned char sw1, unsigned char sw2)
151{
152 VCardResponse *new_response;
153
78a4b8d2 154 new_response = g_new(VCardResponse, 1);
111a38b0
RR
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 */
168void
169vcard_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 */
ec15993d 177 g_free(response->b_data);
7267c094 178 g_free(response);
111a38b0
RR
179 break;
180 case VCARD_MALLOC_DATA:
181 /* only the data buffer was malloc'ed */
ec15993d 182 g_free(response->b_data);
111a38b0
RR
183 break;
184 case VCARD_MALLOC_STRUCT:
185 /* only the structure was malloc'ed */
7267c094 186 g_free(response);
111a38b0
RR
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 */
197static vcard_7816_status_t
198vcard_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 =
4c293dc6 233 (apdu->a_cla == 0xff) ? VCARD_7816_PTS : VCARD_7816_PROPRIETARY;
111a38b0
RR
234 break;
235 }
236 return VCARD7816_STATUS_SUCCESS;
237}
238
239/*
cba919da 240 * set the Le and Lc fields according to table 5 of the
111a38b0
RR
241 * 7816-4 part 4 spec
242 */
243static vcard_7816_status_t
244vcard_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 */
326VCardAPDU *
327vcard_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
78a4b8d2
MT
337 new_apdu = g_new(VCardAPDU, 1);
338 new_apdu->a_data = g_memdup(raw_apdu, len);
111a38b0
RR
339 new_apdu->a_len = len;
340 *status = vcard_apdu_set_class(new_apdu);
341 if (*status != VCARD7816_STATUS_SUCCESS) {
7267c094 342 g_free(new_apdu);
111a38b0
RR
343 return NULL;
344 }
345 *status = vcard_apdu_set_length(new_apdu);
346 if (*status != VCARD7816_STATUS_SUCCESS) {
7267c094 347 g_free(new_apdu);
111a38b0
RR
348 new_apdu = NULL;
349 }
350 return new_apdu;
351}
352
353void
354vcard_apdu_delete(VCardAPDU *apdu)
355{
356 if (apdu == NULL) {
357 return;
358 }
ec15993d 359 g_free(apdu->a_data);
7267c094 360 g_free(apdu);
111a38b0
RR
361}
362
363
364/*
365 * declare response buffers for all the 7816 defined error codes
366 */
367VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_SUCCESS)
368VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING)
369VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_RET_CORUPT)
370VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_BUF_END_BEFORE_LE)
371VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_INVALID_FILE_SELECTED)
372VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FCI_FORMAT_INVALID)
373VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_CHANGE)
374VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_WARNING_FILE_FILLED)
375VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR)
376VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_CHANGE)
377VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_EXC_ERROR_MEMORY_FAILURE)
378VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_LENGTH)
379VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_NOT_SUPPORTED)
380VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CHANNEL_NOT_SUPPORTED)
381VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURE_NOT_SUPPORTED)
382VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED)
383VCARD_RESPONSE_NEW_STATIC_STATUS(
384 VCARD7816_STATUS_ERROR_COMMAND_INCOMPATIBLE_WITH_FILE)
385VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SECURITY_NOT_SATISFIED)
386VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_AUTHENTICATION_BLOCKED)
387VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_INVALID)
388VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED)
389VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NO_EF)
390VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_MISSING)
391VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_SM_OBJECT_INCORRECT)
392VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS)
393VCARD_RESPONSE_NEW_STATIC_STATUS(
394 VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_IN_DATA)
395VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FUNCTION_NOT_SUPPORTED)
396VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_FILE_NOT_FOUND)
397VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_RECORD_NOT_FOUND)
398VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_NO_SPACE_FOR_FILE)
399VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_TLV_INCONSISTENT)
400VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_P1_P2_INCORRECT)
401VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_LC_P1_P2_INCONSISTENT)
402VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_DATA_NOT_FOUND)
403VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_WRONG_PARAMETERS_2)
404VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_INS_CODE_INVALID)
405VCARD_RESPONSE_NEW_STATIC_STATUS(VCARD7816_STATUS_ERROR_CLA_INVALID)
406VCARD_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 */
412VCardResponse *
413vcard_make_response(vcard_7816_status_t status)
414{
1687a089 415 VCardResponse *response;
111a38b0
RR
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 }
1687a089 542 return response;
111a38b0 543 }
111a38b0
RR
544}
545
546/*
547 * Add File card support here if you need it.
548 */
549static VCardStatus
550vcard7816_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 */
563static VCardStatus
564vcard7816_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 */
717VCardStatus
718vcard_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 */
d9676f82 751 assert(!"VCARD_DIRECT: applet failure");
111a38b0
RR
752 break;
753 }
754 *response =
755 vcard_make_response(VCARD7816_STATUS_ERROR_COMMAND_NOT_SUPPORTED);
756 return VCARD_DONE;
757}
This page took 0.324462 seconds and 4 git commands to generate.