Statistics
| Branch: | Revision:

root / libcacard / card_7816.c @ c2162a8b

History | View | Annotate | Download (27.3 kB)

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