root/trunk/src/libopensc/iso7816.c

Revision 3595, 27.8 KB (checked in by martin, 9 days ago)
  • Fix issues with pkcs11-tool testing of C_GenerateRandom/C_SeedRandom and OpenSC PKCS#11 implementation of those functions.

Thanks goes to Rickard Bondesson who noticed the issues.

http://www.opensc-project.org/pipermail/opensc-devel/2008-November/011436.html

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * iso7816.c: Functions specified by the ISO 7816 standard
3 *
4 * Copyright (C) 2001, 2002  Juha YrjölÀ <juha.yrjola@iki.fi>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21#include "internal.h"
22#include "asn1.h"
23#include <assert.h>
24#include <ctype.h>
25#include <stdlib.h>
26#include <string.h>
27
28static const struct sc_card_error iso7816_errors[] = {
29        { 0x6200, SC_ERROR_MEMORY_FAILURE,      "State of non-volatile memory unchanged" },
30        { 0x6281, SC_ERROR_MEMORY_FAILURE,      "Part of returned data may be corrupted" },
31        { 0x6282, SC_ERROR_CARD_CMD_FAILED,     "End of file/record reached before reading Le bytes" },
32        { 0x6283, SC_ERROR_CARD_CMD_FAILED,     "Selected file invalidated" },
33        { 0x6284, SC_ERROR_CARD_CMD_FAILED,     "FCI not formatted according to ISO 7816-4" },
34
35        { 0x6300, SC_ERROR_MEMORY_FAILURE,      "State of non-volatile memory changed" },
36        { 0x6381, SC_ERROR_CARD_CMD_FAILED,     "File filled up by last write" },
37
38        { 0x6581, SC_ERROR_MEMORY_FAILURE,      "Memory failure" },
39
40        { 0x6700, SC_ERROR_WRONG_LENGTH,        "Wrong length" },
41
42        { 0x6800, SC_ERROR_NO_CARD_SUPPORT,     "Functions in CLA not supported" },
43        { 0x6881, SC_ERROR_NO_CARD_SUPPORT,     "Logical channel not supported" },
44        { 0x6882, SC_ERROR_NO_CARD_SUPPORT,     "Secure messaging not supported" },
45
46        { 0x6900, SC_ERROR_NOT_ALLOWED,         "Command not allowed" },
47        { 0x6981, SC_ERROR_CARD_CMD_FAILED,     "Command incompatible with file structure" },
48        { 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED, "Security status not satisfied" },
49        { 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "Authentication method blocked" },
50        { 0x6984, SC_ERROR_CARD_CMD_FAILED,     "Referenced data invalidated" },
51        { 0x6985, SC_ERROR_NOT_ALLOWED,         "Conditions of use not satisfied" },
52        { 0x6986, SC_ERROR_NOT_ALLOWED,         "Command not allowed (no current EF)" },
53        { 0x6987, SC_ERROR_INCORRECT_PARAMETERS,"Expected SM data objects missing" },
54        { 0x6988, SC_ERROR_INCORRECT_PARAMETERS,"SM data objects incorrect" },
55
56        { 0x6A00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
57        { 0x6A80, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect parameters in the data field" },
58        { 0x6A81, SC_ERROR_NO_CARD_SUPPORT,     "Function not supported" },
59        { 0x6A82, SC_ERROR_FILE_NOT_FOUND,      "File not found" },
60        { 0x6A83, SC_ERROR_RECORD_NOT_FOUND,    "Record not found" },
61        { 0x6A84, SC_ERROR_CARD_CMD_FAILED,     "Not enough memory space in the file" },
62        { 0x6A85, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with TLV structure" },
63        { 0x6A86, SC_ERROR_INCORRECT_PARAMETERS,"Incorrect parameters P1-P2" },
64        { 0x6A87, SC_ERROR_INCORRECT_PARAMETERS,"Lc inconsistent with P1-P2" },
65        { 0x6A88, SC_ERROR_DATA_OBJECT_NOT_FOUND,"Referenced data not found" },
66
67        { 0x6B00, SC_ERROR_INCORRECT_PARAMETERS,"Wrong parameter(s) P1-P2" },
68        { 0x6D00, SC_ERROR_INS_NOT_SUPPORTED,   "Instruction code not supported or invalid" },
69        { 0x6E00, SC_ERROR_CLASS_NOT_SUPPORTED, "Class not supported" },
70        { 0x6F00, SC_ERROR_CARD_CMD_FAILED,     "No precise diagnosis" },
71
72        /* Possibly TCOS / Micardo specific errors */
73        { 0x6600, SC_ERROR_INCORRECT_PARAMETERS, "Error setting the security env"},
74        { 0x66F0, SC_ERROR_INCORRECT_PARAMETERS, "No space left for padding"},
75        { 0x69F0, SC_ERROR_NOT_ALLOWED,          "Command not allowed"},
76        { 0x6A89, SC_ERROR_FILE_ALREADY_EXISTS,  "Files exists"},
77        { 0x6A8A, SC_ERROR_FILE_ALREADY_EXISTS,  "Application exists"},
78};
79
80static int iso7816_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
81{
82        const int err_count = sizeof(iso7816_errors)/sizeof(iso7816_errors[0]);
83        int i;
84       
85        /* Handle special cases here */
86        if (sw1 == 0x6C) {
87                sc_error(card->ctx, "Wrong length; correct length is %d\n", sw2);
88                return SC_ERROR_WRONG_LENGTH;
89        }
90        if (sw1 == 0x90)
91                return SC_NO_ERROR;
92        if (sw1 == 0x63U && (sw2 & ~0x0fU) == 0xc0U ) {
93             sc_error(card->ctx, "Verification failed (remaining tries: %d)\n",
94                   (sw2 & 0x0f));
95             return SC_ERROR_PIN_CODE_INCORRECT;
96        }
97        for (i = 0; i < err_count; i++)
98                if (iso7816_errors[i].SWs == ((sw1 << 8) | sw2)) {
99                        sc_error(card->ctx, "%s\n", iso7816_errors[i].errorstr);
100                        return iso7816_errors[i].errorno;
101                }
102        sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
103        return SC_ERROR_CARD_CMD_FAILED;
104}
105
106static int iso7816_read_binary(sc_card_t *card,
107                               unsigned int idx, u8 *buf, size_t count,
108                               unsigned long flags)
109{
110        sc_apdu_t apdu;
111        u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
112        int r;
113
114        if (idx > 0x7fff) {
115                sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
116                return SC_ERROR_OFFSET_TOO_LARGE;
117        }
118
119        assert(count <= card->max_recv_size);
120        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB0,
121                       (idx >> 8) & 0x7F, idx & 0xFF);
122        apdu.le = count;
123        apdu.resplen = count;
124        apdu.resp = recvbuf;
125
126        r = sc_transmit_apdu(card, &apdu);
127        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
128        if (apdu.resplen == 0)
129                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
130        memcpy(buf, recvbuf, apdu.resplen);
131
132        SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
133}
134
135static int iso7816_read_record(sc_card_t *card,
136                               unsigned int rec_nr, u8 *buf, size_t count,
137                               unsigned long flags)
138{
139        sc_apdu_t apdu;
140        u8 recvbuf[SC_MAX_APDU_BUFFER_SIZE];
141        int r;
142
143        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xB2, rec_nr, 0);
144        apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
145        if (flags & SC_RECORD_BY_REC_NR)
146                apdu.p2 |= 0x04;
147       
148        apdu.le = count;
149        apdu.resplen = count;
150        apdu.resp = recvbuf;
151
152        r = sc_transmit_apdu(card, &apdu);
153        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
154        if (apdu.resplen == 0)
155                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
156        memcpy(buf, recvbuf, apdu.resplen);
157
158        SC_FUNC_RETURN(card->ctx, 3, apdu.resplen);
159}
160
161static int iso7816_write_record(sc_card_t *card, unsigned int rec_nr,
162                                const u8 *buf, size_t count,
163                                unsigned long flags)
164{
165        sc_apdu_t apdu;
166        int r;
167
168        if (count > 256) {
169                sc_error(card->ctx, "Trying to send too many bytes\n");
170                return SC_ERROR_INVALID_ARGUMENTS;
171        }
172        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD2, rec_nr, 0);
173        apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
174        if (flags & SC_RECORD_BY_REC_NR)
175                apdu.p2 |= 0x04;
176       
177        apdu.lc = count;
178        apdu.datalen = count;
179        apdu.data = buf;
180
181        r = sc_transmit_apdu(card, &apdu);
182        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
183        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
184                    "Card returned error");
185        SC_FUNC_RETURN(card->ctx, 3, count);
186}
187
188static int iso7816_append_record(sc_card_t *card,
189                                 const u8 *buf, size_t count,
190                                 unsigned long flags)
191{
192        sc_apdu_t apdu;
193        int r;
194
195        if (count > 256) {
196                sc_error(card->ctx, "Trying to send too many bytes\n");
197                return SC_ERROR_INVALID_ARGUMENTS;
198        }
199        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE2, 0, 0);
200        apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
201       
202        apdu.lc = count;
203        apdu.datalen = count;
204        apdu.data = buf;
205
206        r = sc_transmit_apdu(card, &apdu);
207        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
208        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
209                    "Card returned error");
210        SC_FUNC_RETURN(card->ctx, 3, count);
211}
212
213static int iso7816_update_record(sc_card_t *card, unsigned int rec_nr,
214                                 const u8 *buf, size_t count,
215                                 unsigned long flags)
216{
217        sc_apdu_t apdu;
218        int r;
219
220        if (count > 256) {
221                sc_error(card->ctx, "Trying to send too many bytes\n");
222                return SC_ERROR_INVALID_ARGUMENTS;
223        }
224        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xDC, rec_nr, 0);
225        apdu.p2 = (flags & SC_RECORD_EF_ID_MASK) << 3;
226        if (flags & SC_RECORD_BY_REC_NR)
227                apdu.p2 |= 0x04;
228       
229        apdu.lc = count;
230        apdu.datalen = count;
231        apdu.data = buf;
232
233        r = sc_transmit_apdu(card, &apdu);
234        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
235        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
236                    "Card returned error");
237        SC_FUNC_RETURN(card->ctx, 3, count);
238}
239
240static int iso7816_write_binary(sc_card_t *card,
241                                unsigned int idx, const u8 *buf,
242                                size_t count, unsigned long flags)
243{
244        sc_apdu_t apdu;
245        int r;
246
247        assert(count <= card->max_send_size);
248
249        if (idx > 0x7fff) {
250                sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
251                return SC_ERROR_OFFSET_TOO_LARGE;
252        }
253
254        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD0,
255                       (idx >> 8) & 0x7F, idx & 0xFF);
256        apdu.lc = count;
257        apdu.datalen = count;
258        apdu.data = buf;
259
260        r = sc_transmit_apdu(card, &apdu);
261        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
262        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
263                    "Card returned error");
264        SC_FUNC_RETURN(card->ctx, 3, count);
265}
266
267static int iso7816_update_binary(sc_card_t *card,
268                                 unsigned int idx, const u8 *buf,
269                                size_t count, unsigned long flags)
270{
271        sc_apdu_t apdu;
272        int r;
273
274        assert(count <= card->max_send_size);
275
276        if (idx > 0x7fff) {
277                sc_error(card->ctx, "invalid EF offset: 0x%X > 0x7FFF", idx);
278                return SC_ERROR_OFFSET_TOO_LARGE;
279        }
280
281        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xD6,
282                       (idx >> 8) & 0x7F, idx & 0xFF);
283        apdu.lc = count;
284        apdu.datalen = count;
285        apdu.data = buf;
286
287        r = sc_transmit_apdu(card, &apdu);
288        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
289        SC_TEST_RET(card->ctx, sc_check_sw(card, apdu.sw1, apdu.sw2),
290                    "Card returned error");
291        SC_FUNC_RETURN(card->ctx, 3, count);
292}
293
294static int iso7816_process_fci(sc_card_t *card, sc_file_t *file,
295                       const u8 *buf, size_t buflen)
296{
297        sc_context_t *ctx = card->ctx;
298        size_t taglen, len = buflen;
299        const u8 *tag = NULL, *p = buf;
300
301        if (ctx->debug >= 3)
302                sc_debug(ctx, "processing FCI bytes\n");
303        tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
304        if (tag != NULL && taglen == 2) {
305                file->id = (tag[0] << 8) | tag[1];
306                if (ctx->debug >= 3)
307                        sc_debug(ctx, "  file identifier: 0x%02X%02X\n", tag[0],
308                               tag[1]);
309        }
310        tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
311        if (tag != NULL && taglen >= 2) {
312                int bytes = (tag[0] << 8) + tag[1];
313                if (ctx->debug >= 3)
314                        sc_debug(ctx, "  bytes in file: %d\n", bytes);
315                file->size = bytes;
316        }
317        if (tag == NULL) {
318                tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
319                if (tag != NULL && taglen >= 2) {
320                        int bytes = (tag[0] << 8) + tag[1];
321                        if (ctx->debug >= 3)
322                                sc_debug(ctx, "  bytes in file: %d\n", bytes);
323                        file->size = bytes;
324                }
325        }
326        tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
327        if (tag != NULL) {
328                if (taglen > 0) {
329                        unsigned char byte = tag[0];
330                        const char *type;
331
332                        file->shareable = byte & 0x40 ? 1 : 0;
333                        if (ctx->debug >= 3)
334                                sc_debug(ctx, "  shareable: %s\n",
335                                       (byte & 0x40) ? "yes" : "no");
336                        file->ef_structure = byte & 0x07;
337                        switch ((byte >> 3) & 7) {
338                        case 0:
339                                type = "working EF";
340                                file->type = SC_FILE_TYPE_WORKING_EF;
341                                break;
342                        case 1:
343                                type = "internal EF";
344                                file->type = SC_FILE_TYPE_INTERNAL_EF;
345                                break;
346                        case 7:
347                                type = "DF";
348                                file->type = SC_FILE_TYPE_DF;
349                                break;
350                        default:
351                                type = "unknown";
352                                break;
353                        }
354                        if (ctx->debug >= 3) {
355                                sc_debug(ctx, "  type: %s\n", type);
356                                sc_debug(ctx, "  EF structure: %d\n",
357                                       byte & 0x07);
358                        }
359                }
360        }
361        tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
362        if (tag != NULL && taglen > 0 && taglen <= 16) {
363                memcpy(file->name, tag, taglen);
364                file->namelen = taglen;
365
366                if (ctx->debug >= 3)
367                {
368                        char tbuf[128];
369                        sc_hex_dump(ctx, file->name, file->namelen, tbuf, sizeof(tbuf));
370                        sc_debug(ctx, "  File name: %s\n", tbuf);
371                }
372        }
373        tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
374        if (tag != NULL && taglen) {
375                sc_file_set_prop_attr(file, tag, taglen);
376        } else
377                file->prop_attr_len = 0;
378        tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen);
379        if (tag != NULL && taglen) {
380                sc_file_set_prop_attr(file, tag, taglen);
381        }
382        tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen);
383        if (tag != NULL && taglen) {
384                sc_file_set_sec_attr(file, tag, taglen);
385        }
386        file->magic = SC_FILE_MAGIC;
387
388        return 0;
389}
390
391static int iso7816_select_file(sc_card_t *card,
392                               const sc_path_t *in_path,
393                               sc_file_t **file_out)
394{
395        sc_context_t *ctx;
396        sc_apdu_t apdu;
397        u8 buf[SC_MAX_APDU_BUFFER_SIZE];
398        u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
399        int r, pathlen;
400        sc_file_t *file = NULL;
401
402        assert(card != NULL && in_path != NULL);
403        ctx = card->ctx;
404        memcpy(path, in_path->value, in_path->len);
405        pathlen = in_path->len;
406
407        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0, 0);
408       
409        switch (in_path->type) {
410        case SC_PATH_TYPE_FILE_ID:
411                apdu.p1 = 0;
412                if (pathlen != 2)
413                        return SC_ERROR_INVALID_ARGUMENTS;
414                break;
415        case SC_PATH_TYPE_DF_NAME:
416                apdu.p1 = 4;
417                break;
418        case SC_PATH_TYPE_PATH:
419                apdu.p1 = 8;
420                if (pathlen >= 2 && memcmp(path, "\x3F\x00", 2) == 0) {
421                        if (pathlen == 2) {     /* only 3F00 supplied */
422                                apdu.p1 = 0;
423                                break;
424                        }
425                        path += 2;
426                        pathlen -= 2;
427                }
428                break;
429        case SC_PATH_TYPE_FROM_CURRENT:
430                apdu.p1 = 9;
431                break;
432        case SC_PATH_TYPE_PARENT:
433                apdu.p1 = 3;
434                pathlen = 0;
435                apdu.cse = SC_APDU_CASE_2_SHORT;
436                break;
437        default:
438                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_INVALID_ARGUMENTS);
439        }
440        apdu.p2 = 0;            /* first record, return FCI */
441        apdu.lc = pathlen;
442        apdu.data = path;
443        apdu.datalen = pathlen;
444
445        if (file_out != NULL) {
446                apdu.resp = buf;
447                apdu.resplen = sizeof(buf);
448                apdu.le = 256;
449        } else {
450                apdu.resplen = 0;
451                apdu.le = 0;
452                apdu.cse = SC_APDU_CASE_3_SHORT;
453        }
454        r = sc_transmit_apdu(card, &apdu);
455        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
456        if (file_out == NULL) {
457                if (apdu.sw1 == 0x61)
458                        SC_FUNC_RETURN(card->ctx, 2, 0);
459                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
460        }
461
462        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
463        if (r)
464                SC_FUNC_RETURN(card->ctx, 2, r);
465
466        switch (apdu.resp[0]) {
467        case 0x6F:
468                file = sc_file_new();
469                if (file == NULL)
470                        SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
471                file->path = *in_path;
472                if (card->ops->process_fci == NULL) {
473                        sc_file_free(file);
474                        SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
475                }
476                if (apdu.resp[1] <= apdu.resplen)
477                        card->ops->process_fci(card, file, apdu.resp+2, apdu.resp[1]);
478                *file_out = file;
479                break;
480        case 0x00:      /* proprietary coding */
481                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
482        default:
483                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
484        }
485        return 0;
486}
487
488static int iso7816_get_challenge(sc_card_t *card, u8 *rnd, size_t len)
489{
490        int r;
491        sc_apdu_t apdu;
492        u8 buf[10];
493
494        if (!rnd)
495                return SC_ERROR_INVALID_ARGUMENTS;
496
497        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT,
498                       0x84, 0x00, 0x00);
499        apdu.le = 8;
500        apdu.resp = buf;
501        apdu.resplen = 8;       /* include SW's */
502
503        while (len > 0) {
504                size_t n = len > 8 ? 8 : len;
505               
506                r = sc_transmit_apdu(card, &apdu);
507                SC_TEST_RET(card->ctx, r, "APDU transmit failed");
508                if (apdu.resplen != 8)
509                        return sc_check_sw(card, apdu.sw1, apdu.sw2);
510                memcpy(rnd, apdu.resp, n);
511                len -= n;
512                rnd += n;
513        }       
514        return 0;
515}
516
517static int iso7816_construct_fci(sc_card_t *card, const sc_file_t *file,
518        u8 *out, size_t *outlen)
519{
520        u8 *p = out;
521        u8 buf[64];
522       
523        *p++ = 0x6F;
524        p++;
525       
526        buf[0] = (file->size >> 8) & 0xFF;
527        buf[1] = file->size & 0xFF;
528        sc_asn1_put_tag(0x81, buf, 2, p, 16, &p);
529
530        if (file->type_attr_len) {
531                memcpy(buf, file->type_attr, file->type_attr_len);
532                sc_asn1_put_tag(0x82, buf, file->type_attr_len, p, 16, &p);
533        } else {
534                buf[0] = file->shareable ? 0x40 : 0;
535                switch (file->type) {
536                case SC_FILE_TYPE_INTERNAL_EF:
537                        buf[0] |= 0x08;
538                case SC_FILE_TYPE_WORKING_EF:
539                        buf[0] |= file->ef_structure & 7;
540                        break;
541                case SC_FILE_TYPE_DF:
542                        buf[0] |= 0x38;
543                        break;
544                default:
545                        return SC_ERROR_NOT_SUPPORTED;
546                }
547                sc_asn1_put_tag(0x82, buf, 1, p, 16, &p);
548        }
549        buf[0] = (file->id >> 8) & 0xFF;
550        buf[1] = file->id & 0xFF;
551        sc_asn1_put_tag(0x83, buf, 2, p, 16, &p);
552        /* 0x84 = DF name */
553        if (file->prop_attr_len) {
554                memcpy(buf, file->prop_attr, file->prop_attr_len);
555                sc_asn1_put_tag(0x85, buf, file->prop_attr_len, p, 18, &p);
556        }
557        if (file->sec_attr_len) {
558                memcpy(buf, file->sec_attr, file->sec_attr_len);
559                sc_asn1_put_tag(0x86, buf, file->sec_attr_len, p, 18, &p);
560        }
561        out[1] = p - out - 2;
562
563        *outlen = p - out;
564        return 0;
565}
566
567static int iso7816_create_file(sc_card_t *card, sc_file_t *file)
568{
569        int r;
570        size_t len;
571        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
572        sc_apdu_t apdu;
573
574        len = SC_MAX_APDU_BUFFER_SIZE;
575
576        if (card->ops->construct_fci == NULL)
577                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_NOT_SUPPORTED);
578        r = card->ops->construct_fci(card, file, sbuf, &len);
579        SC_TEST_RET(card->ctx, r, "construct_fci() failed");
580       
581        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
582        apdu.lc = len;
583        apdu.datalen = len;
584        apdu.data = sbuf;
585
586        r = sc_transmit_apdu(card, &apdu);
587        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
588        return sc_check_sw(card, apdu.sw1, apdu.sw2);
589}
590
591static int iso7816_get_response(sc_card_t *card, size_t *count, u8 *buf)
592{
593        sc_apdu_t apdu;
594        int r;
595        size_t rlen;
596
597        /* request at most max_recv_size bytes */
598        if (*count > card->max_recv_size)
599                rlen = card->max_recv_size;
600        else
601                rlen = *count;
602
603        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xC0, 0x00, 0x00);
604        apdu.le      = rlen;
605        apdu.resplen = rlen;
606        apdu.resp    = buf;
607        /* don't call GET RESPONSE recursively */
608        apdu.flags  |= SC_APDU_FLAGS_NO_GET_RESP;
609
610        r = sc_transmit_apdu(card, &apdu);
611        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
612        if (apdu.resplen == 0)
613                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
614
615        *count = apdu.resplen;
616
617        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
618                r = 0;                                  /* no more data to read */
619        else if (apdu.sw1 == 0x61)
620                r = apdu.sw2 == 0 ? 256 : apdu.sw2;     /* more data to read    */
621        else if (apdu.sw1 == 0x62 && apdu.sw2 == 0x82)
622                r = 0; /* Le not reached but file/record ended */
623        else
624                r = sc_check_sw(card, apdu.sw1, apdu.sw2);
625
626        return r;
627}
628
629static int iso7816_delete_file(sc_card_t *card, const sc_path_t *path)
630{
631        int r;
632        u8 sbuf[2];
633        sc_apdu_t apdu;
634
635        SC_FUNC_CALLED(card->ctx, 1);
636        if (path->type != SC_PATH_TYPE_FILE_ID || (path->len != 0 && path->len != 2)) {
637                sc_error(card->ctx, "File type has to be SC_PATH_TYPE_FILE_ID\n");
638                SC_FUNC_RETURN(card->ctx, 1, SC_ERROR_INVALID_ARGUMENTS);
639        }
640
641        if (path->len == 2) {
642                sbuf[0] = path->value[0];
643                sbuf[1] = path->value[1];
644                sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
645                apdu.lc = 2;
646                apdu.datalen = 2;
647        }
648        else /* No file ID given: means currently selected file */
649                sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xE4, 0x00, 0x00);
650        apdu.data = sbuf;
651       
652        r = sc_transmit_apdu(card, &apdu);
653        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
654        return sc_check_sw(card, apdu.sw1, apdu.sw2);
655}
656
657static int iso7816_set_security_env(sc_card_t *card,
658                                    const sc_security_env_t *env,
659                                    int se_num)
660{
661        sc_apdu_t apdu;
662        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
663        u8 *p;
664        int r, locked = 0;
665
666        assert(card != NULL && env != NULL);
667        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
668        switch (env->operation) {
669        case SC_SEC_OPERATION_DECIPHER:
670                apdu.p1 = 0x81;
671                apdu.p2 = 0xB8;
672                break;
673        case SC_SEC_OPERATION_SIGN:
674                apdu.p1 = 0x41;
675                apdu.p2 = 0xB6;
676                break;
677        default:
678                return SC_ERROR_INVALID_ARGUMENTS;
679        }
680        apdu.le = 0;
681        p = sbuf;
682        if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
683                *p++ = 0x80;    /* algorithm reference */
684                *p++ = 0x01;
685                *p++ = env->algorithm_ref & 0xFF;
686        }
687        if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
688                *p++ = 0x81;
689                *p++ = env->file_ref.len;
690                memcpy(p, env->file_ref.value, env->file_ref.len);
691                p += env->file_ref.len;
692        }
693        if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
694                if (env->flags & SC_SEC_ENV_KEY_REF_ASYMMETRIC)
695                        *p++ = 0x83;
696                else
697                        *p++ = 0x84;
698                *p++ = env->key_ref_len;
699                memcpy(p, env->key_ref, env->key_ref_len);
700                p += env->key_ref_len;
701        }
702        r = p - sbuf;
703        apdu.lc = r;
704        apdu.datalen = r;
705        apdu.data = sbuf;
706        apdu.resplen = 0;
707        if (se_num > 0) {
708                r = sc_lock(card);
709                SC_TEST_RET(card->ctx, r, "sc_lock() failed");
710                locked = 1;
711        }
712        if (apdu.datalen != 0) {
713                r = sc_transmit_apdu(card, &apdu);
714                if (r) {
715                        sc_perror(card->ctx, r, "APDU transmit failed");
716                        goto err;
717                }
718                r = sc_check_sw(card, apdu.sw1, apdu.sw2);
719                if (r) {
720                        sc_perror(card->ctx, r, "Card returned error");
721                        goto err;
722                }
723        }
724        if (se_num <= 0)
725                return 0;
726        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
727        r = sc_transmit_apdu(card, &apdu);
728        sc_unlock(card);
729        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
730        return sc_check_sw(card, apdu.sw1, apdu.sw2);
731err:
732        if (locked)
733                sc_unlock(card);
734        return r;
735}
736
737static int iso7816_restore_security_env(sc_card_t *card, int se_num)
738{
739        sc_apdu_t apdu;
740        int r;
741        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
742       
743        assert(card != NULL);
744
745        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0xF3, se_num);
746        apdu.resplen = sizeof(rbuf) > 250 ? 250 : sizeof(rbuf);
747        apdu.resp = rbuf;
748        r = sc_transmit_apdu(card, &apdu);
749        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
750        return sc_check_sw(card, apdu.sw1, apdu.sw2);
751}
752
753static int iso7816_compute_signature(sc_card_t *card,
754                                     const u8 * data, size_t datalen,
755                                     u8 * out, size_t outlen)
756{
757        int r;
758        sc_apdu_t apdu;
759        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
760        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
761
762        assert(card != NULL && data != NULL && out != NULL);
763        if (datalen > 255)
764                SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
765
766        /* INS: 0x2A  PERFORM SECURITY OPERATION
767         * P1:  0x9E  Resp: Digital Signature
768         * P2:  0x9A  Cmd: Input for Digital Signature */
769        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x9E,
770                       0x9A);
771        apdu.resp = rbuf;
772        apdu.resplen = sizeof(rbuf); /* FIXME */
773        apdu.le = 256;
774
775        memcpy(sbuf, data, datalen);
776        apdu.data = sbuf;
777        apdu.lc = datalen;
778        apdu.datalen = datalen;
779        apdu.sensitive = 1;
780        r = sc_transmit_apdu(card, &apdu);
781        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
782        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
783                size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
784
785                memcpy(out, apdu.resp, len);
786                SC_FUNC_RETURN(card->ctx, 4, len);
787        }
788        SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
789}
790
791static int iso7816_decipher(sc_card_t *card,
792                            const u8 * crgram, size_t crgram_len,
793                            u8 * out, size_t outlen)
794{
795        int       r;
796        sc_apdu_t apdu;
797        u8        *sbuf = NULL;
798
799        assert(card != NULL && crgram != NULL && out != NULL);
800        SC_FUNC_CALLED(card->ctx, 2);
801
802        sbuf = (u8 *)malloc(crgram_len + 1);
803        if (sbuf == NULL)
804                return SC_ERROR_MEMORY_FAILURE;
805
806        /* INS: 0x2A  PERFORM SECURITY OPERATION
807         * P1:  0x80  Resp: Plain value
808         * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */
809        sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x80, 0x86);
810        apdu.resp    = out;
811        apdu.resplen = outlen;
812        /* if less than 256 bytes are expected than set Le to 0x00
813         * to tell the card the we want everything available (note: we
814         * always have Le <= crgram_len) */
815        apdu.le      = (outlen >= 256 && crgram_len < 256) ? 256 : outlen;
816        apdu.sensitive = 1;
817       
818        sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
819        memcpy(sbuf + 1, crgram, crgram_len);
820        apdu.data = sbuf;
821        apdu.lc   = crgram_len + 1;
822        apdu.datalen = crgram_len + 1;
823        r = sc_transmit_apdu(card, &apdu);
824        sc_mem_clear(sbuf, crgram_len + 1);
825        free(sbuf);
826        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
827        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
828                SC_FUNC_RETURN(card->ctx, 2, apdu.resplen);
829        else
830                SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
831}
832
833static int iso7816_build_pin_apdu(sc_card_t *card, sc_apdu_t *apdu,
834                struct sc_pin_cmd_data *data, u8 *buf, size_t buf_len)
835{
836        int r, len = 0, pad = 0, use_pin_pad = 0, ins, p1 = 0;
837       
838        switch (data->pin_type) {
839        case SC_AC_CHV:
840                break;
841        default:
842                return SC_ERROR_INVALID_ARGUMENTS;
843        }
844
845        if (data->flags & SC_PIN_CMD_NEED_PADDING)
846                pad = 1;
847        if (data->flags & SC_PIN_CMD_USE_PINPAD)
848                use_pin_pad = 1;
849
850        data->pin1.offset = 5;
851
852        switch (data->cmd) {
853        case SC_PIN_CMD_VERIFY:
854                ins = 0x20;
855                if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
856                        return r;
857                len = r;
858                break;
859        case SC_PIN_CMD_CHANGE:
860                ins = 0x24;
861                if (data->pin1.len != 0 || use_pin_pad) {
862                        if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
863                                return r;
864                        len += r;
865                } else {
866                        /* implicit test */
867                        p1 = 1;
868                }
869
870                data->pin2.offset = data->pin1.offset + len;
871                if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
872                        return r;
873                len += r;
874                break;
875        case SC_PIN_CMD_UNBLOCK:
876                ins = 0x2C;
877                if (data->pin1.len != 0 || use_pin_pad) {
878                        if ((r = sc_build_pin(buf, buf_len, &data->pin1, pad)) < 0)
879                                return r;
880                        len += r;
881                } else {
882                        p1 |= 0x02;
883                }
884
885                if (data->pin2.len != 0 || use_pin_pad) {
886                        data->pin2.offset = data->pin1.offset + len;
887                        if ((r = sc_build_pin(buf+len, buf_len-len, &data->pin2, pad)) < 0)
888                                return r;
889                        len += r;
890                } else {
891                        p1 |= 0x01;
892                }
893                break;
894        default:
895                return SC_ERROR_NOT_SUPPORTED;
896        }
897
898        sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT,
899                                ins, p1, data->pin_reference);
900
901        apdu->lc = len;
902        apdu->datalen = len;
903        apdu->data = buf;
904        apdu->resplen = 0;
905        apdu->sensitive = 1;
906
907        return 0;
908}
909
910static int iso7816_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
911                           int *tries_left)
912{
913        sc_apdu_t local_apdu, *apdu;
914        int r;
915        u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
916
917        if (tries_left)
918                *tries_left = -1;
919
920        /* See if we've been called from another card driver, which is
921         * passing an APDU to us (this allows to write card drivers
922         * whose PIN functions behave "mostly like ISO" except in some
923         * special circumstances.
924         */
925        if (data->apdu == NULL) {
926                r = iso7816_build_pin_apdu(card, &local_apdu, data, sbuf, sizeof(sbuf));
927                if (r < 0)
928                        return r;
929                data->apdu = &local_apdu;
930        }
931        apdu = data->apdu;
932
933        if (!(data->flags & SC_PIN_CMD_USE_PINPAD)) {
934                /* Transmit the APDU to the card */
935                r = sc_transmit_apdu(card, apdu);
936
937                /* Clear the buffer - it may contain pins */
938                sc_mem_clear(sbuf, sizeof(sbuf));
939        } else {
940                /* Call the reader driver to collect
941                 * the PIN and pass on the APDU to the card */
942                if (data->pin1.offset == 0) {
943                        sc_error(card->ctx,
944                                "Card driver didn't set PIN offset");
945                        return SC_ERROR_INVALID_ARGUMENTS;
946                }
947                if (card->reader
948                 && card->reader->ops
949                 && card->reader->ops->perform_verify) {
950                        r = card->reader->ops->perform_verify(card->reader,
951                                        card->slot,
952                                        data);
953                        /* sw1/sw2 filled in by reader driver */
954                } else {
955                        sc_error(card->ctx,
956                                "Card reader driver does not support "
957                                "PIN entry through reader key pad");
958                        r = SC_ERROR_NOT_SUPPORTED;
959                }
960        }
961
962        /* Don't pass references to local variables up to the caller. */
963        if (data->apdu == &local_apdu)
964                data->apdu = NULL;
965
966        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
967        if (apdu->sw1 == 0x63) {
968                if ((apdu->sw2 & 0xF0) == 0xC0 && tries_left != NULL)
969                        *tries_left = apdu->sw2 & 0x0F;
970                return SC_ERROR_PIN_CODE_INCORRECT;
971        }
972        return sc_check_sw(card, apdu->sw1, apdu->sw2);
973}
974
975static int no_match(sc_card_t *card)
976{
977        return 0;
978}
979
980static struct sc_card_operations iso_ops = {
981        no_match,
982        NULL,                   /* init   */
983        NULL,                   /* finish */
984        iso7816_read_binary,
985        iso7816_write_binary,