Coverage Report

Created: 2026-02-26 06:59

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
5.68k
#define MFID 0x3F00
68
26
#define EF_KeyD 0x0013    /* File with extra key information. */
69
345
#define EF_Rule 0x0030    /* Default ACL file. */
70
71
2.93k
#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
5.99k
#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
544
{
112
544
  sc_context_t *ctx = card->ctx;
113
544
  struct mcrd_priv_data *priv = DRVDATA(card);
114
544
  struct df_info_s *dfi;
115
116
544
  if(!(!priv->is_ef))
117
1
    return NULL;
118
119
543
  if (!priv->curpathlen) {
120
92
    sc_log(ctx, "no current path to find the df_info\n");
121
92
    return NULL;
122
92
  }
123
124
501
  for (dfi = priv->df_infos; dfi; dfi = dfi->next) {
125
154
    if (dfi->pathlen == priv->curpathlen
126
114
      && !memcmp(dfi->path, priv->curpath,
127
114
          dfi->pathlen * sizeof *dfi->path))
128
104
      return dfi;
129
154
  }
130
  /* Not found, create it. */
131
347
  dfi = calloc(1, sizeof *dfi);
132
347
  if (!dfi) {
133
0
    sc_log(ctx, "out of memory while allocating df_info\n");
134
0
    return NULL;
135
0
  }
136
347
  dfi->pathlen = priv->curpathlen;
137
347
  memcpy(dfi->path, priv->curpath, dfi->pathlen * sizeof *dfi->path);
138
347
  dfi->next = priv->df_infos;
139
347
  priv->df_infos = dfi;
140
347
  return dfi;
141
347
}
142
143
static void clear_special_files(struct df_info_s *dfi)
144
783
{
145
783
  if (dfi) {
146
2.13k
    while (dfi->rule_file) {
147
1.43k
      struct rule_record_s *tmp = dfi->rule_file->next;
148
1.43k
      free(dfi->rule_file);
149
1.43k
      dfi->rule_file = tmp;
150
1.43k
    }
151
986
    while (dfi->keyd_file) {
152
294
      struct keyd_record_s *tmp = dfi->keyd_file->next;
153
294
      free(dfi->keyd_file);
154
294
      dfi->keyd_file = tmp;
155
294
    }
156
692
  }
157
783
}
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
13.5k
{
192
13.5k
  int i = 0;
193
194
13.5k
  i = _sc_match_atr(card, mcrd_atrs, &card->type);
195
13.5k
  if (i >= 0) {
196
397
    card->name = mcrd_atrs[i].name;
197
397
    return 1;
198
397
  }
199
200
13.1k
  return 0;
201
13.5k
}
202
203
static int mcrd_init(sc_card_t * card)
204
397
{
205
397
  unsigned long flags;
206
397
  struct mcrd_priv_data *priv = calloc(1, sizeof *priv);
207
397
  if (!priv)
208
0
    return SC_ERROR_OUT_OF_MEMORY;
209
397
  priv->curpath[0] = MFID;
210
397
  priv->curpathlen = 1;
211
397
  card->drv_data = priv;
212
397
  card->cla = 0x00;
213
397
  card->caps = SC_CARD_CAP_RNG;
214
215
397
  flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1 | SC_ALGORITHM_RSA_HASH_NONE;
216
397
  _sc_card_add_rsa_alg(card, 512, flags, 0);
217
397
  _sc_card_add_rsa_alg(card, 768, flags, 0);
218
397
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
219
220
397
  if (SC_SUCCESS != sc_select_file (card, sc_get_mf_path(), NULL))
221
91
    sc_log(card->ctx, "Warning: select MF failed");
222
223
397
  load_special_files(card);
224
225
397
  return SC_SUCCESS;
226
397
}
227
228
static int mcrd_finish(sc_card_t * card)
229
397
{
230
397
  struct mcrd_priv_data *priv;
231
232
397
  if (card == NULL)
233
0
    return 0;
234
397
  priv = DRVDATA(card);
235
744
  while (priv->df_infos) {
236
347
    struct df_info_s *tmp = priv->df_infos->next;
237
347
    clear_special_files(priv->df_infos);
238
347
    free(priv->df_infos);
239
347
    priv->df_infos = tmp;
240
347
  }
241
397
  free(priv);
242
397
  return 0;
243
397
}
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
436
{
249
436
  sc_context_t *ctx = card->ctx;
250
436
  int r;
251
436
  unsigned int recno;
252
436
  struct df_info_s *dfi;
253
436
  struct rule_record_s *rule;
254
436
  struct keyd_record_s *keyd;
255
256
  /* First check whether we already cached it. */
257
436
  dfi = get_df_info(card);
258
436
  if (dfi && dfi->rule_file)
259
0
    return 0; /* yes. */
260
436
  clear_special_files(dfi);
261
436
  if (!dfi)
262
436
    LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
263
264
  /* Read rule file. Note that we bypass our cache here. */
265
345
  r = select_part(card, MCRD_SEL_EF, EF_Rule, NULL);
266
345
  LOG_TEST_RET(ctx, r, "selecting EF_Rule failed");
267
268
1.62k
  for (recno = 1;; recno++) {
269
1.62k
    u8 recbuf[256];
270
1.62k
    r = sc_read_record(card, recno, 0, recbuf, sizeof(recbuf),
271
1.62k
          SC_RECORD_BY_REC_NR);
272
273
1.62k
    if (r == SC_ERROR_RECORD_NOT_FOUND)
274
26
      break;
275
1.59k
    if (r < 0) {
276
155
      SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
277
1.43k
    } else {
278
1.43k
      rule = malloc(sizeof *rule + (size_t)r);
279
1.43k
      if (!rule)
280
1.43k
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
281
1.43k
      rule->recno = recno;
282
1.43k
      rule->datalen = (size_t)r;
283
1.43k
      memcpy(rule->data, recbuf, r);
284
1.43k
      rule->next = dfi->rule_file;
285
1.43k
      dfi->rule_file = rule;
286
1.43k
    }
287
1.59k
  }
288
289
26
  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
26
  r = select_part(card, MCRD_SEL_EF, EF_KeyD, NULL);
293
26
  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
25
  LOG_TEST_RET(ctx, r, "selecting EF_KeyD failed");
298
299
313
  for (recno = 1;; recno++) {
300
313
    u8 recbuf[256];
301
313
    r = sc_read_record(card, recno, 0, recbuf, sizeof(recbuf),
302
313
          SC_RECORD_BY_REC_NR);
303
304
313
    if (r == SC_ERROR_RECORD_NOT_FOUND)
305
3
      break;
306
310
    if (r < 0) {
307
16
      SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_VERBOSE, r);
308
294
    } else {
309
294
      keyd = malloc(sizeof *keyd + (size_t)r);
310
294
      if (!keyd)
311
294
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
312
294
      keyd->recno = recno;
313
294
      keyd->datalen = (size_t) r;
314
294
      memcpy(keyd->data, recbuf, r);
315
294
      keyd->next = dfi->keyd_file;
316
294
      dfi->keyd_file = keyd;
317
294
    }
318
310
  }
