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

Revision 3308, 35.6 KB (checked in by martin, 12 months ago)

Remove unused code.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * card-mcrd.c: Support for MICARDO cards
3 *
4 * Copyright (C) 2004  Martin Paljak <martin@paljak.pri.ee>
5 * Copyright (C) 2004  Priit Randla <priit.randla@eyp.ee>
6 * Copyright (C) 2003  Marie Fischer <marie@vtl.ee>
7 * Copyright (C) 2001  Juha YrjölÀ <juha.yrjola@iki.fi>
8 * Copyright (C) 2002  g10 Code GmbH
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 */
24
25#include "internal.h"
26#include "asn1.h"
27#include "cardctl.h"
28#include <stdlib.h>
29#include <string.h>
30#include <ctype.h>
31#include "esteid.h"
32
33static struct sc_atr_table mcrd_atrs[] = {
34        {"3B:FF:94:00:FF:80:B1:FE:45:1F:03:00:68:D2:76:00:00:28:FF:05:1E:31:80:00:90:00:23", NULL,
35          "Micardo 2.1/German BMI/D-Trust", SC_CARD_TYPE_MCRD_GENERIC, 0, NULL},
36        {"3b:6f:00:ff:00:68:d2:76:00:00:28:ff:05:1e:31:80:00:90:00", NULL,
37          "D-Trust", SC_CARD_TYPE_MCRD_DTRUST, 0, NULL},
38        {"3b:ff:11:00:ff:80:b1:fe:45:1f:03:00:68:d2:76:00:00:28:ff:05:1e:31:80:00:90:00:a6", NULL,
39          "D-Trust", SC_CARD_TYPE_MCRD_DTRUST, 0, NULL},
40        {NULL, NULL, NULL, 0, 0, NULL}
41};
42
43static struct sc_card_operations mcrd_ops;
44static struct sc_card_driver mcrd_drv = {
45        "MICARDO 2.1",
46        "mcrd",
47        &mcrd_ops,
48        NULL, 0, NULL
49};
50
51static const struct sc_card_operations *iso_ops = NULL;
52
53enum {
54        MCRD_SEL_MF = 0x00,
55        MCRD_SEL_DF = 0x01,
56        MCRD_SEL_EF = 0x02,
57        MCRD_SEL_PARENT = 0x03,
58        MCRD_SEL_AID = 0x04
59};
60
61#define MFID 0x3F00
62#define EF_KeyD 0x0013          /* File with extra key information. */
63#define EF_Rule 0x0030          /* Default ACL file. */
64
65#define MAX_CURPATH 10
66
67struct rule_record_s {
68        struct rule_record_s *next;
69        int recno;
70        size_t datalen;
71        u8 data[1];
72};
73
74struct keyd_record_s {
75        struct keyd_record_s *next;
76        int recno;
77        size_t datalen;
78        u8 data[1];
79};
80
81struct df_info_s {
82        struct df_info_s *next;
83        unsigned short path[MAX_CURPATH];
84        size_t pathlen;
85        struct rule_record_s *rule_file;        /* keeps records of EF_Rule. */
86        struct keyd_record_s *keyd_file;        /* keeps records of EF_KeyD. */
87};
88
89struct mcrd_priv_data {
90        unsigned short curpath[MAX_CURPATH];    /* The currently selected path. */
91        size_t curpathlen;      /* Length of this path or 0 if unknown. */
92        int is_ef;              /* True if the path points to an EF. */
93        struct df_info_s *df_infos;
94        sc_security_env_t sec_env;      /* current security environment */
95};
96
97#define DRVDATA(card)        ((struct mcrd_priv_data *) ((card)->drv_data))
98
99static int load_special_files(sc_card_t * card);
100static int select_part(sc_card_t * card, u8 kind, unsigned short int fid,
101                       sc_file_t ** file);
102
103/* Return the DF_info for the current path.  If does not yet exist,
104   create it.  Returns NULL on error. */
105static struct df_info_s *get_df_info(sc_card_t * card)
106{
107        sc_context_t *ctx = card->ctx;
108        struct mcrd_priv_data *priv = DRVDATA(card);
109        struct df_info_s *dfi;
110
111        assert(!priv->is_ef);
112
113        if (!priv->curpathlen) {
114                sc_debug(ctx, "no current path to find the df_info\n");
115                return NULL;
116        }
117
118        for (dfi = priv->df_infos; dfi; dfi = dfi->next) {
119                if (dfi->pathlen == priv->curpathlen
120                    && !memcmp(dfi->path, priv->curpath,
121                               dfi->pathlen * sizeof *dfi->path))
122                        return dfi;
123        }
124        /* Not found, create it. */
125        dfi = (struct df_info_s *)calloc(1, sizeof *dfi);
126        if (!dfi) {
127                sc_debug(ctx, "out of memory while allocating df_info\n");
128                return NULL;
129        }
130        dfi->pathlen = priv->curpathlen;
131        memcpy(dfi->path, priv->curpath, dfi->pathlen * sizeof *dfi->path);
132        dfi->next = priv->df_infos;
133        priv->df_infos = dfi;
134        return dfi;
135}
136
137static void clear_special_files(struct df_info_s *dfi)
138{
139        if (dfi) {
140                while (dfi->rule_file) {
141                        struct rule_record_s *tmp = dfi->rule_file->next;
142                        free(dfi->rule_file);
143                        dfi->rule_file = tmp;
144                }
145                while (dfi->keyd_file) {
146                        struct keyd_record_s *tmp = dfi->keyd_file->next;
147                        free(dfi->keyd_file);
148                        dfi->keyd_file = tmp;
149                }
150        }
151}
152
153/* Some functionality straight from the EstEID manual.
154 * Official notice: Refer to the Micardo 2.1 Public manual.
155 * Sad side: not available without a NDA.
156 */
157
158static int mcrd_delete_ref_to_authkey(sc_card_t * card)
159{
160        sc_apdu_t apdu;
161        int r;
162        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
163
164        assert(card != NULL);
165        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xA4);
166
167        sbuf[0] = 0x83;
168        sbuf[1] = 0x00;
169        apdu.data = sbuf;
170        apdu.lc = 2;
171        apdu.datalen = 2;
172        r = sc_transmit_apdu(card, &apdu);
173        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
174        SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
175}
176
177static int mcrd_delete_ref_to_signkey(sc_card_t * card)
178{
179        sc_apdu_t apdu;
180        int r;
181        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
182        assert(card != NULL);
183
184        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB6);
185
186        sbuf[0] = 0x83;
187        sbuf[1] = 0x00;
188        apdu.data = sbuf;
189        apdu.lc = 2;
190        apdu.datalen = 2;
191        r = sc_transmit_apdu(card, &apdu);
192        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
193        SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
194
195}
196
197static int mcrd_set_decipher_key_ref(sc_card_t * card, int key_reference)
198{
199        sc_apdu_t apdu;
200        sc_path_t path;
201        int r;
202        u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
203        u8 keyref_data[SC_ESTEID_KEYREF_FILE_RECLEN];
204        assert(card != NULL);
205
206        sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xB8);
207        /* track the active keypair  */
208        sc_format_path("0033", &path);
209        r = sc_select_file(card, &path, NULL);
210        SC_TEST_RET(card->ctx, r, "Can't select keyref info file 0x0033");
211        r = sc_read_record(card, 1, keyref_data,
212                           SC_ESTEID_KEYREF_FILE_RECLEN, SC_RECORD_BY_REC_NR);
213        SC_TEST_RET(card->ctx, r, "Can't read keyref info file!");
214
215        sc_debug(card->ctx,
216                 "authkey reference 0x%02x%02x\n",
217                 keyref_data[9], keyref_data[10]);
218
219        sc_debug(card->ctx,
220                 "signkey reference 0x%02x%02x\n",
221                 keyref_data[19], keyref_data[20]);
222
223        sbuf[0] = 0x83;
224        sbuf[1] = 0x03;
225        sbuf[2] = 0x80;
226        switch (key_reference) {
227        case 1:
228                sbuf[3] = keyref_data[9];
229                sbuf[4] = keyref_data[10];
230                break;
231        case 2:
232                sbuf[3] = keyref_data[19];
233                sbuf[4] = keyref_data[20];
234                break;
235        }
236        apdu.data = sbuf;
237        apdu.lc = 5;
238        apdu.datalen = 5;
239        r = sc_transmit_apdu(card, &apdu);
240        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
241        SC_FUNC_RETURN(card->ctx, 2, sc_check_sw(card, apdu.sw1, apdu.sw2));
242}
243
244static int is_esteid_atr(u8 *atr, size_t atr_len) {
245        const char *str = "EstEID ver 1.0";
246        unsigned int i;
247       
248        if (atr_len<14)
249                return 0;
250
251        for (i = 0; i<atr_len-14+1; i++) {
252                if (!memcmp(atr++, str, 14))
253                        return 1;
254        }
255        return 0;
256}
257
258static int mcrd_match_card(sc_card_t * card)
259{
260        int i;
261
262        if (is_esteid_atr(card->atr, card->atr_len)) {
263                sc_debug(card->ctx, "Found EstEID ver 1.0 card!");
264                card->type = SC_CARD_TYPE_MCRD_ESTEID;
265                return 1;
266        }
267
268        i = _sc_match_atr(card, mcrd_atrs, &card->type);
269        if (i < 0)
270                return 0;
271        return 1;
272}
273
274static int mcrd_init(sc_card_t * card)
275{
276        unsigned long flags;
277        struct mcrd_priv_data *priv;
278        sc_path_t tmppath;
279
280        priv = (struct mcrd_priv_data *)calloc(1, sizeof *priv);
281        if (!priv)
282                return SC_ERROR_OUT_OF_MEMORY;
283        card->name = "MICARDO 2.1";
284        card->drv_data = priv;
285        card->cla = 0x00;
286        card->caps |= SC_CARD_CAP_RNG;
287
288        flags = SC_ALGORITHM_RSA_RAW;
289        flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
290        flags |= SC_ALGORITHM_RSA_HASH_NONE;
291
292        _sc_card_add_rsa_alg(card, 512, flags, 0);
293        _sc_card_add_rsa_alg(card, 768, flags, 0);
294        _sc_card_add_rsa_alg(card, 1024, flags, 0);
295
296        priv->curpath[0] = MFID;
297        priv->curpathlen = 1;
298
299        sc_format_path ("3f00", &tmppath);
300        tmppath.type = SC_PATH_TYPE_PATH;
301        sc_select_file (card, &tmppath, NULL);
302                       
303       
304        /* The special file loading thing doesn't work for EstEID */
305        if (card->type != SC_CARD_TYPE_MCRD_ESTEID)
306                load_special_files(card);
307        return SC_SUCCESS;
308}
309
310static int mcrd_finish(sc_card_t * card)
311{
312        struct mcrd_priv_data *priv;
313
314        if (card == NULL)
315                return 0;
316        priv = DRVDATA(card);
317        while (priv->df_infos) {
318                struct df_info_s *tmp = priv->df_infos->next;
319                clear_special_files(priv->df_infos);
320                priv->df_infos = tmp;
321        }
322        free(priv);
323        return 0;
324}
325
326/* Load the rule and keyd file into our private data.
327   Return 0 on success */
328static int load_special_files(sc_card_t * card)
329{
330        sc_context_t *ctx = card->ctx;
331        struct mcrd_priv_data *priv = DRVDATA(card);
332        int r, recno;
333        struct df_info_s *dfi;
334        struct rule_record_s *rule;
335        struct keyd_record_s *keyd;
336
337        assert(!priv->is_ef);
338
339        /* First check whether we already cached it. */
340        dfi = get_df_info(card);
341        if (dfi && dfi->rule_file)
342                return 0;       /* yes. */
343        clear_special_files(dfi);
344
345        /* Read rule file. Note that we bypass our cache here. */
346        r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL);
347        SC_TEST_RET(ctx, r, "selecting EF_Rule failed");
348
349        for (recno = 1;; recno++) {
350                u8 recbuf[256];
351                r = sc_read_record(card, recno, recbuf, sizeof(recbuf),
352                                   SC_RECORD_BY_REC_NR);
353
354                if (r == SC_ERROR_RECORD_NOT_FOUND)
355                        break;
356                else if (r < 0) {
357                        SC_FUNC_RETURN(ctx, 2, r);
358                } else {
359                        rule = (struct rule_record_s *)malloc(sizeof *rule + r);
360                        if (!rule)
361                                SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
362                        rule->recno = recno;
363                        rule->datalen = r;
364                        memcpy(rule->data, recbuf, r);
365                        rule->next = dfi->rule_file;
366                        dfi->rule_file = rule;
367                }
368        }
369
370        sc_debug(ctx, "new EF_Rule file loaded (%d records)\n", recno - 1);
371
372        /* Read the KeyD file. Note that we bypass our cache here. */
373        r = select_part(card, MCRD_SEL_EF, EF_KeyD, NULL);
374        if (r == SC_ERROR_FILE_NOT_FOUND) {
375                sc_debug(ctx, "no EF_KeyD file available\n");
376                return 0;       /* That is okay. */
377        }
378        SC_TEST_RET(ctx, r, "selecting EF_KeyD failed");
379
380        for (recno = 1;; recno++) {
381                u8 recbuf[256];
382                r = sc_read_record(card, recno, recbuf, sizeof(recbuf),
383                                   SC_RECORD_BY_REC_NR);
384
385                if (r == SC_ERROR_RECORD_NOT_FOUND)
386                        break;
387                else if (r < 0) {
388                        SC_FUNC_RETURN(ctx, 2, r);
389                } else {
390                        keyd = (struct keyd_record_s *)malloc(sizeof *keyd + r);
391                        if (!keyd)
392                                SC_FUNC_RETURN(ctx, 0, SC_ERROR_OUT_OF_MEMORY);
393                        keyd->recno = recno;
394                        keyd->datalen = r;
395                        memcpy(keyd->data, recbuf, r);
396                        keyd->next = dfi->keyd_file;
397                        dfi->keyd_file = keyd;
398                }
399        }
400
401        sc_debug(ctx, "new EF_KeyD file loaded (%d records)\n", recno - 1);
402        /* FIXME: Do we need to restore the current DF?  I guess it is
403           not required, but we could try to do so by selecting 3fff?  */
404        return 0;
405}
406
407/* Return the SE number from the keyD for the FID.  If ref_data is not
408   NULL the reference data is returned; this shoudl be an array of at
409   least 2 bytes.  Returns -1 on error.  */
410static int get_se_num_from_keyd(sc_card_t * card, unsigned short fid,
411                                u8 * ref_data)
412{
413        sc_context_t *ctx = card->ctx;
414        struct df_info_s *dfi;
415        struct keyd_record_s *keyd;
416        size_t len, taglen;
417        const u8 *p, *tag;
418        char dbgbuf[2048];
419        u8 fidbuf[2];
420
421        fidbuf[0] = fid >> 8;
422        fidbuf[1] = fid;
423
424        dfi = get_df_info(card);
425        if (!dfi || !dfi->keyd_file) {
426                sc_debug(ctx, "EF_keyD not loaded\n");
427                return -1;
428        }
429
430        for (keyd = dfi->keyd_file; keyd; keyd = keyd->next) {
431                p = keyd->data;
432                len = keyd->datalen;
433
434                sc_hex_dump(ctx, p, len, dbgbuf, sizeof dbgbuf);
435                sc_debug(ctx, "keyd no %d:\n%s", keyd->recno, dbgbuf);
436
437                tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
438                if (!tag || taglen != 4 ||
439                    !(tag[2] == fidbuf[0] && tag[3] == fidbuf[1]))
440                        continue;
441                /* Found a matching record. */
442                if (ref_data) {
443                        ref_data[0] = tag[0];
444                        ref_data[1] = tag[1];
445                }
446                /* Look for the SE-DO */
447                tag = sc_asn1_find_tag(ctx, p, len, 0x7B, &taglen);
448                if (!tag || !taglen)
449                        continue;
450                p = tag;
451                len = taglen;
452                /* And now look for the referenced SE. */
453                tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
454                if (!tag || taglen != 1)
455                        continue;
456                return *tag;    /* found. */
457        }
458        sc_debug(ctx, "EF_keyD for %04hx not found\n", fid);
459        return -1;
460}
461
462/* Process an ARR (7816-9/8.5.4) and setup the ACL. */
463static void process_arr(sc_card_t * card, sc_file_t * file,
464                        const u8 * buf, size_t buflen)
465{
466        sc_context_t *ctx = card->ctx;
467        struct df_info_s *dfi;
468        struct rule_record_s *rule;
469        size_t left, taglen;
470        unsigned int cla, tag;
471        const u8 *p;
472        int skip;
473        char dbgbuf[2048];
474
475        /* Currently we support only the short for. */
476        if (buflen != 1) {
477                sc_debug(ctx, "can't handle long ARRs\n");
478                return;
479        }
480
481        dfi = get_df_info(card);
482        for (rule = dfi ? dfi->rule_file : NULL; rule && rule->recno != *buf;
483             rule = rule->next) ;
484        if (!rule) {
485                sc_debug(ctx, "referenced EF_rule record %d not found\n", *buf);
486                return;
487        }
488
489        if (ctx->debug) {
490                sc_hex_dump(ctx, rule->data, rule->datalen, dbgbuf,
491                            sizeof dbgbuf);
492                sc_debug(ctx, "rule for record %d:\n%s", *buf, dbgbuf);
493        }
494
495        p = rule->data;
496        left = rule->datalen;
497        skip = 1;               /* Skip over initial unknown SC DOs. */
498        for (;;) {
499                buf = p;
500                if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) !=
501                    SC_SUCCESS)
502                        break;
503                left -= (p - buf);
504                tag |= cla;
505
506                if (tag == 0x80 && taglen != 1) {
507                        skip = 1;
508                } else if (tag == 0x80) {       /* AM byte. */
509                        sc_debug(ctx, "  AM_DO: %02x\n", *p);
510                        skip = 0;
511                } else if (tag >= 0x81 && tag <= 0x8f) {        /* Cmd description */
512                        sc_hex_dump(ctx, p, taglen, dbgbuf, sizeof dbgbuf);
513                        sc_debug(ctx, "  AM_DO: cmd[%s%s%s%s] %s",
514                                 (tag & 8) ? "C" : "",
515                                 (tag & 4) ? "I" : "",
516                                 (tag & 2) ? "1" : "",
517                                 (tag & 1) ? "2" : "", dbgbuf);
518                        skip = 0;
519                } else if (tag == 0x9C) {       /* Proprietary state machine descrip. */
520                        skip = 1;
521                } else if (!skip) {
522                        sc_hex_dump(ctx, p, taglen, dbgbuf, sizeof dbgbuf);
523                        switch (tag) {
524                        case 0x90:      /* Always */
525                                sc_debug(ctx, "     SC: always\n");
526                                break;
527                        case 0x97:      /* Never */
528                                sc_debug(ctx, "     SC: never\n");
529                                break;
530                        case 0xA4:      /* Authentication, value is a CRT. */
531                                sc_debug(ctx, "     SC: auth %s", dbgbuf);
532                                break;
533
534                        case 0xB4:
535                        case 0xB6:
536                        case 0xB8:      /* Cmd or resp with SM, value is a CRT. */
537                                sc_debug(ctx, "     SC: cmd/resp %s", dbgbuf);
538                                break;
539
540                        case 0x9E:      /* Security Condition byte. */
541                                sc_debug(ctx, "     SC: condition %s", dbgbuf);
542                                break;
543
544                        case 0xA0:      /* OR template. */
545                                sc_debug(ctx, "     SC: OR\n");
546                                break;
547                        case 0xAF:      /* AND template. */
548                                sc_debug(ctx, "     SC: AND\n");
549                                break;
550                        }
551                }
552                left -= taglen;
553                p += taglen;
554        }
555
556}
557
558static void process_fcp(sc_card_t * card, sc_file_t * file,
559                        const u8 * buf, size_t buflen)
560{
561        sc_context_t *ctx = card->ctx;
562        size_t taglen, len = buflen;
563        const u8 *tag = NULL, *p = buf;
564        int bad_fde = 0;
565
566        if (ctx->debug >= 3)
567                sc_debug(ctx, "processing FCI bytes\n");
568        /* File identifier. */
569        tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
570        if (tag != NULL && taglen == 2) {
571                file->id = (tag[0] << 8) | tag[1];
572                if (ctx->debug >= 3)
573                        sc_debug(ctx, "  file identifier: 0x%02X%02X\n", tag[0],
574                                 tag[1]);
575        }
576        /* Number of data bytes in the file including structural information. */
577        tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
578        if (!tag) {
579                /* My card does not encode the filelength in 0x81 but
580                   in 0x85 which is the file descriptor extension in TCOS.
581                   Assume that this is the case when the regular file
582                   size tag is not encoded. */
583                tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
584                bad_fde = !!tag;
585        }
586        if (tag != NULL && taglen >= 2) {
587                int bytes = (tag[0] << 8) + tag[1];
588                if (ctx->debug >= 3)
589                        sc_debug(ctx, "  bytes in file: %d\n", bytes);
590                file->size = bytes;
591        }
592        if (tag == NULL) {
593                tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
594                if (tag != NULL && taglen >= 2) {
595                        int bytes = (tag[0] << 8) + tag[1];
596                        if (ctx->debug >= 3)
597                                sc_debug(ctx, "  bytes in file: %d\n", bytes);
598                        file->size = bytes;
599                }
600        }
601
602        /* File descriptor byte(s). */
603        tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
604        if (tag != NULL) {
605                /* Fixme, this might actual be up to 6 bytes. */
606                if (taglen > 0) {
607                        unsigned char byte = tag[0];
608                        const char *type;
609
610                        file->shareable = byte & 0x40 ? 1 : 0;
611                        if (ctx->debug >= 3)
612                                sc_debug(ctx, "  shareable: %s\n",
613                                         (byte & 0x40) ? "yes" : "no");
614                        file->ef_structure = byte & 0x07;
615                        switch ((byte >> 3) & 7) {
616                        case 0:
617                                type = "working EF";
618                                file->type = SC_FILE_TYPE_WORKING_EF;
619                                break;
620                        case 1:
621                                type = "internal EF";
622                                file->type = SC_FILE_TYPE_INTERNAL_EF;
623                                break;
624                        case 7:
625                                type = "DF";
626                                file->type = SC_FILE_TYPE_DF;
627                                break;
628                        default:
629                                type = "unknown";
630                                break;
631                        }
632                        if (ctx->debug >= 3) {
633                                sc_debug(ctx, "  type: %s\n", type);
634                                sc_debug(ctx, "  EF structure: %d\n",
635                                         byte & 0x07);
636                        }
637                }
638        }
639
640        /* DF name. */
641        tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
642        if (tag != NULL && taglen > 0 && taglen <= 16) {
643                char name[17];
644                size_t i;
645
646                memcpy(file->name, tag, taglen);
647                file->namelen = taglen;
648
649                for (i = 0; i < taglen; i++) {
650                        if (isalnum(tag[i]) || ispunct(tag[i])
651                            || isspace(tag[i]))
652                                name[i] = tag[i];
653                        else
654                                name[i] = '?';
655                }
656                name[taglen] = 0;
657                if (ctx->debug >= 3)
658                        sc_debug(ctx, "  file name: %s\n", name);
659        }
660
661        /* Proprietary information. */
662        tag = bad_fde ? NULL : sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
663        if (tag != NULL && taglen) {
664                sc_file_set_prop_attr(file, tag, taglen);
665        } else
666                file->prop_attr_len = 0;
667
668        /* Proprietary information, constructed. */
669        tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen);
670        if (tag != NULL && taglen) {
671                sc_file_set_prop_attr(file, tag, taglen);
672        }
673
674        /* Security attributes, proprietary format. */
675        tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen);
676        if (tag != NULL && taglen) {
677                sc_file_set_sec_attr(file, tag, taglen);
678        }
679
680        /* Security attributes, reference to expanded format. */
681        tag = sc_asn1_find_tag(ctx, p, len, 0x8B, &taglen);
682        if (tag && taglen) {
683                process_arr(card, file, tag, taglen);
684        } else if ((tag = sc_asn1_find_tag(ctx, p, len, 0xA1, &taglen))
685                   && taglen) {
686                /* Not found, but there is a Security Attribute
687                   Template for interface mode. */
688                tag = sc_asn1_find_tag(ctx, tag, taglen, 0x8B, &taglen);
689                if (tag && taglen)
690                        process_arr(card, file, tag, taglen);
691        }
692
693        file->magic = SC_FILE_MAGIC;
694}
695
696/* Send a select command and parse the response. */
697static int
698do_select(sc_card_t * card, u8 kind,
699          const u8 * buf, size_t buflen, sc_file_t ** file)
700{
701        sc_apdu_t apdu;
702        u8 resbuf[255];
703        int r;
704
705        sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, kind, 0x00);
706        apdu.data = buf;
707        apdu.datalen = buflen;
708        apdu.lc = apdu.datalen;
709        apdu.resp = resbuf;
710        apdu.resplen = sizeof(resbuf);
711        apdu.le = sizeof(resbuf);
712
713        r = sc_transmit_apdu(card, &apdu);
714        SC_TEST_RET(card->ctx, r, "APDU transmit failed");
715        if (!file) {
716                if (apdu.sw1 == 0x61)
717                        SC_FUNC_RETURN(card->ctx, 2, 0);
718                r = sc_check_sw(card, apdu.sw1, apdu.sw2);
719                if (!r && kind == MCRD_SEL_AID)
720                        card->cache.current_path.len = 0;
721                SC_FUNC_RETURN(card->ctx, 2, r);
722        }
723        r = sc_check_sw(card, apdu.sw1, apdu.sw2);
724        if (r)
725                SC_FUNC_RETURN(card->ctx, 2, r);
726
727        switch (apdu.resp[0]) {
728        case 0x6F:
729                *file = sc_file_new();
730                if (!*file)
731                        SC_FUNC_RETURN(card->ctx, 0, SC_ERROR_OUT_OF_MEMORY);
732                if (apdu.resp[1] <= apdu.resplen)
733                        process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
734                break;
735        case 0x00:              /* proprietary coding */
736                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
737        default:
738                SC_FUNC_RETURN(card->ctx, 2, SC_ERROR_UNKNOWN_DATA_RECEIVED);
739        }
740        return 0;
741}
742
743/* Wrapper around do_select to be used when multiple selects are
744   required. */
745static int
746select_part(sc_card_t * card, u8 kind, unsigned short int fid,
747            sc_file_t ** file)
748{
749        u8 fbuf[2];
750        int r;
751
752        if (card->ctx->debug >= 3)
753                sc_debug(card->ctx, "select_part (0x%04X, kind=%u)\n", fid,
754                         kind);
755
756        if (fid == MFID)
757                kind = MCRD_SEL_MF;     /* force this kind. */
758
759        fbuf[0] = fid >> 8;
760        fbuf[1] = fid & 0xff;
761        sc_ctx_suppress_errors_on(card->ctx);
762        r = do_select(card, kind, fbuf, 2, file);
763        sc_ctx_suppress_errors_off(card->ctx);
764
765        return r;
766}
767
768/* Select a file by iterating over the FID in the PATHPTR array while
769   updating the curpath kept in the private data cache.  With DF_ONLY
770   passed as true only DF are selected, otherwise the function tries
771   to figure out whether the last path item is a DF or EF. */
772static int
773select_down(sc_card_t * card,
774            unsigned short *pathptr, size_t pathlen,
775            int df_only, sc_file_t ** file)
776{
777        struct mcrd_priv_data *priv = DRVDATA(card);
778        int r;
779        int found_ef = 0;
780
781        if (!pathlen)
782                return SC_ERROR_INVALID_ARGUMENTS;
783
784        for (; pathlen; pathlen--, pathptr++) {
785                if (priv->curpathlen == MAX_CURPATH)
786                        SC_TEST_RET(card->ctx, SC_ERROR_INTERNAL,
787                                    "path too long for cache");
788                r = -1;         /* force DF select. */
789                if (pathlen == 1 && !df_only) {
790                        /* first try to select an EF and retry an DF
791                           on error. */
792                        r = select_part(card, MCRD_SEL_EF, *pathptr, file);
793                        if (!r)
794                                found_ef = 1;
795                }
796                if (r)
797                        r = select_part(card, MCRD_SEL_DF, *pathptr,
798                                        pathlen == 1 ? file : NULL);
799                SC_TEST_RET(card->ctx, r, "unable to select DF");
800                priv->curpath[priv->curpathlen] = *pathptr;
801                priv->curpathlen++;
802        }
803        priv->is_ef = found_ef;
804        if (!found_ef)
805                load_special_files(card);
806
807        return 0;
808}
809
810/* Handle the selection case when a PATH is requested.  Our card does
811   not support this addressing so we have to emulate it.  To keep the
812   security status we should not unnecessary change the directory;
813   this is accomplished be keeping track of the currently selected
814   file.  Note that PATH is an array of PATHLEN file ids and not the
815   usual sc_path structure. */
816
817static int
818select_file_by_path(sc_card_t * card, unsigned short *pathptr,
819                    size_t pathlen, sc_file_t ** file)
820{
821        struct mcrd_priv_data *priv = DRVDATA(card);
822        int r;
823        size_t i;
824
825        assert(!priv->curpathlen || priv->curpath[0] == MFID);
826
827        if (pathlen && *pathptr == 0x3FFF) {
828                pathlen--;
829                pathptr++;
830        }
831
832        if (!pathlen || pathlen >= MAX_CURPATH)
833                r = SC_ERROR_INVALID_ARGUMENTS;
834        else if (pathlen == 1 && pathptr[0] == MFID) {
835                /* MF requested: clear the cache and select it. */
836                priv->curpathlen = 0;
837                r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
838                SC_TEST_RET(card->ctx, r, "unable to select MF");
839                priv->curpath[0] = pathptr[0];
840                priv->curpathlen = 1;
841                priv->is_ef = 0;
842        } else if (pathlen > 1 && pathptr[0] == MFID) {
843                /* Absolute addressing, check cache to avoid
844                   unnecessary selects. */
845                for (i = 0; (i < pathlen && i < priv->curpathlen
846                             && pathptr[i] == priv->curpath[i]); i++) ;
847                if (!priv->curpathlen) {
848                        /* Need to do all selects starting at the root. */
849                        priv->curpathlen = 0;
850                        priv->is_ef = 0;
851                        r = select_down(card, pathptr, pathlen, 0, file);
852                } else if (i == pathlen && i < priv->curpathlen) {
853                        /* Go upwards; we do it the easy way and start
854                           at the root.  However we know that the target is a DF. */
855                        priv->curpathlen = 0;
856                        priv->is_ef = 0;
857                        r = select_down(card, pathptr, pathlen, 1, file);
858                } else if (i == pathlen && i == priv->curpathlen) {
859                        /* Already selected. */
860                        if (!file)
861                                r = 0;  /* The caller did not request the fci. */
862                        else {
863                                /* This EF or DF was already selected, but
864                                   we need to get the FCI, so we have
865                                   to select again. */
866                                assert(priv->curpathlen > 1);
867                                priv->curpathlen--;
868                                priv->is_ef = 0;
869                                r = select_down(card, pathptr + pathlen - 1, 1,
870                                                0, file);
871                        }
872                } else {
873                        /* We have to append something.  For now we
874                           simply start at the root. (fixme) */
875                        priv->curpathlen = 0;
876                        priv->is_ef = 0;
877                        r = select_down(card, pathptr, pathlen, 0, file);
878                }
879        } else {
880                /* Relative addressing. */
881                if (!priv->curpathlen) {
882                        /* Relative addressing without a current path. So we
883                           select the MF first. */
884                        r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
885                        SC_TEST_RET(card->ctx, r, "unable to select MF");
886                        priv->curpath[0] = pathptr[0];
887                        priv->curpathlen = 1;
888                        priv->is_ef = 0;
889                }
890                if (priv->is_ef) {
891                        assert(priv->curpathlen > 1);
892                        priv->curpathlen--;
893                        priv->is_ef = 0;
894                }
895                r = select_down(card, pathptr, pathlen, 0, file);
896        }
897        return r;
898}
899
900static int
901select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
902                   size_t pathlen, sc_file_t ** file)
903{
904        struct mcrd_priv_data *priv = DRVDATA(card);
905        int r;
906
907        assert(!priv->curpathlen || priv->curpath[0] == MFID);
908
909        if (pathlen > 1)
910                return SC_ERROR_INVALID_ARGUMENTS;
911
912        if (pathlen && *pathptr == 0x3FFF)
913                return 0;
914
915        if (!pathlen) {
916                /* re-select the current one if needed. */
917                if (!file)
918                        r = 0;  /* The caller did not request the fci. */
919                else if (!priv->curpathlen) {
920                        /* There is no current file. */
921                        r = SC_ERROR_INTERNAL;
922                } else {
923                        assert(priv->curpathlen > 1);
924                        priv->curpathlen--;
925                        priv->is_ef = 0;
926                        r = select_down(card, pathptr, 1, 0, file);
927                }
928        } else if (pathptr[0] == MFID) {
929                /* MF requested: clear the cache and select it. */
930                priv->curpathlen = 0;
931                r = select_part(card, MCRD_SEL_MF, MFID, file);
932                SC_TEST_RET(card->ctx, r, "unable to select MF");
933                priv->curpath[0] = MFID;
934                priv->curpathlen = 1;
935                priv->is_ef = 0;
936        } else {
937                /* Relative addressing. */
938                if (!priv->curpathlen) {
939                        /* Relative addressing without a current path. So we
940                           select the MF first. */
941                        r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
942                        SC_TEST_RET(card->ctx, r, "unable to select MF");
943                        priv->curpath[0] = pathptr[0];
944                        priv->curpathlen = 1;
945                        priv->is_ef = 0;
946                }
947                if (priv->is_ef) {
948                        assert(priv->curpathlen > 1);
949                        priv->curpathlen--;
950                        priv->is_ef = 0;
951                }
952                r = select_down(card, pathptr, 1, 0, file);
953        }
954
955        return r;
956}
957
958/* This drivers select command handler. */
959static int
960mcrd_select_file(sc_card_t * card, const sc_path_t * path, sc_file_t ** file)
961{
962        struct mcrd_priv_data *priv = DRVDATA(card);
963        int r = 0;
964