Coverage Report

Created: 2025-08-26 06:43

/src/opensc/src/libopensc/card-cardos.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * card-cardos.c: Support for CardOS (from Siemens or Atos) based cards and
3
 * tokens (for example Aladdin eToken PRO, Eutron CryptoIdentity IT-SEC)
4
 *
5
 * Copyright (c) 2005  Nils Larsch <nils@larsch.net>
6
 * Copyright (C) 2002  Andreas Jellinghaus <aj@dungeon.inka.de>
7
 * Copyright (C) 2001  Juha Yrjölä <juha.yrjola@iki.fi>
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
24
#ifdef HAVE_CONFIG_H
25
#include "config.h"
26
#endif
27
28
#include <ctype.h>
29
#include <string.h>
30
#include <stdlib.h>
31
32
#include "internal.h"
33
#include "asn1.h"
34
#include "cardctl.h"
35
36
static const struct sc_card_operations *iso_ops = NULL;
37
38
static struct sc_card_operations cardos_ops;
39
static struct sc_card_driver cardos_drv = {
40
  "Siemens CardOS",
41
  "cardos",
42
  &cardos_ops,
43
  NULL, 0, NULL
44
};
45
46
static const struct sc_atr_table cardos_atrs[] = {
47
  /* 4.0 */
48
  { "3b:e2:00:ff:c1:10:31:fe:55:c8:02:9c", NULL, NULL, SC_CARD_TYPE_CARDOS_GENERIC, 0, NULL },
49
  /* cardos m4.2 and above */
50
  { "3b:f2:18:00:ff:c1:0a:31:fe:55:c8:06:8a", "ff:ff:0f:ff:00:ff:00:ff:ff:00:00:00:00", NULL, SC_CARD_TYPE_CARDOS_M4_2, 0, NULL },
51
  /* CardOS 4.4 */
52
  { "3b:d2:18:02:c1:0a:31:fe:58:c8:0d:51", NULL, NULL, SC_CARD_TYPE_CARDOS_M4_4, 0, NULL},
53
  /* CardOS v5.0 */
54
  { "3b:d2:18:00:81:31:fe:58:c9:01:14", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_0, 0, NULL},
55
  /* CardOS v5.3 */
56
  { "3b:d2:18:00:81:31:fe:58:c9:02:17", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
57
  { "3b:d2:18:00:81:31:fe:58:c9:03:16", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
58
  /* CardOS v5.4 */
59
  { "3b:d2:18:00:81:31:fe:58:c9:04:11", NULL, NULL, SC_CARD_TYPE_CARDOS_V5_3, 0, NULL},
60
  { NULL, NULL, NULL, 0, 0, NULL }
61
};
62
63
/* private data for cardos driver */
64
typedef struct cardos_data {
65
  /* constructed internally */
66
  unsigned int algorithm_ids_in_tokeninfo[SC_MAX_SUPPORTED_ALGORITHMS];
67
  unsigned int algorithm_ids_in_tokeninfo_count;
68
  unsigned long flags; /* flags used by init to create sc_algorithms */
69
  unsigned long ec_flags;
70
  unsigned long ext_flags;
71
  int rsa_2048;
72
  const sc_security_env_t * sec_env;
73
} cardos_data_t;
74
75
static int cardos_match_card(sc_card_t *card)
76
0
{
77
0
  unsigned char atr[SC_MAX_ATR_SIZE] = {0};
78
0
  int i;
79
80
0
  i = _sc_match_atr(card, cardos_atrs, &card->type);
81
0
  if (i < 0)
82
0
    return 0;
83
84
0
  memcpy(atr, card->atr.value, card->atr.len);
85
86
  /* Do not change card type for CIE! */
87
0
  if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1)
88
0
    return 1;
89
0
  if (card->type == SC_CARD_TYPE_CARDOS_M4_4)
90
0
    return 1;
91
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0)
92
0
    return 1;
93
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_3)
94
0
    return 1;
95
0
  if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
96
0
    int rv;
97
0
    sc_apdu_t apdu = {0};
98
0
    u8 rbuf[SC_MAX_APDU_BUFFER_SIZE] = {0};
99
    /* first check some additional ATR bytes */
100
0
    if ((atr[4] != 0xff && atr[4] != 0x02) ||
101
0
        (atr[6] != 0x10 && atr[6] != 0x0a) ||
102
0
        (atr[9] != 0x55 && atr[9] != 0x58))
103
0
      return 0;
104
    /* get the os version using GET DATA and compare it with
105
     * version in the ATR */
106
0
    sc_log(card->ctx,  "checking cardos version ...");
107
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x82);
108
0
    apdu.resp = rbuf;
109
0
    apdu.resplen = sizeof(rbuf);
110
0
    apdu.le = 256;
111
0
    apdu.lc = 0;
112
0
    rv = sc_transmit_apdu(card, &apdu);
113
0
    LOG_TEST_RET(card->ctx, rv, "APDU transmit failed");
114
0
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00 || apdu.resplen < 2)
115
0
      return 0;
116
0
    if (apdu.resp[0] != atr[10] ||
117
0
        apdu.resp[1] != atr[11])
118
      /* version mismatch */
119
0
      return 0;
120
0
    if (atr[11] <= 0x04) {
121
0
      sc_log(card->ctx,  "found cardos m4.01");
122
0
      card->type = SC_CARD_TYPE_CARDOS_M4_01;
123
0
    } else if (atr[11] == 0x08) {
124
0
      sc_log(card->ctx,  "found cardos v4.3b");
125
0
      card->type = SC_CARD_TYPE_CARDOS_M4_3;
126
0
    } else if (atr[11] == 0x09) {
127
0
      sc_log(card->ctx,  "found cardos v4.2b");
128
0
      card->type = SC_CARD_TYPE_CARDOS_M4_2B;
129
0
    } else if (atr[11] >= 0x0B) {
130
0
      sc_log(card->ctx,  "found cardos v4.2c or higher");
131
0
      card->type = SC_CARD_TYPE_CARDOS_M4_2C;
132
0
    } else {
133
0
      sc_log(card->ctx,  "found cardos m4.2");
134
0
    }
135
0
  }
136
0
  return 1;
137
0
}
138
139
static int cardos_have_2048bit_package(sc_card_t *card)
140
0
{
141
0
  sc_apdu_t apdu;
142
0
        u8        rbuf[SC_MAX_APDU_BUFFER_SIZE];
143
0
        int       r;
144
0
  const u8  *p = rbuf, *q, *pp;
145
0
  size_t    len, tlen = 0, ilen = 0;
146
147
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x88);
148
0
  apdu.resp    = rbuf;
149
0
  apdu.resplen = sizeof(rbuf);
150
0
  apdu.lc = 0;
151
0
  apdu.le = 256;
152
0
  r = sc_transmit_apdu(card, &apdu);
153
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
154
155
0
  if ((len = apdu.resplen) == 0)
156
    /* looks like no package has been installed  */
157
0
    return 0;
158
159
0
  while (len != 0) {
160
0
    pp = sc_asn1_find_tag(card->ctx, p, len, 0xe1, &tlen);
161
0
    if (pp == NULL)
162
0
      return 0;
163
0
    q = sc_asn1_find_tag(card->ctx, pp, tlen, 0x01, &ilen);
164
0
    if (q == NULL || ilen != 4)
165
0
      return 0;
166
0
    if (q[0] == 0x1c)
167
0
      return 1;
168
0
    p   += tlen;
169
0
    len -= tlen + 2;
170
0
  }
171
172
0
  return 0;
173
0
}
174
175
176
/* Called from cardos_init for old cards, from cardos_cardctl_parsed_token_info for new cards */
177
/* TODO see if works from old cards too */
178
static int cardos_add_algs(sc_card_t *card, unsigned long flags, unsigned long ec_flags, unsigned long ext_flags)
179
0
{
180
181
0
  cardos_data_t * priv = (cardos_data_t *)card->drv_data;
182
183
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
184
185
0
  _sc_card_add_rsa_alg(card,  512, flags, 0);
186
0
  _sc_card_add_rsa_alg(card,  768, flags, 0);
187
0
  _sc_card_add_rsa_alg(card, 1024, flags, 0);
188
0
  if (priv->rsa_2048 == 1) {
189
0
    _sc_card_add_rsa_alg(card, 1280, flags, 0);
190
0
    _sc_card_add_rsa_alg(card, 1536, flags, 0);
191
0
    _sc_card_add_rsa_alg(card, 1792, flags, 0);
192
0
    _sc_card_add_rsa_alg(card, 2048, flags, 0);
193
0
  }
194
195
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
196
    /* Starting with CardOS 5, the card supports PIN query commands */
197
0
    card->caps |= SC_CARD_CAP_ISO7816_PIN_INFO;
198
0
    _sc_card_add_rsa_alg(card, 3072, flags, 0);
199
0
    _sc_card_add_rsa_alg(card, 4096, flags, 0);
200
0
  }