319
320
3
  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
3
  return 0;
324
19
}
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
124
{
329
124
  sc_context_t *ctx = card->ctx;
330
124
  struct df_info_s *dfi;
331
124
  struct rule_record_s *rule;
332
124
  size_t left, taglen;
333
124
  unsigned int cla, tag;
334
124
  const u8 *p;
335
124
  int skip;
336
124
  char dbgbuf[2048];
337
338
  /* Currently we support only the short for. */
339
124
  if (buflen != 1) {
340
16
    sc_log(ctx, "can't handle long ARRs\n");
341
16
    return;
342
16
  }
343
344
108
  dfi = get_df_info(card);
345
306
  for (rule = dfi ? dfi->rule_file : NULL; rule && rule->recno != *buf;
346
198
    rule = rule->next) ;
347
108
  if (!rule) {
348
13
    sc_log(ctx, "referenced EF_rule record %d not found\n", *buf);
349
13
    return;
350
13
  }
351
352
95
  sc_hex_dump(rule->data, rule->datalen, dbgbuf, sizeof dbgbuf);
353
95
  sc_log(ctx,
354
95
    "rule for record %d:\n%s", *buf, dbgbuf);
355
356
95
  p = rule->data;
357
95
  left = rule->datalen;
358
95
  skip = 1;   /* Skip over initial unknown SC DOs. */
359
1.55k
  for (;;) {
360
1.55k
    buf = p;
361
1.55k
    if (sc_asn1_read_tag(&p, left, &cla, &tag, &taglen) != SC_SUCCESS
362
1.49k
        || p == NULL)
363
95
      break;
364
1.46k
    left -= (size_t)(p - buf);
365
1.46k
    tag |= cla;
366
367
1.46k
    if (tag == 0x80 && taglen != 1) {
368
102
      skip = 1;
369
1.35k
    } else if (tag == 0x80) { /* AM byte. */
370
12
      sc_log(ctx, "  AM_DO: %02x\n", *p);
371
12
      skip = 0;
372
1.34k
    } else if (tag >= 0x81 && tag <= 0x8f) { /* Cmd description */
373
247
      sc_hex_dump(p, taglen, dbgbuf, sizeof dbgbuf);
374
247
      sc_log(ctx, "  AM_DO: cmd[%s%s%s%s] %s",
375
247
         (tag & 8) ? "C" : "",
376
247
         (tag & 4) ? "I" : "",
377
247
         (tag & 2) ? "1" : "",
378
247
         (tag & 1) ? "2" : "", dbgbuf);
379
247
      skip = 0;
380
1.09k
    } else if (tag == 0x9C) { /* Proprietary state machine descrip. */
381
22
      skip = 1;
382
1.07k
    } else if (!skip) {
383
733
      switch (tag) {
384
161
      case 0x90:  /* Always */
385
161
        sc_log(ctx, "     SC: always\n");
386
161
        break;
387
13
      case 0x97:  /* Never */
388
13
        sc_log(ctx, "     SC: never\n");
389
13
        break;
390
13
      case 0xA4:  /* Authentication, value is a CRT. */
391
13
        sc_log_hex(ctx, "     SC: auth", p, taglen);
392
13
        break;
393
394
18
      case 0xB4:
395
41
      case 0xB6:
396
118
      case 0xB8:  /* Cmd or resp with SM, value is a CRT. */
397
118
        sc_log_hex(ctx, "     SC: cmd/resp", p, taglen);
398
118
        break;
399
400
7
      case 0x9E:  /* Security Condition byte. */
401
7
        sc_log_hex(ctx, "     SC: condition", p, taglen);
402
7
        break;
403
404
23
      case 0xA0:  /* OR template. */
405
23
        sc_log(ctx, "     SC: OR\n");
406
23
        break;
407
42
      case 0xAF:  /* AND template. */
408
42
        sc_log(ctx, "     SC: AND\n");
409
42
        break;
410
733
      }
411
733
    }
412
1.46k
    left -= taglen;
413
1.46k
    p += taglen;
414
1.46k
  }
415
416
95
}
417
418
static void process_fcp(sc_card_t * card, sc_file_t * file,
419
      const u8 * buf, size_t buflen)
