Coverage Report

Created: 2026-01-10 06:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-mcrd.c
Line
Count
Source
1
/*
2
 * card-mcrd.c: Support for MICARDO cards
3
 *
4
 * Copyright (C) 2004  Martin Paljak <martin@martinpaljak.net>
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 */
24
25
#ifdef HAVE_CONFIG_H
26
#include "config.h"
27
#endif
28
29
#include <stdlib.h>
30
#include <string.h>
31
#include <ctype.h>
32
33
#include "internal.h"
34
#include "asn1.h"
35
#include "cardctl.h"
36
#include "gp.h"
37
38
static const struct sc_atr_table mcrd_atrs[] = {
39
  {"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,
40
    "Micardo 2.1/German BMI/D-Trust", SC_CARD_TYPE_MCRD_GENERIC, 0, NULL},
41
  {"3b:6f:00:ff:00:68:d2:76:00:00:28:ff:05:1e:31:80:00:90:00", NULL,
42
    "D-Trust", SC_CARD_TYPE_MCRD_GENERIC, 0, NULL},
43
  {"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,
44
    "D-Trust", SC_CARD_TYPE_MCRD_GENERIC, 0, NULL},
45
  {NULL, NULL, NULL, 0, 0, NULL}
46
};
47
48
49
static struct sc_card_operations mcrd_ops;
50
static struct sc_card_driver mcrd_drv = {
51
  "MICARDO 2.1",
52
  "mcrd",
53
  &mcrd_ops,
54
  NULL, 0, NULL
55
};
56
57
static const struct sc_card_operations *iso_ops = NULL;
58
59
enum {
60
  MCRD_SEL_MF = 0x00,
61
  MCRD_SEL_DF = 0x01,
62
  MCRD_SEL_EF = 0x02,
63
  MCRD_SEL_PARENT = 0x03,
64
  MCRD_SEL_AID = 0x04
65
};
66
67
7.06k
#define MFID 0x3F00
68
41
#define EF_KeyD 0x0013    /* File with extra key information. */
69
417
#define EF_Rule 0x0030    /* Default ACL file. */
70
71
3.56k
#define MAX_CURPATH 10
72
73
struct rule_record_s {
74
  struct rule_record_s *next;
75
  unsigned int recno;
76
  size_t datalen;
77
  u8 data[1];
78
};
79
80
struct keyd_record_s {
81
  struct keyd_record_s *next;
82
  unsigned int recno;
83
  size_t datalen;
84
  u8 data[1];
85
};
86
87
struct df_info_s {
88
  struct df_info_s *next;
89
  unsigned short path[MAX_CURPATH];
90
  size_t pathlen;
91
  struct rule_record_s *rule_file;  /* keeps records of EF_Rule. */
92
  struct keyd_record_s *keyd_file;  /* keeps records of EF_KeyD. */
93
};
94
95
struct mcrd_priv_data {
96
  unsigned short curpath[MAX_CURPATH];  /* The currently selected path. */
97
  int is_ef;    /* True if the path points to an EF. */
98
  size_t curpathlen;  /* Length of this path or 0 if unknown. */
99
  struct df_info_s *df_infos;
100
  sc_security_env_t sec_env;  /* current security environment */
101
};
102
103
7.24k
#define DRVDATA(card) ((struct mcrd_priv_data *) ((card)->drv_data))
104
105
static int load_special_files(sc_card_t * card);
106
static int select_part(sc_card_t * card, u8 kind, unsigned short int fid, sc_file_t ** file);
107
108
/* Return the DF_info for the current path.  If does not yet exist,
109
   create it.  Returns NULL on error. */
110
static struct df_info_s *get_df_info(sc_card_t * card)
111
654
{
112
654
  sc_context_t *ctx = card->ctx;
113
654
  struct mcrd_priv_data *priv = DRVDATA(card);
114
654
  struct df_info_s *dfi;
115
116
654
  if(!(!priv->is_ef))
117
1
    return NULL;
118
119
653
  if (!priv->curpathlen) {
120
104
    sc_log(ctx, "no current path to find the df_info\n");
121
104
    return NULL;
122
104
  }
123
124
602
  for (dfi = priv->df_infos; dfi; dfi = dfi->next) {
125
181
    if (dfi->pathlen == priv->curpathlen
126
138
      && !memcmp(dfi->path, priv->curpath,
127
138
          dfi->pathlen * sizeof *dfi->path))
128
128
      return dfi;
129
181
  }
130
  /* Not found, create it. */
131
421
  dfi = calloc(1, sizeof *dfi);
132
421
  if (!dfi) {
133
0
    sc_log(ctx, "out of memory while allocating df_info\n");
134
0
    return NULL;
135
0
  }
136
421
  dfi->pathlen = priv->curpathlen;
137
421
  memcpy(dfi->path, priv->curpath, dfi->pathlen * sizeof *dfi->path);
138
421
  dfi->next = priv->df_infos;
139
421
  priv->df_infos = dfi;
140
421
  return dfi;
141
421
}
142
143
static void clear_special_files(struct df_info_s *dfi)
144
941
{
145
941
  if (dfi) {
146
2.07k
    while (dfi->rule_file) {
147
1.23k
      struct rule_record_s *tmp = dfi->rule_file->next;
148
1.23k
      free(dfi->rule_file);
149
1.23k
      dfi->rule_file = tmp;
150
1.23k
    }
151
1.10k
    while (dfi->keyd_file) {
152
271
      struct keyd_record_s *tmp = dfi->keyd_file->next;
153
271
      free(dfi->keyd_file);
154
271
      dfi->keyd_file = tmp;
155
271
    }
156
838
  }
157
941
}
158
159
/*
160
 * Official notice: Refer to the Micardo 2.1 Public manual.
161
 * Sad side: not available without a NDA.
162
 */
