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