420
321
{
421
321
  sc_context_t *ctx = card->ctx;
422
321
  size_t taglen, len = buflen;
423
321
  const u8 *tag = NULL, *p = buf;
424
321
  int bad_fde = 0;
425
426
321
  sc_log(ctx, "processing FCI bytes\n");
427
428
  /* File identifier. */
429
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x83, &taglen);
430
321
  if (tag != NULL && taglen == 2) {
431
30
    file->id = (tag[0] << 8) | tag[1];
432
30
    sc_log(ctx,
433
30
      "  file identifier: 0x%02X%02X\n", tag[0], tag[1]);
434
30
  }
435
  /* Number of data bytes in the file including structural information. */
436
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x81, &taglen);
437
321
  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
298
    tag = sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
443
298
    bad_fde = !!tag;
444
298
  }
445
321
  if (tag != NULL && taglen >= 2) {
446
44
    int bytes = (tag[0] << 8) + tag[1];
447
44
    sc_log(ctx,
448
44
      "  bytes in file: %d\n", bytes);
449
44
    file->size = (size_t)bytes;
450
44
  }
451
321
  if (tag == NULL) {
452
272
    tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
453
272
    if (tag != NULL && taglen >= 2) {
454
18
      int bytes = (tag[0] << 8) + tag[1];
455
18
      sc_log(ctx,
456
18
        "  bytes in file: %d\n", bytes);
457
18
      file->size = (size_t)bytes;
458
18
    }
459
272
  }