163
164
static int mcrd_delete_ref_to_authkey(sc_card_t * card)
165
0
{
166
0
  sc_apdu_t apdu;
167
0
  int r;
168
0
  u8 sbuf[2] = { 0x83, 0x00 };
169
0
  if(card == NULL)
170
0
    return SC_ERROR_INTERNAL;
171
0
  sc_format_apdu_ex(&apdu, 0x00, 0x22, 0x41, 0xA4, sbuf, 2, NULL, 0);
172
0
  r = sc_transmit_apdu(card, &apdu);
173
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
174
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
175
0
}
176
177
static int mcrd_delete_ref_to_signkey(sc_card_t * card)
178
0
{
179
0
  sc_apdu_t apdu;
180
0
  int r;
181
0
  u8 sbuf[2] = { 0x83, 0x00 };
182
0
  if(card == NULL)
183
0
    return SC_ERROR_INTERNAL;
184
0
  sc_format_apdu_ex(&apdu, 0x00, 0x22, 0x41, 0xB6, sbuf, 2, NULL, 0);
185
0
  r = sc_transmit_apdu(card, &apdu);
186
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
187
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
188
0
}
189
190
static int mcrd_match_card(sc_card_t * card)
191
16.7k
{
192
16.7k
  int i = 0;
193
194
16.7k
  i = _sc_match_atr(card, mcrd_atrs, &card->type);
195
16.7k
  if (i >= 0) {
196
479
    card->name = mcrd_atrs[i].name;
197
479
    return 1;
198
479
  }
199
200
16.2k
  return 0;
201
16.7k
}
202
203
static int mcrd_init(sc_card_t * card)
204
479
{
205
479
  unsigned long flags;
206
479
  struct mcrd_priv_data *priv = calloc(1, sizeof *priv);
207
479
  if (!priv)
208
0
    return SC_ERROR_OUT_OF_MEMORY;
209
479
  priv->curpath[0] = MFID;
210
479
  priv->curpathlen = 1;
211
479
  card->drv_data = priv;
212
479
  card->cla = 0x00;
213
479
  card->caps = SC_CARD_CAP_RNG;
214
215
479
  flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
216
479
  _sc_card_add_rsa_alg(card, 512, flags, 0);
217
479
  _sc_card_add_rsa_alg(card, 768, flags, 0);
218
479
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
219
220
479
  if (SC_SUCCESS != sc_select_file (card, sc_get_mf_path(), NULL))
221
103
    sc_log(card->ctx, "Warning: select MF failed");
222
223
479
  load_special_files(card);
224
225
479
  return SC_SUCCESS;
226
479
}
227
228
static int mcrd_finish(sc_card_t * card)
229
479
{
230
479
  struct mcrd_priv_data *priv;
231
232
479
  if (card == NULL)
233
0
    return 0;
234
479
  priv = DRVDATA(card);
235
900
  while (priv->df_infos) {
236
421
    struct df_info_s *tmp = priv->df_infos->next;
237
421
    clear_special_files(priv->df_infos);
238
421
    free(priv->df_infos);
239
421
    priv->df_infos = tmp;
240
421
  }
241
479
  free(priv);
242
479
  return 0;
243
479
}
244
245
/* Load the rule and keyd file into our private data.
246
   Return 0 on success */
247
static int load_special_files(sc_card_t * card)
248
520
{
249
520
  sc_context_t *ctx = card->ctx;
250
520
  int r;
251
520
  unsigned int recno;
252
520
  struct df_info_s *dfi;
253
520
  struct rule_record_s *rule;
254
520
  struct keyd_record_s *keyd;
255
256
  /* First check whether we already cached it. */
257
520
  dfi = get_df_info(card);
258
520
  if (dfi && dfi->rule_file)
259
0
    return 0; /* yes. */
260
520
  clear_special_files(dfi);
261
520
  if (!dfi)
262
520
    LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
263
264
  /* Read rule file. Note that we bypass our cache here. */
265
417
  r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL);
266
417
  LOG_TEST_RET(ctx, r, "selecting EF_Rule failed");
267
268
1.46k
  for (recno = 1;; recno++) {
269
1.46k
    u8 recbuf[256];
270
1.46k
    r = sc_read_record(card, recno, 0, recbuf, sizeof(recbuf),
271
1.46k
          SC_RECORD_BY_REC_NR);
272
273
1.46k
    if (r == SC_ERROR_RECORD_NOT_FOUND)
274
41
      break;
275
1.42k
    if (r < 0) {
276
190
      SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
277
1.23k
    } else {
278
1.23k
      rule = malloc(sizeof *rule + (size_t)r);
279
1.23k
      if (!rule)
280
1.23k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
281
1.23k
      rule->recno = recno;
282
1.23k
      rule->datalen = (size_t)r;
283
1.23k
      memcpy(rule->data, recbuf, r);
284
1.23k
      rule->next = dfi->rule_file;
285
1.23k
      dfi->rule_file = rule;
286
1.23k
    }
287
1.42k
  }
288
289
41
  sc_log(ctx, "new EF_Rule file loaded (%d records)\n", recno - 1);
290
291
  /* Read the KeyD file. Note that we bypass our cache here. */
292
41
  r = select_part(card, MCRD_SEL_EF, EF_KeyD, NULL);
