root/trunk/src/libopensc/card-cardos.c

Revision 3552, 32.1 KB (checked in by aj, 4 months ago)

Apply security fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * card-cardos.c: Support for Siemens CardOS based cards and tokens
3 *      (for example Aladdin eToken PRO, Eutron CryptoIdentity IT-SEC)
4 *
5 * Copyright (c) 2005  Nils Larsch <nils@larsch.net>
6 * Copyright (C) 2002  Andreas Jellinghaus <aj@dungeon.inka.de>
7 * Copyright (C) 2001  Juha YrjölÀ <juha.yrjola@iki.fi>
8 *
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
13 *
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 * Lesser General Public License for more details.
18 *
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 */
23
24#include "internal.h"
25#include "cardctl.h"
26#include <ctype.h>
27#include <string.h>
28
29#include <opensc/asn1.h>
30
31static const struct sc_card_operations *iso_ops = NULL;
32
33static struct sc_card_operations cardos_ops;
34static struct sc_card_driver cardos_drv = {
35        "Siemens CardOS",
36        "cardos",
37        &cardos_ops,
38        NULL, 0, NULL
39};
40
41static struct sc_atr_table cardos_atrs[] = {
42        /* 4.0 */
43        { "3b:e2:00:ff:c1:10:31:fe:55:c8:02:9c", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
44        /* Italian eID card, postecert */
45        { "3b:e9:00:ff:c1:10:31:fe:55:00:64:05:00:c8:02:31:80:00:47", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
46        /* Italian eID card, infocamere */
47        { "3b:fb:98:00:ff:c1:10:31:fe:55:00:64:05:20:47:03:31:80:00:90:00:f3", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
48        /* Another Italian InfocamereCard */
49        { "3b:fc:98:00:ff:c1:10:31:fe:55:c8:03:49:6e:66:6f:63:61:6d:65:72:65:28", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
50        { "3b:f4:98:00:ff:c1:10:31:fe:55:4d:34:63:76:b4", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL},
51        /* cardos m4.2 and above */
52        { "3b:f2:18:00:ff:c1:0a:31:fe:55:c8:06:8a", "ff:ff:0f:ff:00:ff:00:ff:ff:00:00:00:00", NULL, SC_CARD_TYPE_CARDOS_M4_2, 0, NULL },
53        { NULL, NULL, NULL, 0, 0, NULL }
54};
55
56static int cardos_finish(sc_card_t *card)
57{
58        return 0;
59}
60
61static int cardos_match_card(sc_card_t *card)
62{
63        int i;
64
65        i = _sc_match_atr(card, cardos_atrs, &card->type);
66        if (i < 0)
67                return 0;
68        if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
69                int rv;
70                sc_apdu_t apdu;
71                u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
72                /* first check some additional ATR bytes */
73                if ((card->atr[4] != 0xff && card->atr[4] != 0x02) ||
74                    (card->atr[6] != 0x10 && card->atr[6] != 0x0a) ||
75                    (card->atr[9] != 0x55 && card->atr[9] != 0x58))
76                        return 0;
77                /* get the os version using GET DATA and compare it with
78                 * version in the ATR */
79                sc_debug(card->ctx, "checking cardos version ...");
80                sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x82);
81                apdu.resp = rbuf;
82                apdu.resplen = sizeof(rbuf);
83                apdu.le = 256;
84                apdu.lc = 0;
85                rv = sc_transmit_apdu(card, &apdu);
86                SC_TEST_RET(card->ctx, rv, "APDU transmit failed");
87                if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
88                        return 0;
89                if (apdu.resp[0] != card->atr[10] ||
90                    apdu.resp[1] != card->atr[11])
91                        /* version mismatch */
92                        return 0;
93                if (card->atr[11] <= 0x04) {
94                        sc_debug(card->ctx, "found cardos m4.01");
95                        card->type = SC_CARD_TYPE_CARDOS_M4_01;
96                } else if (card->atr[11] == 0x08) {
97                        sc_debug(card->ctx, "found cardos v4.3b");
98                        card->type = SC_CARD_TYPE_CARDOS_M4_3;
99                } else if (card->atr[11] == 0x09) {
100                        sc_debug(card->ctx, "found cardos v4.2b");
101                        card->type = SC_CARD_TYPE_CARDOS_M4_2B;
102                } else if (card->atr[11] >= 0x0B) {
103                        sc_debug(card->ctx, "found cardos v4.2c or higher");
104                        card->type = SC_CARD_TYPE_CARDOS_M4_2C;
105                } else {
106                        sc_debug(card->ctx, "found cardos m4.2");
107                }
108        }
109        return 1;
110}
111
112static int cardos_have_2048bit_package(sc_card_t *card)
113{
114        sc_apdu_t apdu;
115        u8        rbuf[SC_MAX_APDU_BUFFER_SIZE];
116        int       r;
117        const u8  *p = rbuf, *q;
118        size_t    len, tlen = 0, ilen = 0;
119
120        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
121        apdu.resp    = rbuf;
122        apdu.resplen = sizeof(rbuf);
123        apdu.lc = 0;
124        apdu.le = 256;
125        r = sc_transmit_apdu(card, &apdu);
126        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
127
128        if ((len = apdu.resplen) == 0)
129                /* looks like no package has been installed  */
130                return 0;
131
132        while (len != 0) {
133                p = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
134                if (p == NULL)
135                        return 0;
136                q = sc_asn1_find_tag(card->ctx, p, tlen, 0x01, &ilen);
137                if (q == NULL || ilen != 4)
138                        return 0;
139                if (q[0] == 0x1c)
140                        return 1;
141                p   += tlen;
142                len -= tlen + 2;
143        }
144
145        return 0;
146}
147
148static int cardos_init(sc_card_t *card)
149{
150        unsigned long   flags;
151
152        card->name = "CardOS M4";
153        card->cla = 0x00;
154
155        /* Set up algorithm info. */
156        flags = SC_ALGORITHM_NEED_USAGE
157                | SC_ALGORITHM_RSA_RAW
158                | SC_ALGORITHM_RSA_HASH_NONE
159                | SC_ALGORITHM_ONBOARD_KEY_GEN
160                ;
161        _sc_card_add_rsa_alg(card,  512, flags, 0);
162        _sc_card_add_rsa_alg(card,  768, flags, 0);
163        _sc_card_add_rsa_alg(card, 1024, flags, 0);
164
165        if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
166                int r = cardos_have_2048bit_package(card);
167                if (r < 0)
168                        return r;
169                if (r == 1)
170                        card->caps |= SC_CARD_CAP_RSA_2048;
171                card->caps |= SC_CARD_CAP_APDU_EXT;
172        } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3
173                || card->type == SC_CARD_TYPE_CARDOS_M4_2B
174                || card->type == SC_CARD_TYPE_CARDOS_M4_2C) {
175                card->caps |= SC_CARD_CAP_RSA_2048;
176                card->caps |= SC_CARD_CAP_APDU_EXT;
177        }
178
179        if (card->caps & SC_CARD_CAP_RSA_2048) {
180                _sc_card_add_rsa_alg(card, 1280, flags, 0);
181                _sc_card_add_rsa_alg(card, 1536, flags, 0);
182                _sc_card_add_rsa_alg(card, 1792, flags, 0);
183                _sc_card_add_rsa_alg(card, 2048, flags, 0);
184        }
185
186        return 0;
187}
188
189static const struct sc_card_error cardos_errors[] = {
190/* some error inside the card */
191/* i.e. nothing you can do */
192{ 0x6581, SC_ERROR_MEMORY_FAILURE,      "EEPROM error; command aborted"},
193{ 0x6fff, SC_ERROR_CARD_CMD_FAILED,     "internal assertion error"},
194{ 0x6700, SC_ERROR_WRONG_LENGTH,        "LC invalid"},
195{ 0x6985, SC_ERROR_CARD_CMD_FAILED,     "no random number available"},
196{ 0x6f81, SC_ERROR_CARD_CMD_FAILED,     "file invalid, maybe checksum error"},
197{ 0x6f82, SC_ERROR_CARD_CMD_FAILED,     "not enough memory in xram"},
198{ 0x6f84, SC_ERROR_CARD_CMD_FAILED,     "general protection fault"},
199
200/* the card doesn't now thic combination of ins+cla+p1+p2 */
201/* i.e. command will never work */
202{ 0x6881, SC_ERROR_NO_CARD_SUPPORT,     "logical channel not supported"},
203{ 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"},
204{ 0x6d00, SC_ERROR_INS_NOT_SUPPORTED,   "ins invalid"},
205{ 0x6e00, SC_ERROR_CLASS_NOT_SUPPORTED, "class invalid (hi nibble)"},
206
207/* known command, but incorrectly used */
208/* i.e. command could work, but you need to change something */
209{ 0x6981, SC_ERROR_CARD_CMD_FAILED,     "command cannot be used for file structure"},
210{ 0x6a80, SC_ERROR_INCORRECT_PARAMETERS,"invalid parameters in data field"},
211{ 0x6a81, SC_ERROR_NOT_SUPPORTED,       "function/mode not supported"},
212{ 0x6a85, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit the tlv structure"},
213{ 0x6986, SC_ERROR_INCORRECT_PARAMETERS,"no current ef selected"},
214{ 0x6a87, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit p1/p2"},
215{ 0x6c00, SC_ERROR_WRONG_LENGTH,        "le does not fit the data to be sent"},
216{ 0x6f83, SC_ERROR_CARD_CMD_FAILED,     "command must not be used in transaction"},
217
218/* (something) not found */
219{ 0x6987, SC_ERROR_INCORRECT_PARAMETERS,"key object for sm not found"},
220{ 0x6f86, SC_ERROR_CARD_CMD_FAILED,     "key object not found"},
221{ 0x6a82, SC_ERROR_FILE_NOT_FOUND,      "file not found"},
222{ 0x6a83, SC_ERROR_RECORD_NOT_FOUND,    "record not found"},
223{ 0x6a88, SC_ERROR_CARD_CMD_FAILED,     "object not found"},
224
225/* (something) invalid */
226{ 0x6884, SC_ERROR_CARD_CMD_FAILED,     "chaining error"},
227{ 0x6984, SC_ERROR_CARD_CMD_FAILED,     "bs object has invalid format"},
228{ 0x6988, SC_ERROR_INCORRECT_PARAMETERS,"key object used for sm has invalid format"},
229
230/* (something) deactivated */
231{ 0x6283, SC_ERROR_CARD_CMD_FAILED,     "file is deactivated"   },
232{ 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "bs object blocked"},
233
234/* access denied */
235{ 0x6300, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"authentication failed"},
236{ 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"required access right not granted"},
237
238/* other errors */
239{ 0x6a84, SC_ERROR_CARD_CMD_FAILED,     "not enough memory"},
240
241/* command ok, execution failed */
242{ 0x6f00, SC_ERROR_CARD_CMD_FAILED,     "technical error (see eToken developers guide)"},
243
244/* no error, maybe a note */
245{ 0x9000, SC_NO_ERROR,          NULL},
246{ 0x9001, SC_NO_ERROR,          "success, but eeprom weakness detected"},
247{ 0x9850, SC_NO_ERROR,          "over/underflow useing in/decrease"}
248};
249
250static int cardos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
251{
252        const int err_count = sizeof(cardos_errors)/sizeof(cardos_errors[0]);
253        int i;
254                               
255        for (i = 0; i < err_count; i++) {
256                if (cardos_errors[i].SWs == ((sw1 << 8) | sw2)) {
257                        if ( cardos_errors[i].errorstr )
258                                sc_error(card->ctx, "%s\n",
259                                        cardos_errors[i].errorstr);
260                        return cardos_errors[i].errorno;
261                }
262        }
263
264        sc_error(card->ctx, "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
265        return SC_ERROR_CARD_CMD_FAILED;
266}
267
268static int cardos_list_files(sc_card_t *card, u8 *buf, size_t buflen)
269{
270        sc_apdu_t apdu;
271        u8        rbuf[256], offset = 0;
272        const u8  *p = rbuf, *q;
273        int       r;
274        size_t    fids = 0, len;
275
276        SC_FUNC_CALLED(card->ctx, 1);
277
278        /* 0x16: DIRECTORY */
279        /* 0x02: list both DF and EF */
280
281get_next_part:
282        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x16, 0x02, offset);
283        apdu.cla = 0x80;
284        apdu.le = 256;
285        apdu.resplen = 256;
286        apdu.resp = rbuf;
287
288        r = sc_transmit_apdu(card, &apdu);
289        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
290        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
291        SC_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
292
293        if (apdu.resplen > 256) {
294                sc_error(card->ctx, "directory listing > 256 bytes, cutting");
295                r = 256;
296        }
297
298        len = apdu.resplen;
299        while (len != 0) {
300                size_t   tlen = 0, ilen = 0;
301                /* is there a file informatin block (0x6f) ? */
302                p = sc_asn1_find_tag(card->ctx, p, len, 0x6f, &tlen);
303                if (p == NULL) {
304                        sc_error(card->ctx, "directory tag missing");
305                        return SC_ERROR_INTERNAL;
306                }
307                if (tlen == 0)
308                        /* empty directory */
309                        break;
310                q = sc_asn1_find_tag(card->ctx, p, tlen, 0x86, &ilen);
311                if (q == NULL || ilen != 2) {
312                        sc_error(card->ctx, "error parsing file id TLV object");
313                        return SC_ERROR_INTERNAL;
314                }
315                /* put file id in buf */
316                if (buflen >= 2) {
317                        buf[fids++] = q[0];
318                        buf[fids++] = q[1];
319                        buflen -= 2;
320                } else
321                        /* not enought space left in buffer => break */
322                        break;
323                /* extract next offset */
324                q = sc_asn1_find_tag(card->ctx, p, tlen, 0x8a, &ilen);
325                if (q != NULL && ilen == 1) {
326                        offset = (u8)ilen;
327                        if (offset != 0)
328                                goto get_next_part;
329                }
330                len -= tlen + 2;
331                p   += tlen;
332        }
333
334        r = fids;
335
336        SC_FUNC_RETURN(card->ctx, 1, r);
337}
338
339static void add_acl_entry(sc_file_t *file, int op, u8 byte)
340{
341        unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
342
343        switch (byte) {
344        case 0x00:
345                method = SC_AC_NONE;
346                break;
347        case 0xFF:
348                method = SC_AC_NEVER;
349                break;
350        default:
351                if (byte > 0x7F) {
352                        method = SC_AC_UNKNOWN;
353                } else {
354                        method = SC_AC_CHV;
355                        key_ref = byte;
356                }
357                break;
358        }
359        sc_file_add_acl_entry(file, op, method, key_ref);
360}
361
362static int acl_to_byte(const sc_acl_entry_t *e)
363{
364        if (e != NULL) {
365                switch (e->method) {
366                case SC_AC_NONE:
367                        return 0x00;
368                case SC_AC_NEVER:
369                        return 0xFF;
370                case SC_AC_CHV:
371                case SC_AC_TERM:
372                case SC_AC_AUT:
373                        if (e->key_ref == SC_AC_KEY_REF_NONE)
374                                return -1;
375                        if (e->key_ref > 0x7F)
376                                return -1;
377                        return e->key_ref;
378                }
379        }
380        return 0x00;
381}
382
383static const int df_acl[9] = {
384        -1,                     /* LCYCLE (life cycle change) */
385        SC_AC_OP_UPDATE,        /* UPDATE Objects */
386        -1,                     /* APPEND Objects */
387
388        SC_AC_OP_INVALIDATE,    /* DF */
389        SC_AC_OP_REHABILITATE,  /* DF */
390        SC_AC_OP_DELETE,        /* DF */
391
392        SC_AC_OP_UPDATE,        /* ADMIN DF */
393        SC_AC_OP_CREATE,        /* Files */
394        -1                      /* Reserved */
395};
396static const int ef_acl[9] = {
397        SC_AC_OP_READ,          /* Data */
398        SC_AC_OP_UPDATE,        /* Data (write file content) */
399        SC_AC_OP_WRITE,         /* */
400
401        SC_AC_OP_INVALIDATE,    /* EF */
402        SC_AC_OP_REHABILITATE,  /* EF */
403        SC_AC_OP_DELETE,        /* (delete) EF */
404
405        /* XXX: ADMIN should be an ACL type of its own, or mapped
406         * to erase */
407        SC_AC_OP_UPDATE,        /* ADMIN EF (modify meta information?) */
408        -1,                     /* INC (-> cylic fixed files) */
409        -1                      /* DEC */
410};
411
412static void parse_sec_attr(sc_file_t *file, const u8 *buf, size_t len)
413{
414        size_t i;
415        const int *idx;
416
417        idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
418
419        /* acl defaults to 0xFF if unspecified */
420        for (i = 0; i < 9; i++)
421                if (idx[i] != -1)
422                        add_acl_entry(file, idx[i], (u8)((i < len) ? buf[i] : 0xFF));
423}
424
425static int cardos_select_file(sc_card_t *card,
426                              const sc_path_t *in_path,
427                              sc_file_t **file)
428{
429        int r;
430       
431        SC_FUNC_CALLED(card->ctx, 1);
432        r = iso_ops->select_file(card, in_path, file);
433        if (r >= 0 && file)
434                parse_sec_attr((*file), (*file)->sec_attr, (*file)->sec_attr_len);
435        SC_FUNC_RETURN(card->ctx, 1, r);
436}
437
438static int cardos_acl_to_bytes(sc_card_t *card, const sc_file_t *file,
439        u8 *buf, size_t *outlen)
440{
441        int       i, byte;
442        const int *idx;
443
444        if (buf == NULL || *outlen < 9)
445                return SC_ERROR_INVALID_ARGUMENTS;
446
447        idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
448        for (i = 0; i < 9; i++) {
449                if (idx[i] < 0)
450                        byte = 0x00;
451                else
452                        byte = acl_to_byte(sc_file_get_acl_entry(file, idx[i]));
453                if (byte < 0) {
454                        sc_error(card->ctx, "Invalid ACL\n");
455                        return SC_ERROR_INVALID_ARGUMENTS;
456                }
457                buf[i] = byte;
458        }
459        *outlen = 9;
460
461        return SC_SUCCESS;
462}
463
464static int cardos_set_file_attributes(sc_card_t *card, sc_file_t *file)
465{
466        int r;
467
468        if (file->type_attr_len == 0) {
469                u8 type[3];
470
471                memset(type, 0, sizeof(type));
472                type[0] = 0x00;
473                switch (file->type) {
474                case SC_FILE_TYPE_WORKING_EF:
475                        break;
476                case SC_FILE_TYPE_DF:
477                        type[0] = 0x38;
478                        break;
479                default:
480                        return SC_ERROR_NOT_SUPPORTED;
481                }
482                if (file->type != SC_FILE_TYPE_DF) {
483                        switch (file->ef_structure) {
484                        case SC_FILE_EF_LINEAR_FIXED_TLV:
485                        case SC_FILE_EF_LINEAR_VARIABLE:
486                        case SC_FILE_EF_CYCLIC_TLV:
487                                return SC_ERROR_NOT_SUPPORTED;
488                                /* No idea what this means, but it
489                                 * seems to be required for key
490                                 * generation. */
491                        case SC_FILE_EF_LINEAR_VARIABLE_TLV:
492                                type[1] = 0xff;
493                        default:
494                                type[0] |= file->ef_structure & 7;
495                                break;
496                        }
497                }
498                r = sc_file_set_type_attr(file, type, sizeof(type));
499                if (r != SC_SUCCESS)
500                        return r;
501        }
502        if (file->prop_attr_len == 0) {
503                u8 status[3];
504
505                status[0] = 0x01;
506                if (file->type == SC_FILE_TYPE_DF) {
507                        status[1] = file->size >> 8;
508                        status[2] = file->size;
509                } else {
510                        status[1] = status[2] = 0x00; /* not used */
511                }
512                r = sc_file_set_prop_attr(file, status, sizeof(status));
513                if (r != SC_SUCCESS)
514                        return r;
515        }
516        if (file->sec_attr_len == 0) {
517                u8     acl[9];
518                size_t blen = sizeof(acl);
519
520                r = cardos_acl_to_bytes(card, file, acl, &blen);
521                if (r != SC_SUCCESS)
522                        return r;
523                r = sc_file_set_sec_attr(file, acl, blen);
524                if (r != SC_SUCCESS)
525                        return r;
526        }
527        return SC_SUCCESS;
528}
529
530/* newer versions of cardos seems to prefer the FCP */
531static int cardos_construct_fcp(sc_card_t *card, const sc_file_t *file,
532        u8 *out, size_t *outlen)
533{
534        u8     buf[64], *p = out;
535        size_t inlen = *outlen, len;
536        int    r;
537
538        SC_FUNC_CALLED(card->ctx, 2);
539
540        if (out == NULL || inlen < 64)
541                return SC_ERROR_INVALID_ARGUMENTS;
542        /* add FCP tag */
543        *p++ = 0x62;
544        /* we will add the length later  */
545        p++;
546
547        /* set the length */
548        buf[0] = (file->size >> 8) & 0xff;
549        buf[1] = file->size        & 0xff;
550        if (file->type == SC_FILE_TYPE_DF)
551                r = sc_asn1_put_tag(0x81, buf, 2, p, 4, &p);
552        else
553                r = sc_asn1_put_tag(0x80, buf, 2, p, 4, &p);
554        if (r != SC_SUCCESS)
555                return r;
556        /* set file type  */
557        if (file->shareable != 0)
558                buf[0] = 0x40;
559        else
560                buf[0] = 0x00;
561        if (file->type == SC_FILE_TYPE_WORKING_EF) {
562                switch (file->ef_structure) {
563                case SC_FILE_EF_TRANSPARENT:
564                        buf[0] |= 0x01;
565                        break;
566                case SC_FILE_EF_LINEAR_VARIABLE_TLV:
567                        buf[0] |= 0x05;
568                        break;
569                case SC_FILE_EF_LINEAR_FIXED:
570                        buf[0] |= 0x02;
571                        buf[1] |= 0x21;
572                        buf[2] |= 0x00;
573                        buf[3] |= (u8) file->record_length;
574                        buf[4] |= (u8) file->record_count;
575                        break;
576                case SC_FILE_EF_CYCLIC:
577                        buf[0] |= 0x06;
578                        buf[1] |= 0x21;
579                        buf[2] |= 0x00;
580                        buf[3] |= (u8) file->record_length;
581                        buf[4] |= (u8) file->record_count;
582                        break;
583                default:
584                        sc_error(card->ctx, "unknown EF type: %u", file->type);
585                        return SC_ERROR_INVALID_ARGUMENTS;
586                }
587                if (file->ef_structure == SC_FILE_EF_CYCLIC ||
588                    file->ef_structure == SC_FILE_EF_LINEAR_FIXED)
589                r = sc_asn1_put_tag(0x82, buf, 5, p, 8, &p);
590        else
591                r = sc_asn1_put_tag(0x82, buf, 1, p, 8, &p);
592        } else if (file->type == SC_FILE_TYPE_DF) {
593                buf[0] |= 0x38;
594                r = sc_asn1_put_tag(0x82, buf, 1, p, 8, &p);
595        } else
596                return SC_ERROR_NOT_SUPPORTED;
597        if (r != SC_SUCCESS)
598                return r;
599        /* set file id */
600        buf[0] = (file->id >> 8) & 0xff;
601        buf[1] = file->id        & 0xff;
602        r = sc_asn1_put_tag(0x83, buf, 2, p, 8, &p);
603        if (r != SC_SUCCESS)
604                return r;
605        /* set aid (for DF only) */
606        if (file->type == SC_FILE_TYPE_DF && file->namelen != 0) {
607                r = sc_asn1_put_tag(0x84, file->name, file->namelen, p, 20, &p);
608                if (r != SC_SUCCESS)
609                        return r;
610        }
611        /* set proprietary file attributes */
612        buf[0] = 0x00;          /* use default values */
613        if (file->type == SC_FILE_TYPE_DF)
614                r = sc_asn1_put_tag(0x85, buf, 1, p, 8, &p);
615        else {
616                buf[1] = 0x00;
617                buf[2] = 0x00;
618                r = sc_asn1_put_tag(0x85, buf, 1, p, 8, &p);
619        }
620        if (r != SC_SUCCESS)
621                return r;
622        /* set ACs  */
623        len = 9;
624        r = cardos_acl_to_bytes(card, file, buf, &len);
625        if (r != SC_SUCCESS)
626                return r;
627        r = sc_asn1_put_tag(0x86, buf, len, p, 18, &p);
628        if (r != SC_SUCCESS)
629                return r;
630        /* finally set the length of the FCP */
631        out[1] = p - out - 2;
632
633        *outlen = p - out;
634
635        return SC_SUCCESS;
636}
637
638static int cardos_create_file(sc_card_t *card, sc_file_t *file)
639{
640        int       r;
641
642        SC_FUNC_CALLED(card->ctx, 1);
643
644        if (card->type == SC_CARD_TYPE_CARDOS_GENERIC ||
645            card->type == SC_CARD_TYPE_CARDOS_M4_01) {
646                r = cardos_set_file_attributes(card, file);
647                if (r != SC_SUCCESS)
648                        return r;
649                return iso_ops->create_file(card, file);
650        } else if (card->type == SC_CARD_TYPE_CARDOS_M4_2 ||
651                   card->type == SC_CARD_TYPE_CARDOS_M4_3 ||
652                   card->type == SC_CARD_TYPE_CARDOS_M4_2B ||
653                   card->type == SC_CARD_TYPE_CARDOS_M4_2C) {
654                u8        sbuf[SC_MAX_APDU_BUFFER_SIZE];
655                size_t    len = sizeof(sbuf);
656                sc_apdu_t apdu;
657
658                r = cardos_construct_fcp(card, file, sbuf, &len);
659                if (r < 0) {
660                        sc_error(card->ctx, "unable to create FCP");
661                        return r;
662                }
663       
664                sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
665                apdu.lc      = len;
666                apdu.datalen = len;
667                apdu.data    = sbuf;
668
669                r = sc_transmit_apdu(card, &apdu);
670                SC_TEST_RET(card->ctx, r, "APDU transmit failed");
671
672                return sc_check_sw(card, apdu.sw1, apdu.sw2);
673        } else
674                return SC_ERROR_NOT_SUPPORTED;
675}
676
677/*
678 * Restore the indicated SE
679 */
680static int
681cardos_restore_security_env(sc_card_t *card, int se_num)
682{
683        sc_apdu_t apdu;
684        int     r;
685
686        SC_FUNC_CALLED(card->ctx, 1);
687
688        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 3, se_num);
689
690        r = sc_transmit_apdu(card, &apdu);
691        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
692
693        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
694        SC_TEST_RET(card->ctx, r, "Card returned error");
695
696        SC_FUNC_RETURN(card->ctx, 1, r);
697}
698
699/*
700 * Set the security context
701 * Things get a little messy here. It seems you cannot do any
702 * crypto without a security environment - but there isn't really
703 * a way to specify the security environment in PKCS15.
704 * What I'm doing here (for now) is to assume that for a key
705 * object with ID 0xNN there is always a corresponding SE object
706 * with the same ID.
707 * XXX Need to find out how the Aladdin drivers do it.
708 */
709static int
710cardos_set_security_env(sc_card_t *card,
711                            const sc_security_env_t *env,
712                            int se_num)
713{
714        sc_apdu_t apdu;
715        u8      data[3];
716        int     key_id, r;
717
718        assert(card != NULL && env != NULL);
719
720        if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
721         || env->key_ref_len != 1) {
722                sc_error(card->ctx, "No or invalid key reference\n");
723                return SC_ERROR_INVALID_ARGUMENTS;
724        }
725        key_id = env->key_ref[0];
726
727        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 1, 0);
728        switch (env->operation) {
729        case SC_SEC_OPERATION_DECIPHER:
730                apdu.p2 = 0xB8;
731                break;
732        case SC_SEC_OPERATION_SIGN:
733                apdu.p2 = 0xB6;
734                break;
735        default:
736                return SC_ERROR_INVALID_ARGUMENTS;
737        }
738
739        data[0] = 0x83;
740        data[1] = 0x01;
741        data[2] = key_id;
742        apdu.lc = apdu.datalen = 3;
743        apdu.data = data;
744
745        r = sc_transmit_apdu(card, &apdu);
746        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
747
748        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
749        SC_TEST_RET(card->ctx, r, "Card returned error");
750
751        SC_FUNC_RETURN(card->ctx, 1, r);
752}
753
754/*
755 * Compute digital signature
756 */
757
758/* internal function to do the actual signature computation */
759static int
760do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
761                     u8 *out, size_t outlen)
762{
763        int r;
764        sc_apdu_t apdu;
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, 0x2A, 0x9E, 0x9A);
770        apdu.resp    = out;
771        apdu.le      = outlen;
772        apdu.resplen = outlen;
773
774        apdu.data    = data;
775        apdu.lc      = datalen;
776        apdu.datalen = datalen;
777        apdu.sensitive = 1;
778        r = sc_transmit_apdu(card, &apdu);
779        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
780
781        if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
782                SC_FUNC_RETURN(card->ctx, 4, apdu.resplen);
783        else
784                SC_FUNC_RETURN(card->ctx, 4, sc_check_sw(card, apdu.sw1, apdu.sw2));
785}
786
787static int
788cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
789                         u8 *out, size_t outlen)
790{
791        int    r;
792        u8     buf[SC_MAX_APDU_BUFFER_SIZE];
793        size_t buf_len = sizeof(buf), tmp_len = buf_len;
794        sc_context_t *ctx;
795
796        assert(card != NULL && data != NULL && out != NULL);   
797        ctx = card->ctx;
798        SC_FUNC_CALLED(ctx, 1);
799
800        if (datalen > SC_MAX_APDU_BUFFER_SIZE)
801                SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
802        if (outlen < datalen)
803                SC_FUNC_RETURN(card->ctx, 4, SC_ERROR_BUFFER_TOO_SMALL);
804        outlen = datalen;
805
806        /* XXX As we don't know what operations are allowed with a
807         * certain key, let's try RSA_PURE etc. and see which operation
808         * succeeds (this is not really beautiful, but currently the
809         * only way I see) -- Nils
810         *
811         * We also check for several caps flags here to pervent generating
812         * invalid signatures with duplicated hash prefixes with some cards
813         */
814
815    if (ctx->debug >= 3) {       
816        if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED)
817            sc_debug(ctx, "Forcing RAW_HASH_STRIPPED\n");               
818        if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH)
819            sc_debug(ctx, "Forcing RAW_HASH\n");
820    }
821
822        if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH))) {
823                if (ctx->debug >= 3)
824                        sc_debug(ctx, "trying RSA_PURE_SIG (padded DigestInfo)\n");
825                sc_ctx_suppress_errors_on(ctx);
826                r = do_compute_signature(card, data, datalen, out, outlen);
827                sc_ctx_suppress_errors_off(ctx);
828                if (r >= SC_SUCCESS)
829                        SC_FUNC_RETURN(ctx, 4, r);
830        }               
831               
832        if (ctx->debug >= 3)
833                sc_debug(ctx, "trying RSA_SIG (just the DigestInfo)\n");
834        /* remove padding: first try pkcs1 bt01 padding */
835        r = sc_pkcs1_strip_01_padding(data, datalen, buf, &tmp_len);
836        if (r != SC_SUCCESS) {
837                const u8 *p = data;
838                /* no pkcs1 bt01 padding => let's try zero padding
839                 * This can only work if the data tbs doesn't have a
840                 * leading 0 byte.  */
841                tmp_len = buf_len;
842                while (*p == 0 && tmp_len != 0) {
843                        ++p;
844                        --tmp_len;
845                }
846                memcpy(buf, p, tmp_len);
847        }
848
849        if (!(card->caps & (SC_CARD_CAP_ONLY_RAW_HASH_STRIPPED | SC_CARD_CAP_ONLY_RAW_HASH)) || card->caps & SC_CARD_CAP_ONLY_RAW_HASH ) {
850                if (ctx->debug >= 3)
851                        sc_debug(ctx, "trying to sign raw hash value with prefix\n");   
852                sc_ctx_suppress_errors_on(ctx);
853                r = do_compute_signature(card, buf, tmp_len, out, outlen);
854                sc_ctx_suppress_errors_off(ctx);
855                if (r >= SC_SUCCESS)   
856                        SC_FUNC_RETURN(ctx, 4, r);
857        }
858
859        if (card->caps & SC_CARD_CAP_ONLY_RAW_HASH) {
860            sc_debug(ctx, "Failed to sign raw hash value with prefix when forcing\n");
861            SC_FUNC_RETURN(ctx, 4, SC_ERROR_INVALID_ARGUMENTS);
862        }
863           
864        if (ctx->debug >= 3)
865                sc_debug(ctx, "trying to sign stripped raw hash value (card is responsible for prefix)\n");
866        r = sc_pkcs1_strip_digest_info_prefix(NULL,buf,tmp_len,buf,&buf_len);
867        if (r != SC_SUCCESS)
868                SC_FUNC_RETURN(ctx, 4, r);
869        return do_compute_signature(card, buf, buf_len, out, outlen);
870}
871
872static int
873cardos_lifecycle_get(sc_card_t *card, int *mode)
874{
875        sc_apdu_t       apdu;
876        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
877        int             r;
878
879        SC_FUNC_CALLED(card->ctx, 1);
880
881        sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x83);
882        apdu.cla = 0x00;
883        apdu.le = 256;
884        apdu.resplen = sizeof(rbuf);
885        apdu.resp = rbuf;
886
887        r = sc_transmit_apdu(card, &apdu);
888        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
889
890        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
891        SC_TEST_RET(card->ctx, r, "Card returned error");
892
893        if (apdu.resplen < 1) {
894                SC_TEST_RET(card->ctx, r, "Lifecycle byte not in response");
895        }
896
897        r = SC_SUCCESS;
898        switch (rbuf[0]) {
899        case 0x10:
900                *mode = SC_CARDCTRL_LIFECYCLE_USER;
901                break;
902        case 0x20:
903                *mode = SC_CARDCTRL_LIFECYCLE_ADMIN;
904                break;
905        case 0x34: /* MANUFACTURING */
906                *mode = SC_CARDCTRL_LIFECYCLE_OTHER;
907                break;
908        default:
909                sc_error(card->ctx, "Unknown lifecycle byte %d", rbuf[0]);
910                r = SC_ERROR_INTERNAL;
911        }
912
913        SC_FUNC_RETURN(card->ctx, 1, r);
914}
915
916static int
917cardos_lifecycle_set(sc_card_t *card, int *mode)
918{
919        sc_apdu_t       apdu;
920        int             r;
921
922        int current;
923        int target;
924
925        SC_FUNC_CALLED(card->ctx, 1);
926
927        target = *mode;
928
929        r = cardos_lifecycle_get(card, &current);
930       
931        if (r != SC_SUCCESS)
932                return r;
933
934        if (current == target || current == SC_CARDCTRL_LIFECYCLE_OTHER)
935                return SC_SUCCESS;
936
937        sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x10, 0, 0);
938        apdu.cla = 0x80;
939        apdu.le = 0;
940        apdu.resplen = 0;
941        apdu.resp = NULL;
942
943        r = sc_transmit_apdu(card, &apdu);
944        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
945
946        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
947        SC_TEST_RET(card->ctx, r, "Card returned error");
948
949        SC_FUNC_RETURN(card->ctx, 1, r);
950}
951
952static int
953cardos_put_data_oci(sc_card_t *card,
954                        struct sc_cardctl_cardos_obj_info *args)
955{
956        sc_apdu_t       apdu;
957        int             r;
958
959        SC_FUNC_CALLED(card->ctx, 1);
960
961        memset(&apdu, 0, sizeof(apdu));
962        apdu.cse = SC_APDU_CASE_3_SHORT;
963        apdu.cla = 0x00;
964        apdu.ins = 0xda;
965        apdu.p1  = 0x01;
966        apdu.p2  = 0x6e;
967        apdu.lc  = args->len;
968        apdu.data = args->data;
969        apdu.datalen = args->len;
970
971        r = sc_transmit_apdu(card, &apdu);
972        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
973
974        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
975        SC_TEST_RET(card->ctx, r, "Card returned error");
976
977        SC_FUNC_RETURN(card->ctx, 1, r);
978}
979
980static int
981cardos_put_data_seci(sc_card_t *card,
982                        struct sc_cardctl_cardos_obj_info *args)
983{
984        sc_apdu_t       apdu;
985        int             r;
986
987        memset(&apdu, 0,