201
202
  /* TODO need to get sizes from supported_algos too */
203
0
  if (ec_flags != 0) {
204
0
     _sc_card_add_ec_alg(card, 256, ec_flags, priv->ext_flags, NULL);
205
0
     _sc_card_add_ec_alg(card, 384, ec_flags, priv->ext_flags, NULL);
206
0
  }
207
208
0
  return 0;
209
0
}
210
211
static int cardos_init(sc_card_t *card)
212
0
{
213
0
  cardos_data_t * priv = NULL;
214
0
  unsigned long flags = 0;
215
0
  size_t data_field_length;
216
0
  sc_apdu_t apdu;
217
0
  u8 rbuf[2];
218
0
  int r;
219
220
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
221
222
0
  priv = calloc(1, sizeof(cardos_data_t));
223
0
  if (!priv)
224
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
225
0
  card->drv_data = priv;
226
227
0
  card->name = "Atos CardOS";
228
0
  card->cla = 0x00;
229
230
  /* let user override flags and type from opensc.conf */
231
  /* user can override card->type too.*/
232
0
  if (card->flags) {
233
0
      flags = card->flags;
234
0
  } else {
235
236
    /* Set up algorithm info. */
237
0
    flags = 0;
238
0
    if (card->type == SC_CARD_TYPE_CARDOS_V5_0) {
239
0
      flags |= SC_ALGORITHM_RSA_PAD_PKCS1;
240
0
    } else if(card->type == SC_CARD_TYPE_CARDOS_V5_3) {
241
0
      flags |= SC_ALGORITHM_RSA_RAW
242
0
        | SC_ALGORITHM_RSA_HASH_NONE
243
0
        | SC_ALGORITHM_ONBOARD_KEY_GEN;
244
0
    } else {
245
0
      flags |= SC_ALGORITHM_RSA_RAW
246
0
        | SC_ALGORITHM_RSA_HASH_NONE
247
0
        | SC_ALGORITHM_NEED_USAGE
248
0
        | SC_ALGORITHM_ONBOARD_KEY_GEN;
249
0
    }
250
0
  }
251
252
0
  priv->flags = flags;
253
254
0
  if (card->type == SC_CARD_TYPE_CARDOS_M4_2) {
255
0
    r = cardos_have_2048bit_package(card);
256
0
    if (r < 0) {
257
0
      r = SC_ERROR_INVALID_CARD;
258
0
      goto err;
259
0
    }
260
0
    if (r == 1)
261
0
      priv->rsa_2048 = 1;
262
0
    card->caps |= SC_CARD_CAP_APDU_EXT;
263
0
  } else if (card->type == SC_CARD_TYPE_CARDOS_M4_3
264
0
    || card->type == SC_CARD_TYPE_CARDOS_M4_2B
265
0
    || card->type == SC_CARD_TYPE_CARDOS_M4_2C
266
0
    || card->type == SC_CARD_TYPE_CARDOS_M4_4
267
0
    || card->type == SC_CARD_TYPE_CARDOS_V5_0
268
0
    || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
269
0
    priv->rsa_2048 = 1;
270
0
    card->caps |= SC_CARD_CAP_APDU_EXT;
271
    /* TODO check this. EC only if in supported_algo */
272
0
    priv->ext_flags = SC_ALGORITHM_EXT_EC_NAMEDCURVE | SC_ALGORITHM_EXT_EC_UNCOMPRESES;
273
0
  }
274
275
  /* probe DATA FIELD LENGTH with GET DATA */
276
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x8D);
277
0
  apdu.le = sizeof rbuf;
278
0
  apdu.resp = rbuf;
279
0
  apdu.resplen = sizeof(rbuf);
280
281
0
  r = sc_transmit_apdu(card, &apdu);
282
0
  if (r < 0)
283
0
    LOG_TEST_GOTO_ERR(card->ctx,
284
0
        SC_ERROR_INVALID_CARD,
285
0
        "APDU transmit failed");
286
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
287
0
  if (r < 0)
288
0
    LOG_TEST_GOTO_ERR(card->ctx,
289
0
        SC_ERROR_INVALID_CARD,
290
0
        "GET DATA command returned error");
291
0
  if (apdu.resplen != 2) {
292
0
    r = SC_ERROR_INVALID_CARD;
293
0
    goto err;
294
0
  }
295
0
  data_field_length = ((rbuf[0] << 8) | rbuf[1]);
296
297
  /* TODO is this really needed? strip the length of possible Lc and Le bytes */
298
299
  /* Use Min card sizes and reader too. for V5_3 at least*/
300
301
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
302
0
    sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "data_field_length:%"SC_FORMAT_LEN_SIZE_T"u "
303
0
        "card->reader->max_send_size:%"SC_FORMAT_LEN_SIZE_T"u "
304
0
        "card->reader->max_recv_size:%"SC_FORMAT_LEN_SIZE_T"u %s",
305
0
        data_field_length, card->reader->max_send_size, card->reader->max_recv_size,
306
0
        (card->caps & SC_CARD_CAP_APDU_EXT) ? "SC_CARD_CAP_APDU_EXT" : " ");
307
308
0
    if (card->caps & SC_CARD_CAP_APDU_EXT) {
309
0
      card->max_send_size  = data_field_length - 6;
310
#ifdef _WIN32
311
      /* Windows does not support PCSC PART_10 and may have forced reader to 255/256
312
       * https://github.com/OpenSC/OpenSC/commit/eddea6f3c2d3dafc2c09eba6695c745a61b5186f
313
       * may have reset this. if so, will override and force extended
314
       * Most, if not all, cardos cards do extended, but not chaining
315
       */
316
      if (card->reader->max_send_size == 255 && card->reader->max_recv_size == 256) {
317
        sc_debug(card->ctx, SC_LOG_DEBUG_VERBOSE, "resetting reader to use data_field_length");
318
        card->reader->max_send_size = data_field_length - 6;
319
        card->reader->max_recv_size = data_field_length - 3;
320
      }
321
#endif
322
0
    } else
323
0
      card->max_send_size = data_field_length - 3;
324
325
0
    card->max_send_size = sc_get_max_send_size(card); /* include reader sizes and protocol */
326
0
    card->max_recv_size = data_field_length - 2;
327
0
    card->max_recv_size = sc_get_max_recv_size(card);
328
0
  } else {
329
    /* old way, disregards reader capabilities */
330
0
    if (card->caps & SC_CARD_CAP_APDU_EXT)
331
0
      card->max_send_size = data_field_length - 6;
332
0
    else
333
0
      card->max_send_size = data_field_length - 3;
334
    /* strip the length of SW bytes */
335
0
    card->max_recv_size = data_field_length - 2;
336
0
  }
337
338
  /*for new cards, wait till after sc_pkcs15_bind_internal reads tokeninfo */
339
0
  if (card->type != SC_CARD_TYPE_CARDOS_V5_0 && card->type != SC_CARD_TYPE_CARDOS_V5_3) {
340
0
    r = cardos_add_algs(card, flags, 0, 0);
341
0
  }
342
343
0
err:
344
0
  if (r != SC_SUCCESS) {
345
0
    free(priv);
346
0
    card->drv_data = NULL;
347
0
  }
348
349
0
  return r;