293
41
  if (r == SC_ERROR_FILE_NOT_FOUND) {
294
1
    sc_log(ctx, "no EF_KeyD file available\n");
295
1
    return 0; /* That is okay. */
296
1
  }
297
40
  LOG_TEST_RET(ctx, r, "selecting EF_KeyD failed");
298
299
300
  for (recno = 1;; recno++) {
300
300
    u8 recbuf[256];
301
300
    r = sc_read_record(card, recno, 0, recbuf, sizeof(recbuf),
302
300
          SC_RECORD_BY_REC_NR);
303
304
300
    if (r == SC_ERROR_RECORD_NOT_FOUND)
305
6
      break;
306
294
    if (r < 0) {
307
23
      SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
308
271
    } else {
309
271
      keyd = malloc(sizeof *keyd + (size_t)r);
310
271
      if (!keyd)
311
271
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
312
271
      keyd->recno = recno;
313
271
      keyd->datalen = (size_t) r;
314
271
      memcpy(keyd->data, recbuf, r);
315
271
      keyd->next = dfi->keyd_file;
316
271
      dfi->keyd_file = keyd;
317
271
    }
318
294
  }
319
320
6
  sc_log(ctx, "new EF_KeyD file loaded (%d records)\n", recno - 1);
321
  /* FIXME: Do we need to restore the current DF?  I guess it is
322
     not required, but we could try to do so by selecting 3fff?  */
323
6
  return 0;
324
29
}
325
326
/* Process an ARR (7816-9/8.5.4) and setup the ACL. */
327
static void process_arr(sc_card_t * card, const u8 * buf, size_t buflen)
328
138
{
329
138
  sc_context_t *ctx = card->ctx;
330
138
  struct df_info_s *dfi;
331
138
  struct rule_record_s *rule;
332
138
  size_t left, taglen;
333
138
  unsigned int cla, tag;
334
138
  const u8 *p;
335
138
  int skip;
336
138
  char dbgbuf[2048];
337
338
  /* Currently we support only the short for. */
339
138
  if (buflen != 1) {
340
4
    sc_log(ctx, "can't handle long ARRs\n");
341
4
    return;
342
4
  }
343
344
134
  dfi = get_df_info(card);
345
218
  for (rule = dfi ? dfi->rule_file : NULL; rule && rule->recno != *buf;
346
134
    rule = rule->next) ;
347
134
  if (!rule) {
348
19
    sc_log(ctx, "referenced EF_rule record %d not found\n", *buf);
349
19
    return;
350
19
  }
351
352
115
  sc_hex_dump(rule->data, rule->datalen, dbgbuf, sizeof dbgbuf);
353
115
  sc_log(ctx,
354
115
    "rule for record %d:\n%s", *buf, dbgbuf);
355
356
115
  p = rule->data;
357
115
  left = rule->datalen;
358
115
  skip = 1;   /* Skip over initial unknown SC DOs. */
359
1.28k
  for (;;) {
360
1.28k
    buf = p;
361
1.28k
    if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS
362
1.21k
        || p == NULL)
363
115
      break;
364
1.17k
    left -= (size_t)(p - buf);
365
1.17k
    tag |= cla;
366
367
1.17k
    if (tag == 0x80 && taglen != 1) {
368
88
      skip = 1;
369
1.08k
    } else if (tag == 0x80) { /* AM byte. */
370
11
      sc_log(ctx, "  AM_DO: %02x\n", *p);
371
11
      skip = 0;
372
1.07k
    } else if (tag >= 0x81 && tag <= 0x8f) { /* Cmd description */
373
216
      sc_hex_dump(p, taglen, dbgbuf, sizeof dbgbuf);
374
216
      sc_log(ctx, "  AM_DO: cmd[%s%s%s%s] %s",
375
216
         (tag & 8) ? "C" : "",
376
216
         (tag & 4) ? "I" : "",
377
216
         (tag & 2) ? "1" : "",
378
216
         (tag & 1) ? "2" : "", dbgbuf);
379
216
      skip = 0;
380
856
    } else if (tag == 0x9C) { /* Proprietary state machine descrip. */
381
26
      skip = 1;
382
830
    } else if (!skip) {
383
547
      switch (tag) {
384
102
      case 0x90:  /* Always */
385
102
        sc_log(ctx, "     SC: always\n");
386
102
        break;
387
10
      case 0x97:  /* Never */
388
10
        sc_log(ctx, "     SC: never\n");
389
10
        break;
390
19
      case 0xA4:  /* Authentication, value is a CRT. */
391
19
        sc_log_hex(ctx, "     SC: auth", p, taglen);
392
19
        break;
393
394
21
      case 0xB4:
395
39
      case 0xB6:
396
49
      case 0xB8:  /* Cmd or resp with SM, value is a CRT. */
397
49
        sc_log_hex(ctx, "     SC: cmd/resp", p, taglen);
398
49
        break;
399
400
11
      case 0x9E:  /* Security Condition byte. */
401
11
        sc_log_hex(ctx, "     SC: condition", p, taglen);
402
11
        break;
403
404
23
      case 0xA0:  /* OR template. */
405
23
        sc_log(ctx, "     SC: OR\n");
406
23
        break;
407
58
      case 0xAF:  /* AND template. */
408
58
        sc_log(ctx, "     SC: AND\n");
409
58
        break;
410
547
      }
411
547
    }
412
1.17k
    left -= taglen;
413
1.17k
    p += taglen;
414
1.17k
  }
415
416
115
}
417
418
static void process_fcp(sc_card_t * card, sc_file_t * file,
419
      const u8 * buf, size_t buflen)