460
461
  /* File descriptor byte(s). */
462
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
463
321
  if (tag != NULL) {
464
    /* Fixme, this might actual be up to 6 bytes. */
465
147
    if (taglen > 0) {
466
130
      unsigned char byte = tag[0];
467
130
      const char *type;
468
469
130
      file->shareable = byte & 0x40 ? 1 : 0;
470
130
      sc_log(ctx,
471
130
        "  shareable: %s\n",
472
130
         (byte & 0x40) ? "yes" : "no");
473
130
      file->ef_structure = byte & 0x07;
474
130
      switch ((byte >> 3) & 7) {
475
68
      case 0:
476
68
        type = "working EF";
477
68
        file->type = SC_FILE_TYPE_WORKING_EF;
478
68
        break;
479
8
      case 1:
480
8
        type = "internal EF";
481
8
        file->type = SC_FILE_TYPE_INTERNAL_EF;
482
8
        break;
483
9
      case 7:
484
9
        type = "DF";
485
9
        file->type = SC_FILE_TYPE_DF;
486
9
        break;
487
45
      default:
488
45
        type = "unknown";
489
45
        break;
490
130
      }
491
130
      sc_log(ctx,
492
130
        "  type: %s\n", type);
493
130
      sc_log(ctx,
494
130
        "  EF structure: %d\n", byte & 0x07);
495
130
    }
496
147
  }
497
498
  /* DF name. */
499
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x84, &taglen);
500
321
  if (tag != NULL && taglen > 0 && taglen <= 16) {
501
33
    char name[17];
502
33
    size_t i;
503
504
33
    memcpy(file->name, tag, taglen);
505
33
    file->namelen = taglen;
506
507
272
    for (i = 0; i < taglen; i++) {
508
239
      if (isalnum(tag[i]) || ispunct(tag[i]) || isspace(tag[i]))
509
128
        name[i] = (const char)tag[i];
510
111
      else
511
111
        name[i] = '?';
512
239
    }
513
33
    name[taglen] = 0;
514
33
    sc_log(ctx, "  file name: %s\n", name);
515
33
  }
516
517
  /* Proprietary information. */
518
321
  tag = bad_fde ? NULL : sc_asn1_find_tag(ctx, p, len, 0x85, &taglen);
519
321
  if (tag != NULL && taglen) {
520
6
    sc_file_set_prop_attr(file, tag, taglen);
521
6
  } else
522
315
    file->prop_attr_len = 0;
523
524
  /* Proprietary information, constructed. */
525
321
  tag = sc_asn1_find_tag(ctx, p, len, 0xA5, &taglen);
526
321
  if (tag != NULL && taglen) {
527
4
    sc_file_set_prop_attr(file, tag, taglen);
528
4
  }
529
530
  /* Security attributes, proprietary format. */
531
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x86, &taglen);
532
321
  if (tag != NULL && taglen) {
533
20
    sc_file_set_sec_attr(file, tag, taglen);
534
20
  }