350
0
}
351
352
static int cardos_pass_algo_flags(sc_card_t *card, struct sc_cardctl_cardos_pass_algo_flags * ptr)
353
0
{
354
0
  cardos_data_t * priv = (cardos_data_t *)card->drv_data;
355
0
  int r = 0;
356
357
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
358
0
  switch (ptr->pass) {
359
0
    case 1:
360
0
      ptr->card_flags = card->flags;
361
0
      ptr->used_flags = priv->flags;
362
0
      ptr->ec_flags = priv->ec_flags;
363
0
      ptr->ext_flags = priv->ext_flags;
364
0
      break;
365
0
    case 2:
366
0
      r = cardos_add_algs(card,ptr->new_flags, ptr->ec_flags, ptr->ext_flags);
367
0
      break;
368
0
    default:
369
0
      sc_log(card->ctx, "ptr->pass: %ul invalid", ptr->pass);
370
0
      r = SC_ERROR_INTERNAL;
371
0
  }
372
0
  LOG_FUNC_RETURN(card->ctx, r);
373
0
}
374
375
376
static int cardos_finish(sc_card_t *card)
377
0
{
378
0
  int r = 0;
379
380
0
  if (card == NULL )
381
0
    return 0;
382
383
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
384
385
  /* free priv data */
386
0
  if (card->drv_data) { /* priv */
387
0
    free(card->drv_data);
388
0
    card->drv_data = NULL;
389
0
  }
390
391
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
392
0
}
393
394
395
396
static const struct sc_card_error cardos_errors[] = {
397
/* some error inside the card */
398
/* i.e. nothing you can do */
399
{ 0x6581, SC_ERROR_MEMORY_FAILURE,  "EEPROM error; command aborted"},
400
{ 0x6fff, SC_ERROR_CARD_CMD_FAILED, "internal assertion error"},
401
{ 0x6700, SC_ERROR_WRONG_LENGTH,  "LC invalid"},
402
{ 0x6985, SC_ERROR_CARD_CMD_FAILED, "no random number available"},
403
{ 0x6f81, SC_ERROR_CARD_CMD_FAILED, "file invalid, maybe checksum error"},
404
{ 0x6f82, SC_ERROR_CARD_CMD_FAILED, "not enough memory in xram"},
405
{ 0x6f84, SC_ERROR_CARD_CMD_FAILED, "general protection fault"},
406
407
/* the card doesn't know this combination of ins+cla+p1+p2 */
408
/* i.e. command will never work */
409
{ 0x6881, SC_ERROR_NO_CARD_SUPPORT, "logical channel not supported"},
410
{ 0x6a86, SC_ERROR_INCORRECT_PARAMETERS,"p1/p2 invalid"},
411
{ 0x6d00, SC_ERROR_INS_NOT_SUPPORTED, "ins invalid"},
412
{ 0x6e00, SC_ERROR_CLASS_NOT_SUPPORTED, "class invalid (hi nibble)"},
413
414
/* known command, but incorrectly used */
415
/* i.e. command could work, but you need to change something */
416
{ 0x6981, SC_ERROR_CARD_CMD_FAILED, "command cannot be used for file structure"},
417
{ 0x6a80, SC_ERROR_INCORRECT_PARAMETERS,"invalid parameters in data field"},
418
{ 0x6a81, SC_ERROR_NOT_SUPPORTED, "function/mode not supported"},
419
{ 0x6a85, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit the tlv structure"},
420
{ 0x6986, SC_ERROR_INCORRECT_PARAMETERS,"no current ef selected"},
421
{ 0x6a87, SC_ERROR_INCORRECT_PARAMETERS,"lc does not fit p1/p2"},
422
{ 0x6c00, SC_ERROR_WRONG_LENGTH,  "le does not fit the data to be sent"},
423
{ 0x6f83, SC_ERROR_CARD_CMD_FAILED, "command must not be used in transaction"},
424
425
/* (something) not found */
426
{ 0x6987, SC_ERROR_INCORRECT_PARAMETERS,"key object for sm not found"},
427
{ 0x6f86, SC_ERROR_CARD_CMD_FAILED, "key object not found"},
428
{ 0x6a82, SC_ERROR_FILE_NOT_FOUND,  "file not found"},
429
{ 0x6a83, SC_ERROR_RECORD_NOT_FOUND,  "record not found"},
430
{ 0x6a88, SC_ERROR_CARD_CMD_FAILED, "object not found"},
431
432
/* (something) invalid */
433
{ 0x6884, SC_ERROR_CARD_CMD_FAILED, "chaining error"},
434
{ 0x6984, SC_ERROR_CARD_CMD_FAILED, "bs object has invalid format"},
435
{ 0x6988, SC_ERROR_INCORRECT_PARAMETERS,"key object used for sm has invalid format"},
436
437
/* (something) deactivated */
438
{ 0x6283, SC_ERROR_CARD_CMD_FAILED, "file is deactivated" },
439
{ 0x6983, SC_ERROR_AUTH_METHOD_BLOCKED, "bs object blocked"},
440
441
/* access denied */
442
{ 0x6300, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"authentication failed"},
443
{ 0x6982, SC_ERROR_SECURITY_STATUS_NOT_SATISFIED,"required access right not granted"},
444
445
/* other errors */
446
{ 0x6a84, SC_ERROR_CARD_CMD_FAILED, "not enough memory"},
447
448
/* command ok, execution failed */
449
{ 0x6f00, SC_ERROR_CARD_CMD_FAILED, "technical error (see eToken developers guide)"},
450
451
/* no error, maybe a note */
452
{ 0x9000, SC_SUCCESS,   NULL},
453
{ 0x9001, SC_SUCCESS,   "success, but eeprom weakness detected"},
454
{ 0x9850, SC_SUCCESS,   "over/underflow using in/decrease"}
455
};
456
457
static int cardos_check_sw(sc_card_t *card, unsigned int sw1, unsigned int sw2)
458
0
{
459
0
  const int err_count = sizeof(cardos_errors)/sizeof(cardos_errors[0]);
460
0
  int i;
461
462
0
  for (i = 0; i < err_count; i++) {
463
0
    if (cardos_errors[i].SWs == ((sw1 << 8) | sw2)) {
464
0
      if ( cardos_errors[i].errorstr )
465
0
        sc_log(card->ctx,  "%s\n",
466
0
          cardos_errors[i].errorstr);
467
0
      return cardos_errors[i].errorno;
468
0
    }
469
0
  }
470
471
0
        sc_log(card->ctx,  "Unknown SWs; SW1=%02X, SW2=%02X\n", sw1, sw2);
472
0
  return SC_ERROR_CARD_CMD_FAILED;
473
0
}
474
475
static int cardos_list_files(sc_card_t *card, u8 *buf, size_t buflen)
476
0
{
477
0
  sc_apdu_t apdu;
478
0
  u8        rbuf[256], offset = 0;
479
0
  const u8  *p, *q, *tag;
480
0
  int       r;
481
0
  size_t    fids = 0, len;
482
483
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
484
485
  /* 0x16: DIRECTORY */
486
  /* 0x02: list both DF and EF */
487
488
0
get_next_part:
489
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x16, 0x02, offset);
490
0
  apdu.cla = 0x80;
491
0
  apdu.le = 256;
492
0
  apdu.resplen = 256;
493
0
  apdu.resp = rbuf;
494
495
0
  r = sc_transmit_apdu(card, &apdu);
496
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
497
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
498
0
  LOG_TEST_RET(card->ctx, r, "DIRECTORY command returned error");
499
500
0
  if (apdu.resplen > 256) {
501
0
    sc_log(card->ctx,  "directory listing > 256 bytes, cutting");
502
0
  }
503
504
0
  p = rbuf;
505
0
  len = apdu.resplen;
506
0
  while (len != 0) {
507
0
    size_t   tlen = 0, ilen = 0;
508
    /* is there a file information block (0x6f) ? */
509
0
    tag = sc_asn1_find_tag(card->ctx, p, len, 0x6f, &tlen);
510
0
    if (tag == NULL) {
511
0
      sc_log(card->ctx,  "directory tag missing");
512
0
      return SC_ERROR_INTERNAL;
513
0
    }
514
0
    len = len - tlen - (tag - p);
515
0
    p = tag + tlen;
516
0
    if (tlen == 0)
517
      /* empty directory */
518
0
      break;
519
0
    q = sc_asn1_find_tag(card->ctx, tag, tlen, 0x86, &ilen);
520
0
    if (q == NULL || ilen != 2) {
521
0
      sc_log(card->ctx,  "error parsing file id TLV object");
522
0
      return SC_ERROR_INTERNAL;
523
0
    }
524
    /* put file id in buf */
525
0
    if (buflen >= 2) {
526
0
      buf[fids++] = q[0];
527
0
      buf[fids++] = q[1];
528
0
      buflen -= 2;
529
0
    } else
530
      /* not enough space left in buffer => break */
531
0
      break;
532
    /* extract next offset */
533
0
    q = sc_asn1_find_tag(card->ctx, tag, tlen, 0x8a, &ilen);
534
0
    if (q != NULL && ilen == 1) {
535
0
      offset = (u8)ilen;
536
0
      goto get_next_part;
537
0
    }
538
0
  }
539
540
0
  r = (int)fids;
541
542
0
  LOG_FUNC_RETURN(card->ctx, r);
543
0
}
544
545
static void add_acl_entry(sc_file_t *file, int op, u8 byte)
546
0
{
547
0
  unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
548
549
0
  switch (byte) {
550
0
  case 0x00:
551
0
    method = SC_AC_NONE;
552
0
    break;
553
0
  case 0xFF:
554
0
    method = SC_AC_NEVER;
555
0
    break;
556
0
  default:
557
0
    if (byte > 0x7F) {
558
0
      method = SC_AC_UNKNOWN;
559
0
    } else {
560
0
      method = SC_AC_CHV;
561
0
      key_ref = byte;
562
0
    }
563
0
    break;
564
0
  }
565
0
  sc_file_add_acl_entry(file, op, method, key_ref);
566
0
}
567
568
static int acl_to_byte(const sc_acl_entry_t *e)
569
0
{
570
0
  if (e != NULL) {
571
0
    switch (e->method) {
572
0
    case SC_AC_NONE:
573
0
      return 0x00;
574
0
    case SC_AC_NEVER:
575
0
      return 0xFF;
576
0
    case SC_AC_CHV:
577
0
    case SC_AC_TERM:
578
0
    case SC_AC_AUT:
579
0
      if (e->key_ref == SC_AC_KEY_REF_NONE)
580
0
        return -1;
581
0
      if (e->key_ref > 0x7F)
582
0
        return -1;
583
0
      return e->key_ref;
584
0
    }
585
0
  }
586
0
        return 0x00;
587
0
}
588
589
static const int df_acl[9] = {
590
  -1,     /* LCYCLE (life cycle change) */
591
  SC_AC_OP_UPDATE,  /* UPDATE Objects */
592
  -1,     /* APPEND Objects */
593
594
  SC_AC_OP_INVALIDATE,  /* DF */
595
  SC_AC_OP_REHABILITATE,  /* DF */
596
  SC_AC_OP_DELETE,  /* DF */
597
598
  SC_AC_OP_UPDATE,  /* ADMIN DF */
599
  SC_AC_OP_CREATE,  /* Files */
600
  -1      /* Reserved */
601
};
602
static const int ef_acl[9] = {
603
  SC_AC_OP_READ,    /* Data */
604
  SC_AC_OP_UPDATE,  /* Data (write file content) */
605
  SC_AC_OP_WRITE,   /* */
606
607
  SC_AC_OP_INVALIDATE,  /* EF */
608
  SC_AC_OP_REHABILITATE,  /* EF */
609
  SC_AC_OP_DELETE,  /* (delete) EF */
610
611
  /* XXX: ADMIN should be an ACL type of its own, or mapped
612
   * to erase */
613
  SC_AC_OP_UPDATE,  /* ADMIN EF (modify meta information?) */
614
  -1,     /* INC (-> cyclic fixed files) */
615
  -1      /* DEC */
616
};
617
618
static void parse_sec_attr(sc_file_t *file, const u8 *buf, size_t len)
619
0
{
620
0
  size_t i;
621
0
  const int *idx;
622
623
0
  idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
624
625
  /* acl defaults to 0xFF if unspecified */
626
0
  for (i = 0; i < 9; i++)
627
0
    if (idx[i] != -1)
628
0
      add_acl_entry(file, idx[i], (u8)((i < len) ? buf[i] : 0xFF));
629
0
}
630
631
static int cardos_select_file(sc_card_t *card,
632
            const sc_path_t *in_path,
633
            sc_file_t **file)