420
374
{
421
374
  sc_context_t *ctx = card->ctx;
422
374
  size_t taglen, len = buflen;
423
374
  const u8 *tag = NULL, *p = buf;
424
374
  int bad_fde = 0;
425
426
374
  sc_log(ctx, "processing FCI bytes\n");
427
428
  /* File identifier. */
429
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
430
374
  if (tag != NULL && taglen == 2) {
431
54
    file->id = (tag[0] << 8) | tag[1];
432
54
    sc_log(ctx,
433
54
      "  file identifier: 0x%02X%02X\n", tag[0], tag[1]);
434
54
  }
435
  /* Number of data bytes in the file including structural information. */
436
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
437
374
  if (!tag) {
438
    /* My card does not encode the filelength in 0x81 but
439
       in 0x85 which is the file descriptor extension in TCOS.
440
       Assume that this is the case when the regular file
441
       size tag is not encoded. */
442
341
    tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
443
341
    bad_fde = !!tag;
444
341
  }
445
374
  if (tag != NULL && taglen >= 2) {
446
57
    int bytes = (tag[0] << 8) + tag[1];
447
57
    sc_log(ctx,
448
57
      "  bytes in file: %d\n", bytes);
449
57
    file->size = (size_t)bytes;
450
57
  }
451
374
  if (tag == NULL) {
452
309
    tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
453
309
    if (tag != NULL && taglen >= 2) {
454
22
      int bytes = (tag[0] << 8) + tag[1];
455
22
      sc_log(ctx,
456
22
        "  bytes in file: %d\n", bytes);
457
22
      file->size = (size_t)bytes;
458
22
    }
459
309
  }
460
461
  /* File descriptor byte(s). */
462
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
463
374
  if (tag != NULL) {
464
    /* Fixme, this might actual be up to 6 bytes. */
465
178
    if (taglen > 0) {
466
168
      unsigned char byte = tag[0];
467
168
      const char *type;
468
469
168
      file->shareable = byte & 0x40 ? 1 : 0;
470
168
      sc_log(ctx,
471
168
        "  shareable: %s\n",
472
168
         (byte & 0x40) ? "yes" : "no");
473
168
      file->ef_structure = byte & 0x07;
474
168
      switch ((byte >> 3) & 7) {
475
75
      case 0:
476
75
        type = "working EF";
477
75
        file->type = SC_FILE_TYPE_WORKING_EF;
478
75
        break;
479
13
      case 1:
480
13
        type = "internal EF";
481
13
        file->type = SC_FILE_TYPE_INTERNAL_EF;
482
13
        break;
483
24
      case 7:
484
24
        type = "DF";
485
24
        file->type = SC_FILE_TYPE_DF;
486
24
        break;
487
56
      default:
488
56
        type = "unknown";
489
56
        break;
490
168
      }
491
168
      sc_log(ctx,
492
168
        "  type: %s\n", type);
493
168
      sc_log(ctx,
494
168
        "  EF structure: %d\n", byte & 0x07);
495
168
    }
496
178
  }
497
498
  /* DF name. */
499
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
500
374
  if (tag != NULL && taglen > 0 && taglen <= 16) {
501
44
    char name[17];
502
44
    size_t i;
503
504
44
    memcpy(file->name, tag, taglen);
505
44
    file->namelen = taglen;
506
507
357
    for (i = 0; i < taglen; i++) {
508
313
      if (isalnum(tag[i]) || ispunct(tag[i]) || isspace(tag[i]))
509
165
        name[i] = (const char)tag[i];
510
148
      else
511
148
        name[i] = '?';
512
313
    }
513
44
    name[taglen] = 0;
514
44
    sc_log(ctx, "  file name: %s\n", name);
515
44
  }
516
517
  /* Proprietary information. */
518
374
  tag = bad_fde ? NULL : sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
519
374
  if (tag != NULL && taglen) {
520
6
    sc_file_set_prop_attr(file, tag, taglen);
521
6
  } else
522
368
    file->prop_attr_len = 0;
523
524
  /* Proprietary information, constructed. */
525
374
  tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen);
526
374
  if (tag != NULL && taglen) {
527
4
    sc_file_set_prop_attr(file, tag, taglen);
528
4
  }
529
530
  /* Security attributes, proprietary format. */
531
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen);
532
374
  if (tag != NULL && taglen) {
533
23
    sc_file_set_sec_attr(file, tag, taglen);
534
23
  }
535
536
  /* Security attributes, reference to expanded format. */
537
374
  tag = sc_asn1_find_tag(ctx, p, len, 0x8B, &taglen);
538
374
  if (tag && taglen) {
539
137
    process_arr(card, tag, taglen);
540
237
  } else if ((tag = sc_asn1_find_tag(ctx, p, len, 0xA1, &taglen))
541
9
      && taglen) {
542
    /* Not found, but there is a Security Attribute
543
       Template for interface mode. */
544
5
    tag = sc_asn1_find_tag(ctx, tag, taglen, 0x8B, &taglen);
545
5
    if (tag && taglen)
546
1
      process_arr(card, tag, taglen);
547
5
  }
548
549
374
  file->magic = SC_FILE_MAGIC;
550
374
}
551
552
/* Send a select command and parse the response. */
553
static int
554
do_select(sc_card_t * card, u8 kind,
555
    const u8 * buf, size_t buflen, sc_file_t ** file)