535
536
  /* Security attributes, reference to expanded format. */
537
321
  tag = sc_asn1_find_tag(ctx, p, len, 0x8B, &taglen);
538
321
  if (tag && taglen) {
539
123
    process_arr(card, tag, taglen);
540
198
  } else if ((tag = sc_asn1_find_tag(ctx, p, len, 0xA1, &taglen))
541
12
      && taglen) {
542
    /* Not found, but there is a Security Attribute
543
       Template for interface mode. */
544
8
    tag = sc_asn1_find_tag(ctx, tag, taglen, 0x8B, &taglen);
545
8
    if (tag && taglen)
546
1
      process_arr(card, tag, taglen);
547
8
  }
548
549
321
  file->magic = SC_FILE_MAGIC;
550
321
}
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.20k
{
557
3.20k
  sc_apdu_t apdu;
558
3.20k
  u8 resbuf[SC_MAX_APDU_BUFFER_SIZE];
559
3.20k
  int r;
560
561
3.20k
  u8 p2 = 0x00;
562
3.20k
  if (kind == MCRD_SEL_EF) p2 = 0x04;
563
3.20k
  if (kind == MCRD_SEL_DF) p2 = 0x0C;
564
565
3.20k
  sc_format_apdu_ex(&apdu, 0x00, 0xA4, kind, p2, buf, buflen, resbuf, 256);
566
3.20k
  r = sc_transmit_apdu(card, &apdu);
567
3.20k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
568
3.17k
  if (!file) {
569
2.36k
    if (apdu.sw1 == 0x61)
570
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, 0);
571
2.36k
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
572
2.36k
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
573
2.36k
  }
574
816
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
575
816
  if (r)
576
383
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
577
578
433
  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
408
  if (p2 == 0x04 && apdu.resplen > 2 && apdu.resp[0] == 0x62) {
589
21
    if (apdu.resp[1] > apdu.resplen - 2)
590
21
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
591
9
    *file = sc_file_new();
592
9
    if (!*file)
593
9
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
594
9
    process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
595
9
    return SC_SUCCESS;
596
9
  }
597
598
387
  if (p2 != 0x0C && apdu.resplen > 2 && apdu.resp[0] == 0x6F) {
599
321
    if (apdu.resp[1] > apdu.resplen - 2)
600
321
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_DATA);
601
312
    *file = sc_file_new();
602
312
    if (!*file)
603
312
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
604
312
    process_fcp(card, *file, apdu.resp + 2, apdu.resp[1]);
605
312
    return SC_SUCCESS;
606
312
  }
607
66
  return SC_SUCCESS;