634
0
{
635
0
  int r;
636
637
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
638
0
  r = iso_ops->select_file(card, in_path, file);
639
0
  if (r >= 0 && file)
640
0
    parse_sec_attr((*file), (*file)->sec_attr, (*file)->sec_attr_len);
641
0
  LOG_FUNC_RETURN(card->ctx, r);
642
0
}
643
644
static int cardos_acl_to_bytes(sc_card_t *card, const sc_file_t *file,
645
  u8 *buf, size_t *outlen)
646
0
{
647
0
  int       i, byte;
648
0
  const int *idx;
649
650
0
  if (buf == NULL || *outlen < 9)
651
0
    return SC_ERROR_INVALID_ARGUMENTS;
652
653
0
  idx = (file->type == SC_FILE_TYPE_DF) ?  df_acl : ef_acl;
654
0
  for (i = 0; i < 9; i++) {
655
0
    if (idx[i] < 0)
656
0
      byte = 0x00;
657
0
    else
658
0
      byte = acl_to_byte(sc_file_get_acl_entry(file, idx[i]));
659
0
    if (byte < 0) {
660
0
      sc_log(card->ctx,  "Invalid ACL\n");
661
0
      return SC_ERROR_INVALID_ARGUMENTS;
662
0
    }
663
0
    buf[i] = byte;
664
0
  }
665
0
  *outlen = 9;
666
667
0
  return SC_SUCCESS;
668
0
}
669
670
static int cardos_set_file_attributes(sc_card_t *card, sc_file_t *file)
671
0
{
672
0
  int r;
673
674
0
  if (file->type_attr_len == 0) {
675
0
    u8 type[3];
676
677
0
    memset(type, 0, sizeof(type));
678
0
    type[0] = 0x00;
679
0
    switch (file->type) {
680
0
    case SC_FILE_TYPE_WORKING_EF:
681
0
      break;
682
0
    case SC_FILE_TYPE_DF:
683
0
      type[0] = 0x38;
684
0
      break;
685
0
    default:
686
0
      return SC_ERROR_NOT_SUPPORTED;
687
0
    }
688
0
    if (file->type != SC_FILE_TYPE_DF) {
689
0
      switch (file->ef_structure) {
690
0
      case SC_FILE_EF_LINEAR_FIXED_TLV:
691
0
      case SC_FILE_EF_LINEAR_VARIABLE:
692
0
      case SC_FILE_EF_CYCLIC_TLV:
693
0
        return SC_ERROR_NOT_SUPPORTED;
694
        /* No idea what this means, but it
695
         * seems to be required for key
696
         * generation. */
697
0
      case SC_FILE_EF_LINEAR_VARIABLE_TLV:
698
0
        type[1] = 0xff;
699
        /* fall through */
700
0
      default:
701
0
        type[0] |= file->ef_structure & 7;
702
0
        break;
703
0
      }
704
0
    }
705
0
    r = sc_file_set_type_attr(file, type, sizeof(type));
706
0
    if (r != SC_SUCCESS)
707
0
      return r;
708
0
  }
709
0
  if (file->prop_attr_len == 0) {
710
0
    u8 status[3];
711
712
0
    status[0] = 0x01;
713
0
    if (file->type == SC_FILE_TYPE_DF) {
714
0
      status[1] = (file->size >> 8) & 0xFF;
715
0
      status[2] = file->size & 0xFF;
716
0
    } else {
717
0
      status[1] = status[2] = 0x00; /* not used */
718
0
    }
719
0
    r = sc_file_set_prop_attr(file, status, sizeof(status));
720
0
    if (r != SC_SUCCESS)
721
0
      return r;
722
0
  }
723
0
  if (file->sec_attr_len == 0) {
724
0
    u8     acl[9];
725
0
    size_t blen = sizeof(acl);
726
727
0
    r = cardos_acl_to_bytes(card, file, acl, &blen);
728
0
    if (r != SC_SUCCESS)
729
0
      return r;
730
0
    r = sc_file_set_sec_attr(file, acl, blen);
731
0
    if (r != SC_SUCCESS)
732
0
      return r;
733
0
  }
734
0
  return SC_SUCCESS;
735
0
}
736
737
/* newer versions of cardos seems to prefer the FCP */
738
static int cardos_construct_fcp(sc_card_t *card, const sc_file_t *file,
739
  u8 *out, size_t *outlen)