556
3.96k
{
557
3.96k
  sc_apdu_t apdu;
558
3.96k
  u8 resbuf[SC_MAX_APDU_BUFFER_SIZE];
559
3.96k
  int r;
560
561
3.96k
  u8 p2 = 0x00;
562
3.96k
  if (kind == MCRD_SEL_EF) p2 = 0x04;
563
3.96k
  if (kind == MCRD_SEL_DF) p2 = 0x0C;
564
565
3.96k
  sc_format_apdu_ex(&apdu, 0x00, 0xA4, kind, p2, buf, buflen, resbuf, 256);
566
3.96k
  r = sc_transmit_apdu(card, &apdu);
567
3.96k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
568
3.94k
  if (!file) {
569
2.84k
    if (apdu.sw1 == 0x61)
570
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, 0);
571
2.84k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
572
2.84k
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
573
2.84k
  }
574
1.09k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
575
1.09k
  if (r)
576
597
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
577
578
501
  if (p2 == 0x0C) {
579
25
    if (file) {
580
25
      *file = sc_file_new();
581
25
      if (!*file)
582
25
        LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
583
25
      (*file)->type = SC_FILE_TYPE_DF;
584
25
      return SC_SUCCESS;
585
25
    }
586
25
  }
587
588
476
  if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) {
589
35
    if (apdu.resp[1] > apdu.resplen - 2)
590
35
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
591
20
    *file = sc_file_new();
592
20
    if (!*file)
593
20
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
594
20
    process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
595
20
    return SC_SUCCESS;
596
20
  }
597
598
441
  if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) {
599
369
    if (apdu.resp[1] > apdu.resplen - 2)
600
369
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
601
354
    *file = sc_file_new();
602
354
    if (!*file)
603
354
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
604
354
    process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
605
354
    return SC_SUCCESS;
606
354
  }
607
72
  return SC_SUCCESS;
608
441
}
609
610
/* Wrapper around do_select to be used when multiple selects are
611
   required. */
612
static int
613
select_part(sc_card_t * card, u8 kind, unsigned short int fid,
614
    sc_file_t ** file)
615
3.14k
{
616
3.14k
  u8 fbuf[2];
617
3.14k
  unsigned int len;
618
3.14k
  int r;
619
620
3.14k
  sc_log(card->ctx,
621
3.14k
    "select_part (0x%04X, kind=%u)\n", fid, kind);
622
623
3.14k
  if (fid == MFID) {
624
1.08k
    kind = MCRD_SEL_MF; /* force this kind. */
625
1.08k
    len = 0;
626
2.06k
  } else {
627
2.06k
    fbuf[0] = fid >> 8;
628
2.06k
    fbuf[1] = fid & 0xff;
629
2.06k
    len = 2;
630
2.06k
  }
631
3.14k
  r = do_select(card, kind, fbuf, len, file);
632
633
3.14k
  return r;
634
3.14k
}
635
636
/* Select a file by iterating over the FID in the PATHPTR array while
637
   updating the curpath kept in the private data cache.  With DF_ONLY
638
   passed as true only DF are selected, otherwise the function tries
639
   to figure out whether the last path item is a DF or EF. */
640
static int
641
select_down(sc_card_t * card,
642
    unsigned short *pathptr, size_t pathlen,
643
    int df_only, sc_file_t ** file)
644
1.43k
{
645
1.43k
  struct mcrd_priv_data *priv = DRVDATA(card);
646
1.43k
  int r;
647
1.43k
  int found_ef = 0;
648
649
1.43k
  if (!pathlen)
650
0
    return SC_ERROR_INVALID_ARGUMENTS;
651
652
2.12k
  for (; pathlen; pathlen--, pathptr++) {
653
1.63k
    if (priv->curpathlen == MAX_CURPATH)
654
1.63k
      LOG_TEST_RET(card->ctx, SC_ERROR_INTERNAL,
655
1.63k
          "path too long for cache");
656
1.63k
    r = -1;   /* force DF select. */
657
1.63k
    if (pathlen == 1 && !df_only) {
658
      /* first try to select an EF and retry an DF
659
         on error. */
660
957
      r = select_part(card, MCRD_SEL_EF, *pathptr, file);
661
957
      if (r == SC_SUCCESS)
662
444
        found_ef = 1;
663
957
    }
664
1.63k
    if (r != SC_SUCCESS)
665
1.19k
      r = select_part(card, MCRD_SEL_DF, *pathptr,
666
1.19k
          pathlen == 1 ? file : NULL);
667
1.63k
    LOG_TEST_RET(card->ctx, r, "unable to select DF");
668
690
    priv->curpath[priv->curpathlen] = *pathptr;
669
690
    priv->curpathlen++;
670
690
  }
671
485
  priv->is_ef = found_ef;
672
485
  if (!found_ef)
673
41
    load_special_files(card);
674
675
485
  return 0;
676
1.43k
}
677
678
/* Handle the selection case when a PATH is requested.  Our card does
679
   not support this addressing so we have to emulate it.  To keep the
680
   security status we should not unnecessary change the directory;
681
   this is accomplished be keeping track of the currently selected
682
   file.  Note that PATH is an array of PATHLEN file ids and not the
683
   usual sc_path structure. */
684
685
static int
686
select_file_by_path(sc_card_t * card, unsigned short *pathptr,
687
      size_t pathlen, sc_file_t ** file)
