Statistics
| Branch: | Revision:

root / libcacard / card_7816.c @ 7267c094

History | View | Annotate | Download (27.3 kB)

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
}