740
0
{
741
0
  u8     buf[64], *p = out;
742
0
  size_t inlen = *outlen, len;
743
0
  int    r;
744
745
0
  LOG_FUNC_CALLED(card->ctx);
746
747
0
  if (out == NULL || inlen < 64)
748
0
    return SC_ERROR_INVALID_ARGUMENTS;
749
  /* add FCP tag */
750
0
  *p++ = 0x62;
751
  /* we will add the length later  */
752
0
  p++;
753
754
0
  memset(buf, 0, sizeof(buf));
755
756
  /* set the length */
757
0
  buf[0] = (file->size >> 8) & 0xff;
758
0
  buf[1] = file->size        & 0xff;
759
0
  if (file->type == SC_FILE_TYPE_DF)
760
0
    r = sc_asn1_put_tag(0x81, buf, 2, p, 4, &p);
761
0
  else
762
0
    r = sc_asn1_put_tag(0x80, buf, 2, p, 4, &p);
763
0
  if (r != SC_SUCCESS)
764
0
    return r;
765
  /* set file type  */
766
0
  if (file->shareable != 0)
767
0
    buf[0] = 0x40;
768
0
  else
769
0
    buf[0] = 0x00;
770
0
  if (file->type == SC_FILE_TYPE_WORKING_EF) {
771
0
    switch (file->ef_structure) {
772
0
    case SC_FILE_EF_TRANSPARENT:
773
0
      buf[0] |= 0x01;
774
0
      break;
775
0
    case SC_FILE_EF_LINEAR_VARIABLE_TLV:
776
0
      buf[0] |= 0x05;
777
0
      break;
778
0
    case SC_FILE_EF_LINEAR_FIXED:
779
0
      buf[0] |= 0x02;
780
0
      buf[1] |= 0x21;
781
0
      buf[2] |= 0x00;
782
0
      buf[3] |= (u8) file->record_length;
783
0
      buf[4] |= (u8) file->record_count;
784
0
      break;
785
0
    case SC_FILE_EF_CYCLIC:
786
0
      buf[0] |= 0x06;
787
0
      buf[1] |= 0x21;
788
0
      buf[2] |= 0x00;
789
0
      buf[3] |= (u8) file->record_length;
790
0
      buf[4] |= (u8) file->record_count;
791
0
      break;
792
0
    default:
793
0
      sc_log(card->ctx,  "unknown EF type: %u", file->type);
794
0
      return SC_ERROR_INVALID_ARGUMENTS;
795
0
    }
796
0
    if (file->ef_structure == SC_FILE_EF_CYCLIC ||
797
0
        file->ef_structure == SC_FILE_EF_LINEAR_FIXED)
798
0
    r = sc_asn1_put_tag(0x82, buf, 5, p, 8, &p);
799
0
  else
800
0
    r = sc_asn1_put_tag(0x82, buf, 1, p, 8, &p);
801
0
  } else if (file->type == SC_FILE_TYPE_DF) {
802
0
    buf[0] |= 0x38;
803
0
    r = sc_asn1_put_tag(0x82, buf, 1, p, 8, &p);
804
0
  } else
805
0
    return SC_ERROR_NOT_SUPPORTED;
806
0
  if (r != SC_SUCCESS)
807
0
    return r;
808
  /* set file id */
809
0
  buf[0] = (file->id >> 8) & 0xff;
810
0
  buf[1] = file->id        & 0xff;
811
0
  r = sc_asn1_put_tag(0x83, buf, 2, p, 8, &p);
812
0
  if (r != SC_SUCCESS)
813
0
    return r;
814
  /* set aid (for DF only) */
815
0
  if (file->type == SC_FILE_TYPE_DF && file->namelen != 0) {
816
0
    r = sc_asn1_put_tag(0x84, file->name, file->namelen, p, 20, &p);
817
0
    if (r != SC_SUCCESS)
818
0
      return r;
819
0
  }
820
  /* set proprietary file attributes */
821
0
  buf[0] = 0x00;    /* use default values */
822
0
  if (file->type == SC_FILE_TYPE_DF)
823
0
    r = sc_asn1_put_tag(0x85, buf, 1, p, 8, &p);
824
0
  else {
825
0
    buf[1] = 0x00;
826
0
    buf[2] = 0x00;
827
0
    r = sc_asn1_put_tag(0x85, buf, 1, p, 8, &p);
828
0
  }
829
0
  if (r != SC_SUCCESS)
830
0
    return r;
831
  /* set ACs  */
832
0
  len = 9;
833
0
  r = cardos_acl_to_bytes(card, file, buf, &len);
834
0
  if (r != SC_SUCCESS)
835
0
    return r;
836
0
  r = sc_asn1_put_tag(0x86, buf, len, p, 18, &p);
837
0
  if (r != SC_SUCCESS)
838
0
    return r;
839
  /* finally set the length of the FCP */
840
0
  out[1] = p - out - 2;
841
842
0
  *outlen = p - out;
843
844
0
  return SC_SUCCESS;
845
0
}
846
847
static int cardos_create_file(sc_card_t *card, sc_file_t *file)
848
0
{
849
0
  int       r;
850
851
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
852
853
0
  if (card->type == SC_CARD_TYPE_CARDOS_GENERIC ||
854
0
      card->type == SC_CARD_TYPE_CARDOS_M4_01) {
855
0
    r = cardos_set_file_attributes(card, file);
856
0
    if (r != SC_SUCCESS)
857
0
      return r;
858
0
    return iso_ops->create_file(card, file);
859
0
  } else if (card->type == SC_CARD_TYPE_CARDOS_M4_2 ||
860
0
             card->type == SC_CARD_TYPE_CARDOS_M4_3 ||
861
0
       card->type == SC_CARD_TYPE_CARDOS_M4_2B ||
862
0
             card->type == SC_CARD_TYPE_CARDOS_M4_2C ||
863
0
       card->type == SC_CARD_TYPE_CARDOS_M4_4) {
864
0
    u8        sbuf[SC_MAX_APDU_BUFFER_SIZE];
865
0
    size_t    len = sizeof(sbuf);
866
0
    sc_apdu_t apdu;
867
868
0
    r = cardos_construct_fcp(card, file, sbuf, &len);
869
0
    if (r < 0) {
870
0
      sc_log(card->ctx,  "unable to create FCP");
871
0
      return r;
872
0
    }
873
874
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, 0x00);
875
0
    apdu.lc      = len;
876
0
    apdu.datalen = len;
877
0
    apdu.data    = sbuf;
878
879
0
    r = sc_transmit_apdu(card, &apdu);
880
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
881
882
0
    return sc_check_sw(card, apdu.sw1, apdu.sw2);
883
0
  } else
884
0
    return SC_ERROR_NOT_SUPPORTED;
885
0
}
886
887
/*
888
 * Restore the indicated SE
889
 */
890
static int
891
cardos_restore_security_env(sc_card_t *card, int se_num)
892
0
{
893
0
  sc_apdu_t apdu;
894
0
  int r;
895
896
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
897
898
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0, se_num);
899
0
  apdu.p1 = (card->type == SC_CARD_TYPE_CARDOS_CIE_V1 ? 0xF3 : 0x03);
900
901
0
  r = sc_transmit_apdu(card, &apdu);
902
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
903
904
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
905
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
906
907
0
  LOG_FUNC_RETURN(card->ctx, r);
908
0
}
909
910
/*
911
 * Set the security context
912
 * Things get a little messy here. It seems you cannot do any
913
 * crypto without a security environment - but there isn't really
914
 * a way to specify the security environment in PKCS15.
915
 * What I'm doing here (for now) is to assume that for a key
916
 * object with ID 0xNN there is always a corresponding SE object
917
 * with the same ID.
918
 * XXX Need to find out how the Aladdin drivers do it.
919
 */
920
static int
921
cardos_set_security_env(sc_card_t *card,
922
          const sc_security_env_t *env,
923
          int se_num)
924
0
{
925
0
  cardos_data_t* priv = (cardos_data_t*)card->drv_data;
926
0
  sc_apdu_t apdu;
927
0
  u8  data[9];
928
0
  int key_id, r;
929
930
0
  assert(card != NULL && env != NULL);
931
932
0
  if (!(env->flags & SC_SEC_ENV_KEY_REF_PRESENT) || env->key_ref_len != 1) {
933
0
    sc_log(card->ctx, "No or invalid key reference\n");
934
0
    return SC_ERROR_INVALID_ARGUMENTS;
935
0
  }
936
0
  priv->sec_env = env; /* pass on to crypto routines */
937
938
  /* key_ref includes card mechanism and key number
939
   * But newer cards appear to get this some other way,
940
   * We can use flags passed to know what OpenSC expects from the card
941
   * and have derived what these machanisums are.
942
   * Newer cards may change how this is done
943
   */
944
945
0
  key_id = env->key_ref[0];
946
947
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
948
0
  if (card->type == SC_CARD_TYPE_CARDOS_CIE_V1) {
949
0
    cardos_restore_security_env(card, 0x30);
950
0
    apdu.p1 = 0xF1;
951
0
  } else {
952
0
    apdu.p1 = 0x41;
953
0
  }
954
0
  switch (env->operation) {
955
0
  case SC_SEC_OPERATION_DECIPHER:
956
0
    apdu.p2 = 0xB8;
957
0
    break;
958
0
  case SC_SEC_OPERATION_SIGN:
959
0
    apdu.p2 = 0xB6;
960
0
    break;
961
0
  default:
962
0
    return SC_ERROR_INVALID_ARGUMENTS;
963
0
  }
964
965
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
966
    /* some cards appear to have key_id be both Cryptographic mechanism reference 4 bits
967
     * and key_ref 4 bits. But this limits card to 16 keys.
968
     * TODO may need to be looked at at a later time
969
     */
970
    /* Private key reference */
971
0
    data[0] = 0x84;
972
0
    data[1] = 0x01;
973
0
    data[2] = key_id & 0x0F;
974
    /* Usage qualifier byte */
975
0
    data[3] = 0x95;
976
0
    data[4] = 0x01;
977
0
    data[5] = 0x40;
978
0
    apdu.lc = apdu.datalen = 6;
979
0
    if (key_id & 0xF0) {
980
      /* Cryptographic mechanism reference */
981
0
      data[6] = 0x80;
982
0
      data[7] = 0x01;
983
0
      data[8] = key_id & 0xF0;
984
0
      apdu.lc = apdu.datalen = 9;
985
0
    } else if ((env->operation == SC_SEC_OPERATION_SIGN
986
0
            && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01)
987
0
          || (env->operation == SC_SEC_OPERATION_DECIPHER
988
0
            && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02)) {
989
      /* TODO this may only apply to c903 cards */
990
      /* TODO or only for cards without any supported_algos or EIDComplient only */
991
0
      data[6] = 0x80;
992
0
      data[7] = 0x01;
993
0
      data[8] = 0x10;
994
0
      apdu.lc = apdu.datalen = 9;
995
0
    } else if (priv->sec_env->algorithm_flags & SC_ALGORITHM_ECDSA_RAW) {
996
0
      data[6] = 0x80;
997
0
      data[7] = 0x01;
998
0
      data[8] = 0x30;
999
0
      apdu.lc = apdu.datalen = 9;
1000
0
    }
1001
0
  } else {
1002
0
    data[0] = 0x83;
1003
0
    data[1] = 0x01;
1004
0
    data[2] = key_id;
1005
0
    apdu.lc = apdu.datalen = 3;
1006
0
  }