688
1.92k
{
689
1.92k
  struct mcrd_priv_data *priv = DRVDATA(card);
690
1.92k
  int r;
691
1.92k
  size_t i;
692
693
1.92k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
694
695
1.92k
  if (!(!priv->curpathlen || priv->curpath[0] == MFID))
696
2
    return SC_ERROR_INTERNAL;
697
698
1.92k
  if (pathlen && *pathptr == 0x3FFF) {
699
4
    pathlen--;
700
4
    pathptr++;
701
4
  }
702
703
1.92k
  if (!pathlen || pathlen >= MAX_CURPATH)
704
1
    r = SC_ERROR_INVALID_ARGUMENTS;
705
1.92k
  else if (pathlen == 1 && pathptr[0] == MFID) {
706
    /* MF requested: clear the cache and select it. */
707
481
    priv->curpathlen = 0;
708
481
    r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
709
481
    LOG_TEST_RET(card->ctx, r, "unable to select MF");
710
377
    priv->curpath[0] = pathptr[0];
711
377
    priv->curpathlen = 1;
712
377
    priv->is_ef = 0;
713
1.44k
  } else if (pathlen > 1 && pathptr[0] == MFID) {
714
    /* Absolute addressing, check cache to avoid
715
       unnecessary selects. */
716
844
    for (i = 0; (i < pathlen && i < priv->curpathlen
717
486
        && pathptr[i] == priv->curpath[i]); i++) ;
718
600
    if (!priv->curpathlen) {
719
      /* Need to do all selects starting at the root. */
720
358
      priv->curpathlen = 0;
721
358
      priv->is_ef = 0;
722
358
      r = select_down(card, pathptr, pathlen, 0, file);
723
358
    } else if (i == pathlen && i < priv->curpathlen) {
724
      /* Go upwards; we do it the easy way and start
725
         at the root.  However we know that the target is a DF. */
726
0
      priv->curpathlen = 0;
727
0
      priv->is_ef = 0;
728
0
      r = select_down(card, pathptr, pathlen, 1, file);
729
242
    } else if (i == pathlen && i == priv->curpathlen) {
730
      /* Already selected. */
731
0
      if (!file)
732
0
        r = 0; /* The caller did not request the fci. */
733
0
      else {
734
        /* This EF or DF was already selected, but
735
           we need to get the FCI, so we have
736
           to select again. */
737
0
        if (!(priv->curpathlen > 1))
738
0
          return SC_ERROR_INTERNAL;
739
0
        priv->curpathlen--;
740
0
        priv->is_ef = 0;
741
0
        r = select_down(card, pathptr + pathlen - 1, 1,
742
0
            0, file);
743
0
      }
744
242
    } else {
745
      /* We have to append something.  For now we
746
         simply start at the root. (fixme) */
747
242
      priv->curpathlen = 0;
748
242
      priv->is_ef = 0;
749
242
      r = select_down(card, pathptr, pathlen, 0, file);
750
242
    }
751
845
  } else {
752
    /* Relative addressing. */
753
845
    if (!priv->curpathlen) {
754
      /* Relative addressing without a current path. So we
755
         select the MF first. */
756
57
      r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
757
57
      LOG_TEST_RET(card->ctx, r, "unable to select MF");
758
45
      priv->curpath[0] = pathptr[0];
759
45
      priv->curpathlen = 1;
760
45
      priv->is_ef = 0;
761
45
    }
762
833
    if (priv->is_ef) {
763
100
      if(!(priv->curpathlen > 1))
764
0
        return SC_ERROR_INTERNAL;
765
100
      priv->curpathlen--;
766
100
      priv->is_ef = 0;
767
100
    }
768
    /* Free the previously allocated file so we do not leak memory here */
769
833
    if (file) {
770
639
      sc_file_free(*file);
771
639
      *file = NULL;
772
639
    }
773
833
    r = select_down(card, pathptr, pathlen, 0, file);
774
833
  }
775
1.81k
  return r;
776
1.92k
}
777
778
static int
779
select_file_by_fid(sc_card_t * card, unsigned short *pathptr,
780
      size_t pathlen, sc_file_t ** file)