608
387
}
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
2.49k
{
616
2.49k
  u8 fbuf[2];
617
2.49k
  unsigned int len;
618
2.49k
  int r;
619
620
2.49k
  sc_log(card->ctx,
621
2.49k
    "select_part (0x%04X, kind=%u)\n", fid, kind);
622
623
2.49k
  if (fid == MFID) {
624
960
    kind = MCRD_SEL_MF; /* force this kind. */
625
960
    len = 0;
626
1.53k
  } else {
627
1.53k
    fbuf[0] = fid >> 8;
628
1.53k
    fbuf[1] = fid & 0xff;
629
1.53k
    len = 2;
630
1.53k
  }
631
2.49k
  r = do_select(card, kind, fbuf, len, file);
632
633
2.49k
  return r;
634
2.49k
}
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.17k
{
645
1.17k
  struct mcrd_priv_data *priv = DRVDATA(card);
646
1.17k
  int r;
647
1.17k
  int found_ef = 0;
648
649
1.17k
  if (!pathlen)
650
0
    return SC_ERROR_INVALID_ARGUMENTS;
651
652
1.78k
  for (; pathlen; pathlen--, pathptr++) {
653
1.35k
    if (priv->curpathlen == MAX_CURPATH)
654
1.35k
      LOG_TEST_RET(card->ctx, SC_ERROR_INTERNAL,
655
1.35k
          "path too long for cache");
656
1.35k
    r = -1;   /* force DF select. */
657
1.35k
    if (pathlen == 1 && !df_only) {
658
      /* first try to select an EF and retry an DF
659
         on error. */
660
717
      r = select_part(card, MCRD_SEL_EF, *pathptr, file);
661
717
      if (r == SC_SUCCESS)
662
387
        found_ef = 1;
663
717
    }
664
1.35k
    if (r != SC_SUCCESS)
665
966
      r = select_part(card, MCRD_SEL_DF, *pathptr,
666
966
          pathlen == 1 ? file : NULL);
667
1.35k
    LOG_TEST_RET(card->ctx, r, "unable to select DF");
668
606
    priv->curpath[priv->curpathlen] = *pathptr;
669
606
    priv->curpathlen++;
670
606
  }
671
426
  priv->is_ef = found_ef;
672
426
  if (!found_ef)
673
39
    load_special_files(card);
674
675
426
  return 0;
676
1.17k
}
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.58k
{
689
1.58k
  struct mcrd_priv_data *priv = DRVDATA(card);
690
1.58k
  int r;
691
1.58k
  size_t i;
692
693
1.58k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
694
695
1.58k
  if (!(!priv->curpathlen || priv->curpath[0] == MFID))
696
1
    return SC_ERROR_INTERNAL;
697
698
1.58k
  if (pathlen && *pathptr == 0x3FFF) {
699
5
    pathlen--;
700
5
    pathptr++;
701
5
  }
702
703
1.58k
  if (!pathlen || pathlen >= MAX_CURPATH)
704
1
    r = SC_ERROR_INVALID_ARGUMENTS;
705
1.58k
  else if (pathlen == 1 && pathptr[0] == MFID) {
706
    /* MF requested: clear the cache and select it. */
707
399
    priv->curpathlen = 0;
708
399
    r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
709
399
    LOG_TEST_RET(card->ctx, r, "unable to select MF");
710
307
    priv->curpath[0] = pathptr[0];
711
307
    priv->curpathlen = 1;
712
307
    priv->is_ef = 0;
713
1.18k
  } else if (pathlen > 1 && pathptr[0] == MFID) {
714
    /* Absolute addressing, check cache to avoid
715
       unnecessary selects. */
716
798
    for (i = 0; (i < pathlen && i < priv->curpathlen
717
469
        && pathptr[i] == priv->curpath[i]); i++) ;
718
562
    if (!priv->curpathlen) {
719
      /* Need to do all selects starting at the root. */
720
328
      priv->curpathlen = 0;
721
328
      priv->is_ef = 0;
722
328
      r = select_down(card, pathptr, pathlen, 0, file);
723
328
    } 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
234
    } else if (i == pathlen && i == priv->curpathlen) {
730
      /* Already selected. */
731
1
      if (!file)
732
1
        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
233
    } else {
745
      /* We have to append something.  For now we
746
         simply start at the root. (fixme) */
747
233
      priv->curpathlen = 0;
748
233
      priv->is_ef = 0;
749
233
      r = select_down(card, pathptr, pathlen, 0, file);
750
233
    }
751
621
  } else {
752
    /* Relative addressing. */
753
621
    if (!priv->curpathlen) {
754
      /* Relative addressing without a current path. So we
755
         select the MF first. */
756
42
      r = select_part(card, MCRD_SEL_MF, pathptr[0], file);
757
42
      LOG_TEST_RET(card->ctx, r, "unable to select MF");
758
35
      priv->curpath[0] = pathptr[0];
759
35
      priv->curpathlen = 1;
760
35
      priv->is_ef = 0;
761
35
    }
762
614
    if (priv->is_ef) {
763
81
      if(!(priv->curpathlen > 1))
764
0
        return SC_ERROR_INTERNAL;
765
81
      priv->curpathlen--;
766
81
      priv->is_ef = 0;
767
81
    }
768
    /* Free the previously allocated file so we do not leak memory here */
769
614
    if (file) {
770
489
      sc_file_free(*file);
771
489
      *file = NULL;
772
489
    }
773
614
    r = select_down(card, pathptr, pathlen, 0, file);
774
614
  }