1007
0
  apdu.data = data;
1008
1009
0
  r = sc_transmit_apdu(card, &apdu);
1010
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1011
1012
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1013
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1014
1015
0
  do   {
1016
0
    const struct sc_supported_algo_info* algorithm_info = env->supported_algos;
1017
0
    int i=0;
1018
0
    int algorithm_id_count = 0;
1019
1020
0
    for(i=0;i<SC_MAX_SUPPORTED_ALGORITHMS;++i)  {
1021
0
      struct sc_supported_algo_info alg = algorithm_info[i];
1022
1023
0
      if(alg.operations & SC_PKCS15_ALGO_OP_COMPUTE_SIGNATURE)  {
1024
0
        unsigned int algorithm_id = alg.algo_ref;
1025
1026
0
        sc_log(card->ctx, "is signature");
1027
0
        sc_log(card->ctx, "Adding ID %d at index %d", algorithm_id, algorithm_id_count);
1028
0
        priv->algorithm_ids_in_tokeninfo[algorithm_id_count++] = algorithm_id;
1029
0
      }
1030
0
      sc_log(card->ctx, "reference=%d, mechanism=%d, operations=%d, algo_ref=%d",
1031
0
          alg.reference, alg.mechanism, alg.operations, alg.algo_ref);
1032
0
    }
1033
0
    priv -> algorithm_ids_in_tokeninfo_count = algorithm_id_count;
1034
0
  } while (0);
1035
1036
0
  LOG_FUNC_RETURN(card->ctx, r);
1037
0
}
1038
1039
/*
1040
 * Compute digital signature
1041
 */
1042
1043
/* internal function to do the actual signature computation */
1044
static int
1045
do_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
1046
         u8 *out, size_t outlen)
1047
0
{
1048
0
  /* cardos_data_t* priv = (cardos_data_t*)card->drv_dataa */;
1049
0
  int r;
1050
0
  sc_apdu_t apdu;
1051
1052
  /* INS: 0x2A  PERFORM SECURITY OPERATION
1053
   * P1:  0x9E  Resp: Digital Signature
1054
   * P2:  0x9A  Cmd: Input for Digital Signature */
1055
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4, 0x2A, 0x9E, 0x9A);
1056
0
  apdu.resp    = out;
1057
0
  apdu.le      = outlen;
1058
0
  apdu.resplen = outlen;
1059
1060
0
  apdu.data    = data;
1061
0
  apdu.lc      = datalen;
1062
0
  apdu.datalen = datalen;
1063
0
  iso7816_fixup_transceive_length(card, &apdu);
1064
0
  r = sc_transmit_apdu(card, &apdu);
1065
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1066
1067
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)
1068
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)apdu.resplen);
1069
0
  else
1070
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
1071
0
}
1072
1073
static int
1074
cardos_compute_signature(sc_card_t *card, const u8 *data, size_t datalen,
1075
       u8 *out, size_t outlen)
1076
0
{
1077
0
  cardos_data_t* priv;
1078
0
  int    r;
1079
0
  sc_context_t *ctx;
1080
0
  int do_rsa_pure_sig = 0;
1081
0
  int do_rsa_sig = 0;
1082
0
  size_t i;
1083
1084
1085
0
  assert(card != NULL && data != NULL && out != NULL);
1086
0
  ctx = card->ctx;
1087
0
  priv = (cardos_data_t*)card->drv_data;
1088
0
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
1089
1090
  /* sec_env has algorithm_flags set from sc_get_encoding_flags sec_flags
1091
   * If flags are set correctly we don't need to test anything
1092
   * TODO this assumes RSA is  PSS, PKCS1 or RAW and we are passing
1093
   * the correct data. Should work for ECDSA too.
1094
   * use for V5 cards and TODO should for older cards too
1095
   */
1096
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
1097
1098
0
    r = do_compute_signature(card, data, datalen, out, outlen);
1099
0
    LOG_FUNC_RETURN(ctx, r);
1100
0
  }
1101
1102
  /* There are two ways to create a signature, depending on the way,
1103
   * the key was created: RSA_SIG and RSA_PURE_SIG.
1104
   * We can use the following reasoning, to determine the correct operation:
1105
   * 1. We check for several caps flags (as set in card->caps), to prevent generating
1106
   *    invalid signatures with duplicated hash prefixes with some cards
1107
   * 2. Use the information from AlgorithmInfo of the TokenInfo file.
1108
   *    This information is parsed in set_security_env and stored in a static variable.
1109
   *    The problem is, that that information is only available for the whole token and not
1110
        for a specific key, so if both operations are present, we can only do trial and error
1111
   *
1112
   * The Algorithm IDs for RSA_SIG are 0x86 and 0x88, those for RSA_PURE_SIG 0x8c and 0x8a
1113
   * (According to http://www.opensc-project.org/pipermail/opensc-devel/2010-September/014912.html
1114
   *   and www.crysys.hu/infsec/M40_Manual_E_2001_10.pdf)
1115
   */
1116
1117
  /* check the the algorithmIDs from the AlgorithmInfo */
1118
0
  for (i = 0; i < priv->algorithm_ids_in_tokeninfo_count; ++i) {
1119
0
    unsigned int id = priv->algorithm_ids_in_tokeninfo[i];
1120
0
    if (id == 0x86 || id == 0x88) {
1121
0
      do_rsa_sig = 1;
1122
0
    } else if (id == 0x8C || id == 0x8A) {
1123
0
      do_rsa_pure_sig = 1;
1124
0
    }
1125
0
  }
1126
1127
  /* check if any operation was selected */
1128
0
  if (do_rsa_sig == 0 && do_rsa_pure_sig == 0) {
1129
    /* no operation selected. we just have to try both,
1130
     * for the lack of any better reasoning */
1131
0
    sc_log(ctx, "I was unable to determine, whether this key can be used with RSA_SIG or RSA_PURE_SIG. I will just try both.");
1132
0
    do_rsa_sig = 1;
1133
0
    do_rsa_pure_sig = 1;
1134
0
  }
1135
1136
0
  if(do_rsa_pure_sig == 1){
1137
0
    sc_log(ctx, "trying RSA_PURE_SIG (padded DigestInfo)");
1138
0
    r = do_compute_signature(card, data, datalen, out, outlen);
1139
0
    if (r >= SC_SUCCESS)
1140
0
      LOG_FUNC_RETURN(ctx, r);
1141
0
  }
1142
1143
0
  if(do_rsa_sig == 1){
1144
0
    u8 *buf = malloc(datalen);
1145
0
    u8 *stripped_data = buf;
1146
0
    size_t stripped_datalen = datalen;
1147
0
    if (!buf)
1148
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
1149
0
    memcpy(buf, data, datalen);
1150
0
    data = buf;
1151
1152
0
    sc_log(ctx, "trying RSA_SIG (just the DigestInfo)");
1153
1154
    /* remove padding: first try pkcs1 bt01 padding */
1155
0
    r = sc_pkcs1_strip_01_padding(ctx, data, datalen, stripped_data, &stripped_datalen);
1156
0
    if (r != SC_SUCCESS) {
1157
      /* no pkcs1 bt01 padding => let's try zero padding
1158
       * This can only work if the data tbs doesn't have a
1159
       * leading 0 byte.  */
1160
0
      while (*stripped_data == 0 && stripped_datalen != 0) {
1161
0
        ++stripped_data;
1162
0
        --stripped_datalen;
1163
0
      }
1164
0
    }
1165
0
    sc_log(ctx, "trying to sign raw hash value with prefix");
1166
0
    r = do_compute_signature(card, stripped_data, stripped_datalen, out, outlen);
1167
0
    if (r >= SC_SUCCESS) {
1168
0
      free(buf);
1169
0
      LOG_FUNC_RETURN(ctx, r);
1170
0
    }
1171
0
    sc_log(ctx, "trying to sign stripped raw hash value (card is responsible for prefix)");
1172
0
    r = sc_pkcs1_strip_digest_info_prefix(NULL, stripped_data, stripped_datalen, stripped_data, &stripped_datalen);
1173
0
    if (r != SC_SUCCESS) {
1174
0
      free(buf);
1175
0
      LOG_FUNC_RETURN(ctx, r);
1176
0
    }
1177
0
    r = do_compute_signature(card, stripped_data, stripped_datalen, out, outlen);
1178
0
    free(buf);
1179
0
    LOG_FUNC_RETURN(ctx, r);
1180
0
  }