781
0
{
782
0
  struct mcrd_priv_data *priv = DRVDATA(card);
783
0
  int r;
784
785
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
786
787
0
  if (!(!priv->curpathlen || priv->curpath[0] == MFID))
788
0
    return SC_ERROR_INTERNAL;
789
790
0
  if (pathlen > 1)
791
0
    return SC_ERROR_INVALID_ARGUMENTS;
792
793
0
  if (pathlen && *pathptr == 0x3FFF)
794
0
    return 0;
795
796
0
  if (!pathlen) {
797
    /* re-select the current one if needed. */
798
0
    if (!file)
799
0
      r = 0; /* The caller did not request the fci. */
800
0
    else if (!priv->curpathlen) {
801
      /* There is no current file. */
802
0
      r = SC_ERROR_INTERNAL;
803
0
    } else {
804
0
      if (!(priv->curpathlen > 1))
805
0
        return SC_ERROR_INTERNAL;
806
0
      priv->curpathlen--;
807
0
      priv->is_ef = 0;
808
0
      r = select_down(card, pathptr, 1, 0, file);
809
0
    }
810
0
  } else if (pathptr[0] == MFID) {
811
    /* MF requested: clear the cache and select it. */
812
0
    priv->curpathlen = 0;
813
0
    r = select_part(card, MCRD_SEL_MF, MFID, file);
814
0
    LOG_TEST_RET(card->ctx, r, "unable to select MF");
815
0
    priv->curpath[0] = MFID;
816
0
    priv->curpathlen = 1;
817
0
    priv->is_ef = 0;
818
0
  } else {
819
    /* Relative addressing. */
820
0
    if (!priv->curpathlen) {
821
      /* Relative addressing without a current path. So we
822
         select the MF first. */
823
0
      r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
824
0
      LOG_TEST_RET(card->ctx, r, "unable to select MF");
825
0
      priv->curpath[0] = pathptr[0];
826
0
      priv->curpathlen = 1;
827
0
      priv->is_ef = 0;
828
0
    }
829
0
    if (priv->is_ef) {
830
0
      if (!(priv->curpathlen > 1))
831
0
        return SC_ERROR_INTERNAL;
832
0
      priv->curpathlen--;
833
0
      priv->is_ef = 0;
834
0
    }
835
    /* Free the previously allocated file so we do not leak memory here */
836
0
    if (file) {
837
0
      sc_file_free(*file);
838
0
      *file = NULL;
839
0
    }
840
0
    r = select_down(card, pathptr, 1, 0, file);
841
0
  }
842
843
0
  return r;
844
0
}
845
846
/* This drivers select command handler. */
847
static int
848
mcrd_select_file(sc_card_t * card, const sc_path_t * path, sc_file_t ** file)
849
2.75k
{
850
2.75k
  struct mcrd_priv_data *priv = DRVDATA(card);
851
2.75k
  int r = 0;
852
853
2.75k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
854
855
2.75k
  if (path->type == SC_PATH_TYPE_DF_NAME) {
856
822
    if (path->len > 16)
857
0
      return SC_ERROR_INVALID_ARGUMENTS;
858
822
    r = do_select(card, MCRD_SEL_AID, path->value, path->len, file);
859
822
    priv->curpathlen = 0;
860
1.92k
  } else {
861
1.92k
    unsigned short int pathtmp[SC_MAX_PATH_SIZE / 2];
862
1.92k
    unsigned short int *pathptr;
863
1.92k
    int samepath = 1;
864
1.92k
    size_t pathlen, n;
865
866
1.92k
    if ((path->len & 1) || path->len > sizeof(pathtmp))
867
0
      return SC_ERROR_INVALID_ARGUMENTS;
868
869
1.92k
    memset(pathtmp, 0, sizeof pathtmp);
870
1.92k
    pathptr = pathtmp;
871
5.46k
    for (n = 0; n < path->len; n += 2)
872
3.53k
      pathptr[n >> 1] =
873
3.53k
        (unsigned short)((path->value[n] << 8) | path->value[n + 1]);
874
1.92k
    pathlen = path->len >> 1;
875
876
1.92k
    if (pathlen == priv->curpathlen && priv->is_ef != 2) {
877
1.45k
      for (n = 0; n < pathlen; n++) {
878
974
        if (priv->curpath[n] != pathptr[n]) {
879
251
          samepath = 0;
880
251
          break;
881
251
        }
882
974
      }
883
1.19k
    } else if (priv->curpathlen < pathlen && priv->is_ef != 2) {
884
1.95k
      for (n = 0; n < priv->curpathlen; n++) {
885
816
        if (priv->curpath[n] != pathptr[n]) {
886
32
          samepath = 0;
887
32
          break;
888
32
        }
889
816
      }
890
1.17k
      pathptr = pathptr + n;
891
1.17k
      pathlen = pathlen - n;
892
1.17k
    }
893
894
1.92k
    if (samepath != 1 || priv->is_ef == 0 || priv->is_ef == 1) {
895
1.92k
      if (path->type == SC_PATH_TYPE_PATH)
896
1.92k
        r = select_file_by_path(card, pathptr, pathlen, file);
897
0
      else { /* SC_PATH_TYPE_FILEID */
898
0
        r = select_file_by_fid(card, pathptr, pathlen, file);
899
0
      }
900
1.92k
    }
901
1.92k
  }
902
903
2.75k
  return r;
904
2.75k
}
905
906
/* It seems that MICARDO does not fully comply with ISO, so I use
907
   values gathered from peeking actual signing operations using a
908
   different system.
909
   It has been generalized [?] and modified by information coming from
910
   openpgp card implementation and some other sources. -mp
911
   */
912
static int mcrd_set_security_env(sc_card_t * card,
913
         const sc_security_env_t * env, int se_num)
914
0
{
915
0
  struct mcrd_priv_data *priv;
916
0
  sc_apdu_t apdu;
917
0
  u8 sbuf[5] = {0x83, 0x03, 0x80, 0, 0};
918
0
  int r = 0, locked = 0;
919
920
0
  if (card == NULL || env == NULL)
921
0
    return SC_ERROR_INTERNAL;
922
0
  LOG_FUNC_CALLED(card->ctx);
923
0
  priv = DRVDATA(card);
924
925
  /* some sanity checks */
926
0
  if (env->flags & SC_SEC_ENV_ALG_PRESENT) {
927
0
    if (env->algorithm != SC_ALGORITHM_RSA)
928
0
      return SC_ERROR_INVALID_ARGUMENTS;
929
0
  }
930
0
  if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT)
931
0
    || env->key_ref_len != 1)
932
0
    return SC_ERROR_INVALID_ARGUMENTS;
933
934
0
  switch (env->operation) {
935
0
  case SC_SEC_OPERATION_DECIPHER:
936
0
    sc_log(card->ctx, "Using keyref %d to decipher\n", env->key_ref[0]);
937
0
    mcrd_delete_ref_to_authkey(card);
938
0
    mcrd_delete_ref_to_signkey(card);
939
0
    break;
940
0
  case SC_SEC_OPERATION_SIGN:
941
0
    sc_log(card->ctx, "Using keyref %d to sign\n", env->key_ref[0]);
942
0
    break;
943
0
  default:
944
0
    return SC_ERROR_INVALID_ARGUMENTS;
945
0
  }
946
0
  priv->sec_env = *env;
947
948
0
  sbuf[3] = env->key_ref[0];