775
1.48k
  return r;
776
1.58k
}
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.29k
{
850
2.29k
  struct mcrd_priv_data *priv = DRVDATA(card);
851
2.29k
  int r = 0;
852
853
2.29k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
854
855
2.29k
  if (path->type == SC_PATH_TYPE_DF_NAME) {
856
709
    if (path->len > 16)
857
0
      return SC_ERROR_INVALID_ARGUMENTS;
858
709
    r = do_select(card, MCRD_SEL_AID, path->value, path->len, file);
859
709
    priv->curpathlen = 0;
860
1.58k
  } else {
861
1.58k
    unsigned short int pathtmp[SC_MAX_PATH_SIZE / 2];
862
1.58k
    unsigned short int *pathptr;
863
1.58k
    int samepath = 1;
864
1.58k
    size_t pathlen, n;
865
866
1.58k
    if ((path->len & 1) || path->len > sizeof(pathtmp))
867
0
      return SC_ERROR_INVALID_ARGUMENTS;
868
869
1.58k
    memset(pathtmp, 0, sizeof pathtmp);
870
1.58k
    pathptr = pathtmp;
871
4.48k
    for (n = 0; n < path->len; n += 2)
872
2.90k
      pathptr[n >> 1] =
873
2.90k
        (unsigned short)((path->value[n] << 8) | path->value[n + 1]);
874
1.58k
    pathlen = path->len >> 1;
875
876
1.58k
    if (pathlen == priv->curpathlen && priv->is_ef != 2) {
877
1.27k
      for (n = 0; n < pathlen; n++) {
878
881
        if (priv->curpath[n] != pathptr[n]) {
879
248
          samepath = 0;
880
248
          break;
881
248
        }
882
881
      }
883
938
    } else if (priv->curpathlen < pathlen && priv->is_ef != 2) {
884
1.49k
      for (n = 0; n < priv->curpathlen; n++) {
885
600
        if (priv->curpath[n] != pathptr[n]) {
886
26
          samepath = 0;
887
26
          break;
888
26
        }
889
600
      }
890
920
      pathptr = pathptr + n;
891
920
      pathlen = pathlen - n;
892
920
    }
893
894
1.58k
    if (samepath != 1 || priv->is_ef == 0 || priv->is_ef == 1) {
895
1.58k
      if (path->type == SC_PATH_TYPE_PATH)
896
1.58k
        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.58k
    }
901
1.58k
  }
902
903
2.29k
  return r;
904
2.29k
}
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
13.9k
{
1051
13.9k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
1052
13.9k
  if (iso_ops == NULL)
1053
1
    iso_ops = iso_drv->ops;
1054
1055
13.9k
  mcrd_ops = *iso_drv->ops;
1056
13.9k
  mcrd_ops.match_card = mcrd_match_card;
1057
13.9k
  mcrd_ops.init = mcrd_init;
1058
13.9k
  mcrd_ops.finish = mcrd_finish;
1059
13.9k
  mcrd_ops.select_file = mcrd_select_file;
1060
13.9k
  mcrd_ops.set_security_env = mcrd_set_security_env;
1061
13.9k
  mcrd_ops.compute_signature = mcrd_compute_signature;
1062
13.9k
  mcrd_ops.pin_cmd = mcrd_pin_cmd;
1063
13.9k
  mcrd_ops.logout = mcrd_logout;
1064
1065
13.9k
  return &mcrd_drv;
1066
13.9k
}
1067
1068
struct sc_card_driver *sc_get_mcrd_driver(void)
1069
13.9k
{
1070
13.9k
  return sc_get_driver();
1071
13.9k
}