1181
1182
0
  LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
1183
0
}
1184
1185
static int
1186
cardos_decipher(struct sc_card *card,
1187
    const u8 * crgram, size_t crgram_len,
1188
    u8 * out, size_t outlen)
1189
0
{
1190
0
  cardos_data_t* priv = (cardos_data_t*)card->drv_data;
1191
0
  int r;
1192
0
  size_t card_max_send_size = card->max_send_size;
1193
0
  size_t reader_max_send_size = card->reader->max_send_size;
1194
1195
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1196
1197
  /* 5.3 supports command chaining. Others may also
1198
   * card_max_send_size for 5.3 is already based on reader max_send_size */
1199
1200
0
  if (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
1201
1202
0
    r = iso_ops->decipher(card, crgram, crgram_len, out, outlen);
1203
    /*
1204
     * 5.3 supports RAW as well as PKCS1 and PSS
1205
     * description may strip padding if card supports it
1206
     * with cards that support RAW, it always appears to
1207
     * drop first 00 that is start of padding.
1208
     */
1209
1210
0
    if (r > 0 && priv->sec_env->algorithm_flags & SC_ALGORITHM_RSA_RAW) {
1211
0
      size_t rsize = r;
1212
      /* RSA RAW crgram_len == modlen */
1213
      /* removed padding is always > 1 byte */
1214
      /* add back missing leading zero if card dropped it */
1215
0
      if (rsize == crgram_len - 1 && rsize < outlen) {
1216
0
        memmove(out+1, out, rsize);
1217
0
        out[0] =0x00;
1218
0
        r++;
1219
0
      }
1220
0
    }
1221
1222
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
1223
0
  }
1224
1225
0
  if (sc_get_max_send_size(card) < crgram_len + 1) {
1226
    /* CardOS doesn't support chaining for PSO:DEC, so we just _hope_
1227
     * that both, the reader and the card are able to send enough data.
1228
     * (data is prefixed with 1 byte padding content indicator) */
1229
0
    card->max_send_size = crgram_len + 1;
1230
0
    card->reader->max_send_size = crgram_len + 1;
1231
0
  }
1232
1233
0
  r = iso_ops->decipher(card, crgram, crgram_len, out, outlen);
1234
1235
  /* reset whatever we've modified above */
1236
0
  card->max_send_size = card_max_send_size;
1237
0
  card->reader->max_send_size = reader_max_send_size;
1238
1239
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
1240
0
}
1241
1242
static int
1243
cardos_lifecycle_get(sc_card_t *card, int *mode)
1244
0
{
1245
0
  sc_apdu_t apdu;
1246
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
1247
0
  int   r;
1248
1249
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1250
1251
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x83);
1252
0
  apdu.cla = 0x00;
1253
0
  apdu.le = 256;
1254
0
  apdu.resplen = sizeof(rbuf);
1255
0
  apdu.resp = rbuf;
1256
1257
0
  r = sc_transmit_apdu(card, &apdu);
1258
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1259
1260
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1261
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1262
1263
0
  if (apdu.resplen < 1) {
1264
0
    LOG_TEST_RET(card->ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Lifecycle byte not in response");
1265
0
  }
1266
1267
0
  r = SC_SUCCESS;
1268
0
  switch (rbuf[0]) {
1269
0
  case 0x10:
1270
0
    *mode = SC_CARDCTRL_LIFECYCLE_USER;
1271
0
    break;
1272
0
  case 0x20:
1273
0
    *mode = SC_CARDCTRL_LIFECYCLE_ADMIN;
1274
0
    break;
1275
0
  case 0x34: /* MANUFACTURING */
1276
0
    *mode = SC_CARDCTRL_LIFECYCLE_OTHER;
1277
0
    break;
1278
0
  default:
1279
0
    sc_log(card->ctx,  "Unknown lifecycle byte %d", rbuf[0]);
1280
0
    r = SC_ERROR_INTERNAL;
1281
0
  }
1282
1283
0
  LOG_FUNC_RETURN(card->ctx, r);
1284
0
}
1285
1286
static int
1287
cardos_lifecycle_set(sc_card_t *card, int *mode)
1288
0
{
1289
0
  sc_apdu_t apdu;
1290
0
  int   r;
1291
1292
0
  int current;
1293
0
  int target;
1294
1295
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1296
1297
0
  target = *mode;
1298
1299
0
  r = cardos_lifecycle_get(card, &current);
1300
1301
0
  if (r != SC_SUCCESS)
1302
0
    return r;
1303
1304
0
  if (current == target || current == SC_CARDCTRL_LIFECYCLE_OTHER)
1305
0
    return SC_SUCCESS;
1306
1307
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x10, 0, 0);
1308
0
  apdu.cla = 0x80;
1309
0
  apdu.le = 0;
1310
0
  apdu.resplen = 0;
1311
0
  apdu.resp = NULL;
1312
1313
0
  r = sc_transmit_apdu(card, &apdu);
1314
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1315
1316
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1317
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1318
1319
0
  LOG_FUNC_RETURN(card->ctx, r);
1320
0
}
1321
1322
static int
1323
cardos_put_data_oci(sc_card_t *card,
1324
      struct sc_cardctl_cardos_obj_info *args)
1325
0
{
1326
0
  sc_apdu_t apdu;
1327
0
  int   r;
1328
1329
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1330
1331
0
  memset(&apdu, 0, sizeof(apdu));
1332
0
  apdu.cse = SC_APDU_CASE_3_SHORT;
1333
0
  apdu.cla = 0x00;
1334
0
  apdu.ins = 0xda;
1335
0
  apdu.p1  = 0x01;
1336
0
  apdu.p2  = 0x6e;
1337
0
  apdu.lc  = args->len;
1338
0
  apdu.data = args->data;
1339
0
  apdu.datalen = args->len;
1340
1341
0
  r = sc_transmit_apdu(card, &apdu);
1342
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1343
1344
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1345
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1346
1347
0
  LOG_FUNC_RETURN(card->ctx, r);
1348
0
}
1349
1350
static int
1351
cardos_put_data_seci(sc_card_t *card,
1352
      struct sc_cardctl_cardos_obj_info *args)
1353
0
{
1354
0
  sc_apdu_t apdu;
1355
0
  int   r;
1356
1357
0
  memset(&apdu, 0, sizeof(apdu));
1358
0
  apdu.cse = SC_APDU_CASE_3_SHORT;
1359
0
  apdu.cla = 0x00;
1360
0
  apdu.ins = 0xda;
1361
0
  apdu.p1  = 0x01;
1362
0
  apdu.p2  = 0x6d;
1363
0
  apdu.lc  = args->len;
1364
0
  apdu.data = args->data;
1365
0
  apdu.datalen = args->len;
1366
1367
0
  r = sc_transmit_apdu(card, &apdu);
1368
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1369
1370
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1371
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1372
1373
0
  return r;
1374
0
}
1375
1376
static int
1377
cardos_generate_key(sc_card_t *card,
1378
    struct sc_cardctl_cardos_genkey_info *args)
1379
0
{
1380
0
  sc_apdu_t apdu;
1381
0
  u8    data[8];
1382
0
  int   r;
1383
1384
0
  data[0] = 0x20;   /* store as PSO object */
1385
0
  data[1] = args->key_id;
1386
0
  data[2] = args->fid >> 8;
1387
0
  data[3] = args->fid & 0xff;
1388
0
  data[4] = 0;    /* additional Rabin Miller tests */
1389
0
  data[5] = 0x10;   /* length difference between p, q (bits) */
1390
0
  data[6] = 0;    /* default length of exponent, MSB */
1391
0
  data[7] = 0x20;   /* default length of exponent, LSB */
1392
1393
0
  memset(&apdu, 0, sizeof(apdu));
1394
0
  apdu.cse = SC_APDU_CASE_3_SHORT;
1395
0
  apdu.cla = 0x00;
1396
0
  apdu.ins = 0x46;
1397
0
  apdu.p1  = 0x00;
1398
0
  apdu.p2  = 0x00;
1399
0
  apdu.data= data;
1400
0
  apdu.datalen = apdu.lc = sizeof(data);
1401
1402
0
  r = sc_transmit_apdu(card, &apdu);
1403
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1404
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1405
0
  LOG_TEST_RET(card->ctx, r, "GENERATE_KEY failed");
1406
1407
0
  return r;
1408
0
}
1409
1410
static int cardos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
1411
0
{
1412
0
  int r;
1413
0
  sc_apdu_t apdu;
1414
0
  u8  rbuf[SC_MAX_APDU_BUFFER_SIZE];
1415
1416
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xca, 0x01, 0x81);
1417
0
  apdu.resp = rbuf;