949
0
  switch (env->operation) {
950
0
  case SC_SEC_OPERATION_DECIPHER:
951
0
    sc_format_apdu_ex(&apdu, 0x00, 0x22, 0x41, 0xB8, sbuf, 5, NULL, 0);
952
0
    break;
953
0
  case SC_SEC_OPERATION_SIGN:
954
0
    sc_format_apdu_ex(&apdu, 0x00, 0x22, 0x41, 0xB6, sbuf, 5, NULL, 0);
955
0
    break;
956
0
  default:
957
0
    return SC_ERROR_INVALID_ARGUMENTS;
958
0
  }
959
960
0
  if (se_num > 0) {
961
0
    r = sc_lock(card);
962
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
963
0
    locked = 1;
964
0
  }
965
0
  if (apdu.datalen != 0) {
966
0
    r = sc_transmit_apdu(card, &apdu);
967
0
    if (r) {
968
0
      sc_log(card->ctx,
969
0
        "%s: APDU transmit failed", sc_strerror(r));
970
0
      goto err;
971
0
    }
972
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
973
0
    if (r) {
974
0
      sc_log(card->ctx,
975
0
        "%s: Card returned error", sc_strerror(r));
976
0
      goto err;
977
0
    }
978
0
  }
979
0
  if (se_num <= 0)
980
0
    return 0;
981
0
  sc_unlock(card);
982
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
983
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
984
0
err:
985
0
  if (locked)
986
0
    sc_unlock(card);
987
0
  return r;
988
0
}
989
990
/* heavily modified by -mp */
991
static int mcrd_compute_signature(sc_card_t * card,
992
          const u8 * data, size_t datalen,
993
          u8 * out, size_t outlen)
994
0
{
995
0
  struct mcrd_priv_data *priv = DRVDATA(card);
996
0
  sc_security_env_t *env = NULL;
997
0
  int r;
998
0
  sc_apdu_t apdu;
999
1000
0
  if (data == NULL || out == NULL)
1001
0
    return SC_ERROR_INVALID_ARGUMENTS;
1002
0
  env = &priv->sec_env;
1003
1004
0
  LOG_FUNC_CALLED(card->ctx);
1005
0
  if (env->operation != SC_SEC_OPERATION_SIGN)
1006
0
    return SC_ERROR_INVALID_ARGUMENTS;
1007
0
  if (datalen > 255)
1008
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
1009
1010
0
  sc_log(card->ctx,
1011
0
     "Will compute signature (%d) for %"SC_FORMAT_LEN_SIZE_T"u (0x%02"SC_FORMAT_LEN_SIZE_T"x) bytes using key %d algorithm %lu flags %lu\n",
1012
0
     env->operation, datalen, datalen, env->key_ref[0],
1013
0
     env->algorithm, env->algorithm_flags);
1014
1015
0
  if (env->key_ref[0] == 1) /* authentication key */
1016
0
    sc_format_apdu_ex(&apdu, 0x00, 0x88, 0, 0, data, datalen, out, MIN(0x80U, outlen));
1017
0
  else
1018
0
    sc_format_apdu_ex(&apdu, 0x00, 0x2A, 0x9E, 0x9A, data, datalen, out, MIN(0x80U, outlen));
1019
0
  r = sc_transmit_apdu(card, &apdu);
1020
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1021
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1022
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1023
1024
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)apdu.resplen);
1025
0
}
1026
1027
/* added by -mp, to give pin information in the card driver (pkcs15emu->driver needed) */
1028
static int mcrd_pin_cmd(sc_card_t * card, struct sc_pin_cmd_data *data,
1029
      int *tries_left)
1030
1
{
1031
1
  LOG_FUNC_CALLED(card->ctx);
1032
1
  data->pin1.offset = 5;
1033
1
  data->pin2.offset = 5;
1034
1035
1
  if (card->type == SC_CARD_TYPE_MCRD_GENERIC) {
1036
1
    sc_log(card->ctx, "modify pin reference for D-Trust\n");
1037
1
    if (data->pin_reference == 0x02)
1038
1
      data->pin_reference = data->pin_reference | 0x80;
1039
1
  }
1040
1
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, iso_ops->pin_cmd(card, data, tries_left));
1041
1
}
1042
1043
static int mcrd_logout(sc_card_t * card)
1044
0
{
1045
0
  return SC_ERROR_NOT_SUPPORTED;
1046
0
}
1047
1048
/* Driver binding */
1049
static struct sc_card_driver *sc_get_driver(void)
1050
17.2k
{
1051
17.2k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
1052
17.2k
  if (iso_ops == NULL)
1053
1
    iso_ops = iso_drv->ops;
1054
1055
17.2k
  mcrd_ops = *iso_drv->ops;
1056
17.2k
  mcrd_ops.match_card = mcrd_match_card;
1057
17.2k
  mcrd_ops.init = mcrd_init;
1058
17.2k
  mcrd_ops.finish = mcrd_finish;
1059
17.2k
  mcrd_ops.select_file = mcrd_select_file;
1060
17.2k
  mcrd_ops.set_security_env = mcrd_set_security_env;
1061
17.2k
  mcrd_ops.compute_signature = mcrd_compute_signature;
1062
17.2k
  mcrd_ops.pin_cmd = mcrd_pin_cmd;
1063
17.2k
  mcrd_ops.logout = mcrd_logout;
1064
1065
17.2k
  return &mcrd_drv;
1066
17.2k
}
1067
1068
struct sc_card_driver *sc_get_mcrd_driver(void)
1069
17.2k
{
1070
17.2k
  return sc_get_driver();
1071
17.2k
}