1418
0
  apdu.resplen = sizeof(rbuf);
1419
0
  apdu.le   = 256;
1420
0
  r = sc_transmit_apdu(card, &apdu);
1421
0
  LOG_TEST_RET(card->ctx, r,  "APDU transmit failed");
1422
0
  if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
1423
0
    return SC_ERROR_INTERNAL;
1424
0
  if ((apdu.resplen == 8) && (card->type == SC_CARD_TYPE_CARDOS_V5_0 || card->type == SC_CARD_TYPE_CARDOS_V5_3)) {
1425
    /* cache serial number */
1426
0
    memcpy(card->serialnr.value, rbuf, 8);
1427
0
    card->serialnr.len = 8;
1428
0
  } else if (apdu.resplen == 32) {
1429
    /* cache serial number */
1430
0
    memcpy(card->serialnr.value, &rbuf[10], 6);
1431
0
    card->serialnr.len = 6;
1432
0
  } else {
1433
0
    sc_log(card->ctx,  "unexpected response to GET DATA serial"
1434
0
        " number\n");
1435
0
    return SC_ERROR_INTERNAL;
1436
0
  }
1437
  /* copy and return serial number */
1438
0
  memcpy(serial, &card->serialnr, sizeof(*serial));
1439
0
  return SC_SUCCESS;
1440
0
}
1441
1442
static int
1443
cardos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
1444
0
{
1445
0
  switch (cmd) {
1446
0
  case SC_CARDCTL_CARDOS_PUT_DATA_FCI:
1447
0
    break;
1448
0
  case SC_CARDCTL_CARDOS_PUT_DATA_OCI:
1449
0
    return cardos_put_data_oci(card,
1450
0
      (struct sc_cardctl_cardos_obj_info *) ptr);
1451
0
    break;
1452
0
  case SC_CARDCTL_CARDOS_PUT_DATA_SECI:
1453
0
    return cardos_put_data_seci(card,
1454
0
      (struct sc_cardctl_cardos_obj_info *) ptr);
1455
0
    break;
1456
0
  case SC_CARDCTL_CARDOS_GENERATE_KEY:
1457
0
    return cardos_generate_key(card,
1458
0
      (struct sc_cardctl_cardos_genkey_info *) ptr);
1459
0
  case  SC_CARDCTL_CARDOS_PASS_ALGO_FLAGS:
1460
0
    return cardos_pass_algo_flags(card,
1461
0
      (struct sc_cardctl_cardos_pass_algo_flags *) ptr);
1462
0
  case SC_CARDCTL_LIFECYCLE_GET:
1463
0
    return cardos_lifecycle_get(card, (int *) ptr);
1464
0
  case SC_CARDCTL_LIFECYCLE_SET:
1465
0
    return cardos_lifecycle_set(card, (int *) ptr);
1466
0
  case SC_CARDCTL_GET_SERIALNR:
1467
0
    return cardos_get_serialnr(card, (sc_serial_number_t *)ptr);
1468
0
  }
1469
0
  return SC_ERROR_NOT_SUPPORTED;
1470
0
}
1471
1472
/*
1473
 * The 0x80 thing tells the card it's okay to search parent
1474
 * directories as well for the referenced object.
1475
 * Unfortunately, it doesn't seem to work without this flag :-/
1476
 */
1477
static int
1478
cardos_pin_cmd(struct sc_card *card, struct sc_pin_cmd_data *data,
1479
     int *tries_left)
1480
0
{
1481
0
  struct sc_context *ctx = card->ctx;
1482
0
  int rv;
1483
1484
0
  LOG_FUNC_CALLED(card->ctx);
1485
1486
0
  data->flags |= SC_PIN_CMD_NEED_PADDING;
1487
0
  data->pin_reference |= 0x80;
1488
1489
0
  sc_log(ctx, "PIN_CMD(cmd:%i, ref:%i)", data->cmd, data->pin_reference);
1490
0
  sc_log(ctx,
1491
0
         "PIN1(max:%"SC_FORMAT_LEN_SIZE_T"u, min:%"SC_FORMAT_LEN_SIZE_T"u)",
1492
0
         data->pin1.max_length, data->pin1.min_length);
1493
0
  sc_log(ctx,
1494
0
         "PIN2(max:%"SC_FORMAT_LEN_SIZE_T"u, min:%"SC_FORMAT_LEN_SIZE_T"u)",
1495
0
         data->pin2.max_length, data->pin2.min_length);
1496
1497
  /* FIXME: the following values depend on what pin length was
1498
   * used when creating the BS objects */
1499
0
  if (data->pin1.max_length == 0)
1500
0
    data->pin1.max_length = 8;
1501
0
  if (data->pin2.max_length == 0)
1502
0
    data->pin2.max_length = 8;
1503
1504
0
  rv = iso_ops->pin_cmd(card, data, tries_left);
1505
0
  LOG_FUNC_RETURN(ctx, rv);
1506
0
}
1507
1508
1509
static int
1510
cardos_logout(sc_card_t *card)
1511
0
{
1512
0
  if (card->type == SC_CARD_TYPE_CARDOS_M4_01
1513
0
        || card->type == SC_CARD_TYPE_CARDOS_M4_2
1514
0
        || card->type == SC_CARD_TYPE_CARDOS_M4_2B
1515
0
        || card->type == SC_CARD_TYPE_CARDOS_M4_2C
1516
0
        || card->type == SC_CARD_TYPE_CARDOS_M4_3
1517
0
        || card->type == SC_CARD_TYPE_CARDOS_M4_4
1518
0
      || card->type == SC_CARD_TYPE_CARDOS_V5_0
1519
0
      || card->type == SC_CARD_TYPE_CARDOS_V5_3) {
1520
0
    sc_apdu_t apdu;
1521
0
    int       r;
1522
0
    sc_path_t path;
1523
1524
0
    sc_format_path("3F00", &path);
1525
0
    r = sc_select_file(card, &path, NULL);
1526
0
    if (r != SC_SUCCESS)
1527
0
      return r;
1528
1529
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0xEA, 0x00, 0x00);
1530
0
    apdu.cla = 0x80;
1531
1532
0
    r = sc_transmit_apdu(card, &apdu);
1533
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1534
1535
0
    return sc_check_sw(card, apdu.sw1, apdu.sw2);
1536
0
  } else
1537
0
    return SC_ERROR_NOT_SUPPORTED;
1538
0
}
1539
1540
/* eToken R2 supports WRITE_BINARY, PRO Tokens support UPDATE_BINARY */
1541
1542
static struct sc_card_driver * sc_get_driver(void)
1543
3.19k
{
1544
3.19k
  if (iso_ops == NULL)
1545
1
    iso_ops = sc_get_iso7816_driver()->ops;
1546
3.19k
  cardos_ops = *iso_ops;
1547
3.19k
  cardos_ops.match_card = cardos_match_card;
1548
3.19k
  cardos_ops.init = cardos_init;
1549
3.19k
  cardos_ops.finish = cardos_finish;
1550
3.19k
  cardos_ops.select_file = cardos_select_file;
1551
3.19k
  cardos_ops.create_file = cardos_create_file;
1552
3.19k
  cardos_ops.set_security_env = cardos_set_security_env;
1553
3.19k
  cardos_ops.restore_security_env = cardos_restore_security_env;
1554
3.19k
  cardos_ops.compute_signature = cardos_compute_signature;
1555
3.19k
  cardos_ops.decipher = cardos_decipher;
1556
1557
3.19k
  cardos_ops.list_files = cardos_list_files;
1558
3.19k
  cardos_ops.check_sw = cardos_check_sw;
1559
3.19k
  cardos_ops.card_ctl = cardos_card_ctl;
1560
3.19k
  cardos_ops.pin_cmd = cardos_pin_cmd;
1561
3.19k
  cardos_ops.logout  = cardos_logout;
1562
1563
3.19k
  return &cardos_drv;
1564
3.19k
}
1565
1566
#if 1
1567
struct sc_card_driver * sc_get_cardos_driver(void)
1568
3.19k
{
1569
3.19k
  return sc_get_driver();
1570
3.19k
}
1571
#endif