Coverage Report

Created: 2026-06-10 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-setcos.c
Line
Count
Source
1
/*
2
 * card-setcos.c: Support for PKI cards by Setec
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 * Copyright (C) 2005  Antti Tapaninen <aet@cc.hut.fi>
6
 * Copyright (C) 2005  Zetes
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU Lesser General Public
10
 * License as published by the Free Software Foundation; either
11
 * version 2.1 of the License, or (at your option) any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * Lesser General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21
 */
22
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26
27
#include <stdlib.h>
28
#include <string.h>
29
30
#include "internal.h"
31
#include "asn1.h"
32
#include "cardctl.h"
33
34
static const struct sc_atr_table setcos_atrs[] = {
35
    /* some Nokia branded SC */
36
    {"3B:1F:11:00:67:80:42:46:49:53:45:10:52:66:FF:81:90:00",     NULL,               NULL, SC_CARD_TYPE_SETCOS_GENERIC, 0, NULL},
37
    /* RSA SecurID 3100 */
38
    {"3B:9F:94:40:1E:00:67:16:43:46:49:53:45:10:52:66:FF:81:90:00", NULL,                     NULL, SC_CARD_TYPE_SETCOS_PKI,     0, NULL},
39
    /* Swedish NIDEL card */
40
    {"3b:9f:94:80:1f:c3:00:68:10:44:05:01:46:49:53:45:31:c8:07:90:00:18", NULL,                   NULL, SC_CARD_TYPE_SETCOS_NIDEL,   0, NULL},
41
    /* Setcos 4.4.1 */
42
    {"3b:9f:94:80:1f:c3:00:68:11:44:05:01:46:49:53:45:31:c8:00:00:00:00", "ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00", NULL, SC_CARD_TYPE_SETCOS_44,   0, NULL},
43
    {NULL,                NULL,               NULL, 0,            0, NULL}
44
};
45
46
5.61k
#define SETCOS_IS_EID_APPLET(card) ((card)->type == SC_CARD_TYPE_SETCOS_EID_V2_0 || (card)->type == SC_CARD_TYPE_SETCOS_EID_V2_1)
47
48
/* Setcos 4.4 Life Cycle Status Integer  */
49
18
#define SETEC_LCSI_CREATE      0x01
50
#define SETEC_LCSI_INIT        0x03
51
54
#define SETEC_LCSI_ACTIVATED   0x07
52
#define SETEC_LCSI_DEACTIVATE  0x06
53
#define SETEC_LCSI_TEMINATE    0x0F /* MF only  */
54
55
static struct sc_card_operations setcos_ops;
56
static struct sc_card_driver setcos_drv = {
57
  "Setec cards",
58
  "setcos",
59
  &setcos_ops,
60
  NULL, 0, NULL
61
};
62
63
static int match_hist_bytes(sc_card_t *card, const char *str, size_t len)
64
859
{
65
859
  const char *src = (const char *) card->reader->atr_info.hist_bytes;
66
859
  size_t srclen = card->reader->atr_info.hist_bytes_len;
67
859
  size_t offset = 0;
68
69
859
  if (len == 0)
70
859
    len = strlen(str);
71
859
  if (srclen < len)
72
720
    return 0;
73
1.11k
  while (srclen - offset > len) {
74
988
    if (memcmp(src + offset, str, len) == 0) {
75
12
      return 1;
76
12
    }
77
976
    offset++;
78
976
  }
79
127
  return 0;
80
139
}
81
82
static int setcos_match_card(sc_card_t *card)
83
862
{
84
862
  sc_apdu_t apdu;
85
862
  u8 buf[6];
86
862
  int i;
87
88
862
  i = _sc_match_atr(card, setcos_atrs, &card->type);
89
862
  if (i < 0) {
90
859
    if (match_hist_bytes(card, "FISE", 0)) {
91
12
      card->type = SC_CARD_TYPE_SETCOS_GENERIC;
92
12
      return 1;
93
12
    }
94
    /* Check if it's a EID2.x applet by reading the version info */
95
847
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0xDF, 0x30);
96
847
    apdu.cla = 0x00;
97
847
    apdu.resp = buf;
98
847
    apdu.resplen = 5;
99
847
    apdu.le = 5;
100
847
    i = sc_transmit_apdu(card, &apdu);
101
847
    if (i == 0 && apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && apdu.resplen == 5) {
102
210
      if (memcmp(buf, "v2.0", 4) == 0)
103
29
        card->type = SC_CARD_TYPE_SETCOS_EID_V2_0;
104
181
      else if (memcmp(buf, "v2.1", 4) == 0)
105
111
        card->type = SC_CARD_TYPE_SETCOS_EID_V2_1;
106
70
      else {
107
70
        buf[sizeof(buf) - 1] = '\0';
108
70
        sc_log(card->ctx,  "SetCOS EID applet %s is not supported", (char *) buf);
109
70
        return 0;
110
70
      }
111
140
      return 1;
112
210
    }
113
114
637
    return 0;
115
847
  }
116
3
  card->flags = setcos_atrs[i].flags;
117
3
  return 1;
118
862
}
119
120
static int select_pkcs15_app(sc_card_t * card)
121
0
{
122
0
  sc_path_t app;
123
0
  int r;
124
125
  /* Regular PKCS#15 AID */
126
0
  sc_format_path("A000000063504B43532D3135", &app);
127
0
  app.type = SC_PATH_TYPE_DF_NAME;
128
0
  r = sc_select_file(card, &app, NULL);
129
0
  return r;
130
0
}
131
132
static int setcos_init(sc_card_t *card)
133
155
{
134
155
  card->name = "SetCOS";
135
136
  /* Handle unknown or forced cards */
137
155
  if (card->type < 0) {
138
0
    card->type = SC_CARD_TYPE_SETCOS_GENERIC;
139
0
  }
140
141
155
  switch (card->type) {
142
0
  case SC_CARD_TYPE_SETCOS_NIDEL:
143
0
    card->cla = 0x00;
144
0
    select_pkcs15_app(card);
145
0
    if (card->flags & SC_CARD_FLAG_RNG)
146
0
      card->caps |= SC_CARD_CAP_RNG;
147
0
    break;
148
3
  case SC_CARD_TYPE_SETCOS_44:
149
32
  case SC_CARD_TYPE_SETCOS_EID_V2_0:
150
143
  case SC_CARD_TYPE_SETCOS_EID_V2_1:
151
143
    card->cla = 0x00;
152
143
    card->caps |= SC_CARD_CAP_USE_FCI_AC;
153
143
    card->caps |= SC_CARD_CAP_RNG;
154
143
    card->caps |= SC_CARD_CAP_APDU_EXT;
155
143
    break;
156
12
  default:
157
    /* XXX: Get SetCOS version */
158
12
    card->cla = 0x80; /* SetCOS 4.3.x */
159
    /* State that we have an RNG */
160
12
    card->caps |= SC_CARD_CAP_RNG;
161
12
    break;
162
155
  }
163
164
155
  switch (card->type) {
165
0
  case SC_CARD_TYPE_SETCOS_PKI: {
166
0
    unsigned long flags;
167
168
0
    flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1;
169
0
    flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
170
171
0
    _sc_card_add_rsa_alg(card, 1024, flags, 0);
172
0
    _sc_card_add_rsa_alg(card, 2048, flags, 0);
173
0
  } break;
174
3
  case SC_CARD_TYPE_SETCOS_44:
175
3
  case SC_CARD_TYPE_SETCOS_NIDEL:
176
32
  case SC_CARD_TYPE_SETCOS_EID_V2_0:
177
143
  case SC_CARD_TYPE_SETCOS_EID_V2_1:
178
143
    {
179
143
      unsigned long flags;
180
181
143
      flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1;
182
143
      flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
183
143
      flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
184
185
143
      _sc_card_add_rsa_alg(card, 512, flags, 0);
186
143
      _sc_card_add_rsa_alg(card, 768, flags, 0);
187
143
      _sc_card_add_rsa_alg(card, 1024, flags, 0);
188
143
      _sc_card_add_rsa_alg(card, 2048, flags, 0);
189
143
    }
190
143
    break;
191
155
  }
192
155
  return 0;
193
155
}
194
195
static const struct sc_card_operations *iso_ops = NULL;
196
197
static int setcos_construct_fci_44(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen)
198
35
{
199
35
  u8 *p = out;
200
35
  u8 buf[64];
201
35
  const u8 *pin_key_info;
202
35
  int len;
203
204
  /* Command */
205
35
  *p++ = 0x6F;
206
35
  p++;
207
208
  /* Size (set to 0 for keys/PINs on a Java card) */
209
35
  if (SETCOS_IS_EID_APPLET(card) &&
210
35
      (file->type == SC_FILE_TYPE_INTERNAL_EF ||
211
34
       (file->type == SC_FILE_TYPE_WORKING_EF && file->ef_structure == 0x22)))
212
1
        buf[0] = buf[1] = 0x00;
213
34
  else {
214
34
    buf[0] = (file->size >> 8) & 0xFF;
215
34
    buf[1] = file->size & 0xFF;
216
34
  }
217
35
  sc_asn1_put_tag(0x81, buf, 2, p, *outlen - (p - out), &p);
218
219
  /* Type */
220
35
  if (file->type_attr_len) {
221
0
    memcpy(buf, file->type_attr, file->type_attr_len);
222
0
    sc_asn1_put_tag(0x82, buf, file->type_attr_len, p, *outlen - (p - out), &p);
223
35
  } else {
224
35
    u8  bLen = 1;
225
226
35
    buf[0] = file->shareable ? 0x40 : 0;
227
35
    switch (file->type) {
228
1
    case SC_FILE_TYPE_INTERNAL_EF:       /* RSA keyfile */
229
1
      buf[0] = 0x11;
230
1
      break;
231
15
    case SC_FILE_TYPE_WORKING_EF:
232
15
      if (file->ef_structure == 0x22) {   /* pin-file */
233
0
        buf[0] = 0x0A;        /* EF linear fixed EF for ISF keys */
234
0
        if (SETCOS_IS_EID_APPLET(card))
235
0
          bLen = 1;
236
0
        else {
237
          /* Setcos V4.4 */
238
0
          bLen = 5;
239
0
          buf[1] = 0x41;        /* fixed */
240
0
          buf[2] = file->record_length >> 8;  /* 2 byte record length  */
241
0
          buf[3] = file->record_length & 0xFF;
242
0
          buf[4] = file->size / file->record_length; /* record count */
243
0
        }
244
15
      } else {
245
15
        buf[0] |= file->ef_structure & 7; /* set file-type, only for EF, not for DF objects  */
246
15
      }
247
15
      break;
248
16
    case SC_FILE_TYPE_DF:
249
16
      buf[0] = 0x38;
250
16
      break;
251
3
    default:
252
3
      return SC_ERROR_NOT_SUPPORTED;
253
35
    }
254
32
    sc_asn1_put_tag(0x82, buf, bLen, p, *outlen - (p - out), &p);
255
32
  }
256
257
  /* File ID */
258
32
  buf[0] = (file->id >> 8) & 0xFF;
259
32
  buf[1] = file->id & 0xFF;
260
32
  sc_asn1_put_tag(0x83, buf, 2, p, *outlen - (p - out), &p);
261
262
  /* DF name */
263
32
  if (file->type == SC_FILE_TYPE_DF) {
264
16
    if (file->name[0] != 0)
265
1
      sc_asn1_put_tag(0x84, (u8 *) file->name, file->namelen, p, *outlen - (p - out), &p);
266
15
    else { /* Name required -> take the FID if not specified */
267
15
      buf[0] = (file->id >> 8) & 0xFF;
268
15
      buf[1] = file->id & 0xFF;
269
15
      sc_asn1_put_tag(0x84, buf, 2, p, *outlen - (p - out), &p);
270
15
    }
271
16
  }
272
273
  /* Security Attributes */
274
32
  memcpy(buf, file->sec_attr, file->sec_attr_len);
275
32
  sc_asn1_put_tag(0x86, buf, file->sec_attr_len, p, *outlen - (p - out), &p);
276
277
  /* Life cycle status */
278
32
  if (file->prop_attr_len) {
279
32
    memcpy(buf, file->prop_attr, file->prop_attr_len);
280
32
    sc_asn1_put_tag(0x8A, buf, file->prop_attr_len, p, *outlen - (p - out), &p);
281
32
  }
282
283
  /* PIN definitions */
284
32
  if (file->type == SC_FILE_TYPE_DF) {
285
16
    if (card->type == SC_CARD_TYPE_SETCOS_EID_V2_1) {
286
9
      pin_key_info = (const u8*)"\xC1\x04\x81\x82\x83\x84";
287
9
      len = 6;
288
9
    }
289
7
    else if (card->type == SC_CARD_TYPE_SETCOS_EID_V2_0) {
290
7
      pin_key_info = (const u8*)"\xC1\x04\x81\x82"; /* Max 2 PINs supported */
291
7
      len = 4;
292
7
    }
293
0
    else {
294
      /* Pin/key info: define 4 pins, no keys */
295
0
      if(file->path.len == 2)
296
0
        pin_key_info = (const u8*)"\xC1\x04\x81\x82\x83\x84\xC2\x00"; /* root-MF: use local pin-file */
297
0
      else
298
0
        pin_key_info = (const u8 *)"\xC1\x04\x01\x02\x03\x04\xC2\x00"; /* sub-DF: use parent pin-file in root-MF */
299
0
      len = 8;
300
0
    }
301
16
    sc_asn1_put_tag(0xA5, pin_key_info, len, p, *outlen - (p - out), &p);
302
16
  }
303
304
  /* Length */
305
32
  out[1] = p - out - 2;
306
307
32
  *outlen = p - out;
308
32
  return 0;
309
35
}
310
311
static int setcos_construct_fci(sc_card_t *card, const sc_file_t *file, u8 *out, size_t *outlen)
312
37
{
313
37
  if (card->type == SC_CARD_TYPE_SETCOS_44 ||
314
37
      card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
315
37
      SETCOS_IS_EID_APPLET(card))
316
35
    return setcos_construct_fci_44(card, file, out, outlen);
317
2
  else
318
2
    return iso_ops->construct_fci(card, file, out, outlen);
319
37
}
320
321
static u8 acl_to_byte(const sc_acl_entry_t *e)
322
12
{
323
12
  switch (e->method) {
324
3
  case SC_AC_NONE:
325
3
    return 0x00;
326
1
  case SC_AC_CHV:
327
1
    switch (e->key_ref) {
328
0
    case 1:
329
0
      return 0x01;
330
0
      break;
331
0
    case 2:
332
0
      return 0x02;
333
0
      break;
334
1
    default:
335
1
      return 0x00;
336
1
    }
337
0
    break;
338
0
  case SC_AC_TERM:
339
0
    return 0x04;
340
8
  case SC_AC_NEVER:
341
8
    return 0x0F;
342
12
  }
343
0
  return 0x00;
344
12
}
345
346
static unsigned int acl_to_byte_44(const struct sc_acl_entry *e, u8* p_bNumber)
347
228
{
348
  /* Handle special fixed values */
349
228
  if (e == (sc_acl_entry_t *) 1)           /* SC_AC_NEVER */
350
5
    return SC_AC_NEVER;
351
223
  else if ((e == (sc_acl_entry_t *) 2) ||  /* SC_AC_NONE */
352
64
           (e == (sc_acl_entry_t *) 3) ||  /* SC_AC_UNKNOWN */
353
64
           (e == (sc_acl_entry_t *) 0))
354
159
    return SC_AC_NONE;
355
356
  /* Handle standard values */
357
64
  *p_bNumber = e->key_ref;
358
64
  return(e->method);
359
228
}
360
361
/* If pin is present in the pins list, return it's index.
362
 * If it's not yet present, add it to the list and return the index. */
363
static int setcos_pin_index_44(int *pins, int len, int pin)
364
61
{
365
61
  int i;
366
77
  for (i = 0; i < len; i++) {
367
77
    if (pins[i] == pin)
368
34
      return i;
369
43
    if (pins[i] == -1) {
370
27
      pins[i] = pin;
371
27
      return i;
372
27
    }
373
43
  }
374
0
  if (i == len)
375
0
    return SC_ERROR_INTERNAL;
376
0
  return 0;
377
0
}
378
379
/* The ACs are always for the SETEC_LCSI_ACTIVATED state, even if
380
 * we have to create the file in the SC_FILE_STATUS_INITIALISATION state. */
381
static int setcos_create_file_44(sc_card_t *card, sc_file_t *file)
382
36
{
383
36
  const u8 bFileStatus = file->status == SC_FILE_STATUS_CREATION ?
384
18
    SETEC_LCSI_CREATE : SETEC_LCSI_ACTIVATED;
385
36
  u8 bCommands_always = 0;
386
36
  int pins[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
387
36
  u8 bCommands_pin[sizeof(pins)/sizeof(pins[0])]; /* both 7 entries big */
388
36
  u8 bCommands_key = 0;
389
36
  u8 bNumber = 0;
390
36
  u8 bKeyNumber = 0;
391
36
  unsigned int bMethod = 0;
392
393
  /* -1 means RFU */
394
36
  const int df_idx[8] = {  /* byte 1 = OpenSC type of AC Bit0,  byte 2 = OpenSC type of AC Bit1 ...*/
395
36
    SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE,
396
36
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
397
36
    SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1};
398
36
  const int ef_idx[8] = {  /* note: SC_AC_OP_SELECT to be ignored, actually RFU */
399
36
    SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
400
36
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
401
36
    -1, SC_AC_OP_ERASE, -1};
402
36
  const int efi_idx[8] = {  /* internal EF used for RSA keys */
403
36
    SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE,
404
36
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
405
36
    -1, SC_AC_OP_ERASE, -1};
406
407
  /* Set file creation status  */
408
36
  sc_file_set_prop_attr(file, &bFileStatus, 1);
409
410
  /* Build ACL from local structure = get AC for each operation group */
411
36
  if (file->sec_attr_len == 0) {
412
36
    const int* p_idx;
413
36
    int        i;
414
36
    int        len = 0;
415
36
    u8         bBuf[64];
416
417
    /* Get specific operation groups for specified file-type */
418
36
    switch (file->type){
419
16
    case SC_FILE_TYPE_DF:           /* DF */
420
16
      p_idx = df_idx;
421
16
      break;
422
1
    case SC_FILE_TYPE_INTERNAL_EF:  /* EF for RSA keys */
423
1
      p_idx = efi_idx;
424
1
      break;
425
19
    default:                        /* SC_FILE_TYPE_WORKING_EF */
426
19
      p_idx = ef_idx;
427
19
      break;
428
36
    }
429
430
    /* Get enabled commands + required Keys/Pins  */
431
36
    memset(bCommands_pin, 0, sizeof(bCommands_pin));
432
317
    for (i = 7; i >= 0; i--) {  /* for each AC Setcos operation */
433
282
      int pin_index;
434
282
      bCommands_always <<= 1;
435
282
      bCommands_key <<= 1;
436
437
282
      if (p_idx[i] == -1)  /* -1 means that bit is RFU -> set to 0 */
438
55
        continue;
439
440
227
      bMethod = acl_to_byte_44(file->acl[ p_idx[i] ], &bNumber);
441
      /* Convert to OpenSc-index, convert to pin/key number */
442
227
      switch(bMethod){
443
158
      case SC_AC_NONE:     /* always allowed */
444
158
        bCommands_always |= 1;
445
158
        break;
446
62
      case SC_AC_CHV:       /* pin */
447
62
        if ((bNumber & 0x7F) == 0 || (bNumber & 0x7F) > 7) {
448
1
          sc_log(card->ctx,  "SetCOS 4.4 PIN refs can only be 1..7\n");
449
1
          return SC_ERROR_INVALID_ARGUMENTS;
450
1
        }
451
61
        pin_index = setcos_pin_index_44(pins, sizeof(pins) / sizeof(pins[0]), (int)bNumber);
452
61
        if (pin_index < 0) {
453
0
          return SC_ERROR_INTERNAL;
454
0
        }
455
61
        bCommands_pin[pin_index] |= 1 << i;
456
61
        break;
457
0
      case SC_AC_TERM:     /* key */
458
0
        bKeyNumber = bNumber; /* There should be only 1 key */
459
0
        bCommands_key |= 1;
460
0
        break;
461
227
      }
462
227
    }
463
464
    /* Add the commands that are always allowed */
465
35
    if (bCommands_always) {
466
33
      bBuf[len++] = 1;
467
33
      bBuf[len++] = bCommands_always;
468
33
    }
469
    /* Add commands that require pins */
470
62
    for (i = 0; i < (int)sizeof(bCommands_pin) && pins[i] != -1; i++) {
471
27
      bBuf[len++] = 2;
472
27
      bBuf[len++] = bCommands_pin[i];
473
27
      if (SETCOS_IS_EID_APPLET(card))
474
27
        bBuf[len++] = pins[i];  /* pin ref */
475
0
      else
476
0
        bBuf[len++] = pins[i] & 0x07;  /* pin ref */
477
27
    }
478
    /* Add commands that require the key */
479
35
    if (bCommands_key) {
480
0
      bBuf[len++] = 2 | 0x20;     /* indicate keyNumber present */
481
0
      bBuf[len++] = bCommands_key;
482
0
      bBuf[len++] = bKeyNumber;
483
0
    }
484
    /* RSA signing/decryption requires AC adaptive coding,  can't be put
485
       in AC simple coding. Only implemented for pins, not for a key. */
486
35
    if ( (file->type == SC_FILE_TYPE_INTERNAL_EF) &&
487
1
         (acl_to_byte_44(file->acl[SC_AC_OP_CRYPTO], &bNumber) == SC_AC_CHV) ) {
488
0
      bBuf[len++] = 0x83;
489
0
      bBuf[len++] = 0x01;
490
0
      bBuf[len++] = 0x2A;  /* INS byte for the sign/decrypt APDU */
491
0
      bBuf[len++] = bNumber & 0x07;  /* pin ref */
492
0
    }
493
494
35
    sc_file_set_sec_attr(file, bBuf, len);
495
35
  }
496
497
35
  return iso_ops->create_file(card, file);
498
36
}
499
500
static int setcos_create_file(sc_card_t *card, sc_file_t *file)
501
38
{
502
38
  if (card->type == SC_CARD_TYPE_SETCOS_44 || SETCOS_IS_EID_APPLET(card))
503
36
    return setcos_create_file_44(card, file);
504
505
2
  if (file->prop_attr_len == 0)
506
2
    sc_file_set_prop_attr(file, (const u8 *) "\x03\x00\x00", 3);
507
2
  if (file->sec_attr_len == 0) {
508
2
    int idx[6], i;
509
2
    u8 buf[6];
510
511
2
    if (file->type == SC_FILE_TYPE_DF) {
512
1
      const int df_idx[6] = {
513
1
        SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
514
1
        SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
515
1
        SC_AC_OP_INVALIDATE
516
1
      };
517
7
      for (i = 0; i < 6; i++)
518
6
        idx[i] = df_idx[i];
519
1
    } else {
520
1
      const int ef_idx[6] = {
521
1
        SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
522
1
        SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
523
1
        SC_AC_OP_INVALIDATE
524
1
      };
525
7
      for (i = 0; i < 6; i++)
526
6
        idx[i] = ef_idx[i];
527
1
    }
528
14
    for (i = 0; i < 6; i++) {
529
12
      const struct sc_acl_entry *entry;
530
12
      entry = sc_file_get_acl_entry(file, idx[i]);
531
12
      buf[i] = acl_to_byte(entry);
532
12
    }
533
534
2
    sc_file_set_sec_attr(file, buf, 6);
535
2
  }
536
537
2
  return iso_ops->create_file(card, file);
538
38
}
539
540
static int setcos_set_security_env2(sc_card_t *card,
541
            const sc_security_env_t *env, int se_num)
542
0
{
543
0
  sc_apdu_t apdu;
544
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
545
0
  u8 *p;
546
0
  int r, locked = 0;
547
548
0
  if (card == NULL || env == NULL)
549
0
    return SC_ERROR_INTERNAL;
550
551
0
  if (card->type == SC_CARD_TYPE_SETCOS_44 ||
552
0
      card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
553
0
      SETCOS_IS_EID_APPLET(card)) {
554
0
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC) {
555
0
      sc_log(card->ctx,  "symmetric keyref not supported.\n");
556
0
      return SC_ERROR_NOT_SUPPORTED;
557
0
    }
558
0
    if (se_num > 0) {
559
0
      sc_log(card->ctx,  "restore security environment not supported.\n");
560
0
      return SC_ERROR_NOT_SUPPORTED;
561
0
    }
562
0
  }
563
564
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0, 0);
565
0
  switch (env->operation) {
566
0
  case SC_SEC_OPERATION_DECIPHER:
567
    /* Should be 0x81 */
568
0
    apdu.p1 = 0x41;
569
0
    apdu.p2 = 0xB8;
570
0
    break;
571
0
  case SC_SEC_OPERATION_SIGN:
572
    /* Should be 0x41 */
573
0
    apdu.p1 = ((card->type == SC_CARD_TYPE_SETCOS_44) ||
574
0
            (card->type == SC_CARD_TYPE_SETCOS_NIDEL) ||
575
0
            SETCOS_IS_EID_APPLET(card))
576
0
            ? 0x41
577
0
            : 0x81;
578
0
    apdu.p2 = 0xB6;
579
0
    break;
580
0
  default:
581
0
    return SC_ERROR_INVALID_ARGUMENTS;
582
0
  }
583
0
  apdu.le = 0;
584
0
  p = sbuf;
585
0
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
586
0
    *p++ = 0x80;  /* algorithm reference */
587
0
    *p++ = 0x01;
588
0
    *p++ = env->algorithm_ref & 0xFF;
589
0
  }
590
0
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT) {
591
0
    *p++ = 0x81;
592
0
    *p++ = env->file_ref.len;
593
0
    memcpy(p, env->file_ref.value, env->file_ref.len);
594
0
    p += env->file_ref.len;
595
0
  }
596
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT &&
597
0
      !(card->type == SC_CARD_TYPE_SETCOS_NIDEL)) {
598
0
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
599
0
      *p++ = 0x83;
600
0
    else
601
0
      *p++ = 0x84;
602
0
    *p++ = env->key_ref_len;
603
0
    memcpy(p, env->key_ref, env->key_ref_len);
604
0
    p += env->key_ref_len;
605
0
  }
606
0
  r = (int)(p - sbuf);
607
0
  apdu.lc = r;
608
0
  apdu.datalen = r;
609
0
  apdu.data = sbuf;
610
0
  apdu.resplen = 0;
611
0
  if (se_num > 0) {
612
0
    r = sc_lock(card);
613
0
    LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
614
0
    locked = 1;
615
0
  }
616
0
  if (apdu.datalen != 0) {
617
0
    r = sc_transmit_apdu(card, &apdu);
618
0
    if (r) {
619
0
      sc_log(card->ctx,
620
0
        "%s: APDU transmit failed", sc_strerror(r));
621
0
      goto err;
622
0
    }
623
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
624
0
    if (r) {
625
0
      sc_log(card->ctx,
626
0
        "%s: Card returned error", sc_strerror(r));
627
0
      goto err;
628
0
    }
629
0
  }
630
0
  if (se_num <= 0)
631
0
    return 0;
632
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0xF2, se_num);
633
0
  r = sc_transmit_apdu(card, &apdu);
634
0
  sc_unlock(card);
635
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
636
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
637
0
err:
638
0
  if (locked)
639
0
    sc_unlock(card);
640
0
  return r;
641
0
}
642
643
static int setcos_set_security_env(sc_card_t *card,
644
           const sc_security_env_t *env, int se_num)
645
0
{
646
0
  if (env->flags & SC_SEC_ENV_ALG_PRESENT) {
647
0
    sc_security_env_t tmp;
648
649
0
    tmp = *env;
650
0
    tmp.flags &= ~SC_SEC_ENV_ALG_PRESENT;
651
0
    tmp.flags |= SC_SEC_ENV_ALG_REF_PRESENT;
652
0
    if (tmp.algorithm != SC_ALGORITHM_RSA) {
653
0
      sc_log(card->ctx,  "Only RSA algorithm supported.\n");
654
0
      return SC_ERROR_NOT_SUPPORTED;
655
0
    }
656
0
    switch (card->type) {
657
0
    case SC_CARD_TYPE_SETCOS_PKI:
658
0
    case SC_CARD_TYPE_SETCOS_NIDEL:
659
0
    case SC_CARD_TYPE_SETCOS_44:
660
0
    case SC_CARD_TYPE_SETCOS_EID_V2_0:
661
0
    case SC_CARD_TYPE_SETCOS_EID_V2_1:
662
0
      break;
663
0
    default:
664
0
      sc_log(card->ctx,  "Card does not support RSA.\n");
665
0
      return SC_ERROR_NOT_SUPPORTED;
666
0
      break;
667
0
    }
668
0
    tmp.algorithm_ref = 0x00;
669
    /* potential FIXME: return an error, if an unsupported
670
     * pad or hash was requested, although this shouldn't happen.
671
     */
672
0
    if ((env->operation == SC_SEC_OPERATION_SIGN && env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01) ||
673
0
        (env->operation == SC_SEC_OPERATION_DECIPHER && env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02))
674
0
      tmp.algorithm_ref = 0x02;
675
0
    if (tmp.algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
676
0
      tmp.algorithm_ref |= 0x10;
677
0
    return setcos_set_security_env2(card, &tmp, se_num);
678
0
  }
679
0
  return setcos_set_security_env2(card, env, se_num);
680
0
}
681
682
static void add_acl_entry(sc_file_t *file, int op, u8 byte)
683
90
{
684
90
  unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
685
686
90
  switch (byte >> 4) {
687
19
  case 0:
688
19
    method = SC_AC_NONE;
689
19
    break;
690
0
  case 1:
691
0
    method = SC_AC_CHV;
692
0
    key_ref = 1;
693
0
    break;
694
2
  case 2:
695
2
    method = SC_AC_CHV;
696
2
    key_ref = 2;
697
2
    break;
698
0
  case 4:
699
0
    method = SC_AC_TERM;
700
0
    break;
701
12
  case 15:
702
12
    method = SC_AC_NEVER;
703
12
    break;
704
57
  default:
705
57
    method = SC_AC_UNKNOWN;
706
57
    break;
707
90
  }
708
90
  sc_file_add_acl_entry(file, op, method, key_ref);
709
90
}
710
711
static void parse_sec_attr(sc_file_t *file, const u8 * buf, size_t len)
712
25
{
713
25
  int i;
714
25
  int idx[6];
715
716
25
  if (len < 6)
717
10
    return;
718
15
  if (file->type == SC_FILE_TYPE_DF) {
719
1
    const int df_idx[6] = {
720
1
      SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
721
1
      SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
722
1
      SC_AC_OP_INVALIDATE
723
1
    };
724
7
    for (i = 0; i < 6; i++)
725
6
      idx[i] = df_idx[i];
726
14
  } else {
727
14
    const int ef_idx[6] = {
728
14
      SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
729
14
      SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
730
14
      SC_AC_OP_INVALIDATE
731
14
    };
732
98
    for (i = 0; i < 6; i++)
733
84
      idx[i] = ef_idx[i];
734
14
  }
735
105
  for (i = 0; i < 6; i++)
736
90
    add_acl_entry(file, idx[i], buf[i]);
737
15
}
738
739
static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
740
2.67k
{
741
  /* OpenSc Operation values for each command operation-type */
742
2.67k
  const int df_idx[8] = {  /* byte 1 = OpenSC type of AC Bit0,  byte 2 = OpenSC type of AC Bit1 ...*/
743
2.67k
    SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE,
744
2.67k
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
745
2.67k
    SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1};
746
2.67k
  const int ef_idx[8] = {
747
2.67k
    SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
748
2.67k
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
749
2.67k
    -1, SC_AC_OP_ERASE, -1};
750
2.67k
  const int efi_idx[8] = { /* internal EF used for RSA keys */
751
2.67k
    SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE,
752
2.67k
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
753
2.67k
    -1, SC_AC_OP_ERASE, -1};
754
755
2.67k
  u8    bValue;
756
2.67k
  int   i;
757
2.67k
  int   iKeyRef = 0;
758
2.67k
  int   iMethod;
759
2.67k
  int   iPinCount;
760
2.67k
  int   iOffset = 0;
761
2.67k
  int   iOperation;
762
2.67k
  const int*  p_idx;
763
764
  /* Check all sub-AC definitions within the total AC */
765
4.61k
  while (len > 1 && (size_t)iOffset < len) { /* minimum length = 2 */
766
2.44k
    size_t iACLen   = buf[iOffset] & 0x0F;
767
2.44k
    if (iACLen >= len)
768
277
      break;
769
770
2.16k
    iMethod = SC_AC_NONE;   /* default no authentication required */
771
772
2.16k
    if (buf[iOffset] & 0X80) { /* AC in adaptive coding */
773
      /* Evaluates only the command-byte, not the optional P1/P2/Option bytes */
774
828
      size_t  iParmLen = 1;     /* command-byte is always present */
775
828
      size_t  iKeyLen  = 0;     /* Encryption key is optional */
776
777
828
      if (buf[iOffset]   & 0x20) iKeyLen++;
778
828
      if (buf[iOffset+1] & 0x40) iParmLen++;
779
828
      if (buf[iOffset+1] & 0x20) iParmLen++;
780
828
      if (buf[iOffset+1] & 0x10) iParmLen++;
781
828
      if (buf[iOffset+1] & 0x08) iParmLen++;
782
783
      /* Get KeyNumber if available */
784
828
      if(iKeyLen) {
785
401
        int iSC;
786
401
        if (len < 1 + iACLen)
787
0
          break;
788
401
        iSC = buf[iOffset+iACLen];
789
790
401
        switch( (iSC>>5) & 0x03 ){
791
60
        case 0:
792
60
          iMethod = SC_AC_TERM;   /* key authentication */
793
60
          break;
794
0
        case 1:
795
0
          iMethod = SC_AC_AUT;   /* key authentication  */
796
0
          break;
797
12
        case 2:
798
341
        case 3:
799
341
          iMethod = SC_AC_PRO;   /* secure messaging */
800
341
          break;
801
401
        }
802
401
        iKeyRef = iSC & 0x1F;     /* get key number */
803
401
      }
804
805
      /* Get PinNumber if available */
806
828
      if (iACLen > (1+iParmLen+iKeyLen)) {  /* check via total length if pin is present */
807
83
        if (len < 1+1+1+(size_t)iParmLen)
808
0
          break;
809
83
        iKeyRef = buf[iOffset+1+1+iParmLen];  /* PTL + AM-header + parameter-bytes */
810
83
        iMethod = SC_AC_CHV;
811
83
      }
812
813
      /* Convert SETCOS command to OpenSC command group */
814
828
      if (len < 1+2)
815
226
        break;
816
602
      switch(buf[iOffset+2]){
817
12
      case 0x2A:      /* crypto operation */
818
12
        iOperation = SC_AC_OP_CRYPTO;
819
12
        break;
820
0
      case 0x46:      /* key-generation operation */
821
0
        iOperation = SC_AC_OP_UPDATE;
822
0
        break;
823
590
      default:
824
590
        iOperation = SC_AC_OP_SELECT;
825
590
        break;
826
602
      }
827
602
      sc_file_add_acl_entry(file, iOperation, iMethod, iKeyRef);
828
602
    }
829
1.33k
    else { /* AC in simple coding */
830
         /* Initial AC is treated as an operational AC */
831
832
      /* Get specific Cmd groups for specified file-type */
833
1.33k
      switch (file->type) {
834
80
      case SC_FILE_TYPE_DF:            /* DF */
835
80
        p_idx = df_idx;
836
80
        break;
837
35
      case SC_FILE_TYPE_INTERNAL_EF:   /* EF for RSA keys */
838
35
        p_idx = efi_idx;
839
35
        break;
840
1.22k
      default:                         /* EF */
841
1.22k
        p_idx = ef_idx;
842
1.22k
        break;
843
1.33k
      }
844
845
      /* Encryption key present ? */
846
1.33k
      iPinCount = iACLen > 0 ? (int)iACLen - 1 : 0;
847
848
1.33k
      if (buf[iOffset] & 0x20) {
849
160
        int iSC;
850
160
        if (len < 1 + (size_t)iACLen)
851
0
          break;
852
160
        iSC = buf[iOffset + iACLen];
853
854
160
        switch( (iSC>>5) & 0x03 ) {
855
146
        case 0:
856
146
          iMethod = SC_AC_TERM;   /* key authentication */
857
146
          break;
858
5
        case 1:
859
5
          iMethod = SC_AC_AUT;   /* key authentication  */
860
5
          break;
861
1
        case 2:
862
9
        case 3:
863
9
          iMethod = SC_AC_PRO;   /* secure messaging */
864
9
          break;
865
160
        }
866
160
        iKeyRef = iSC & 0x1F;     /* get key number */
867
868
160
        iPinCount--;        /* one byte used for keyReference  */
869
160
      }
870
871
      /* Pin present ? */
872
1.33k
      if ( iPinCount > 0 ) {
873
190
        if (len < 1 + 2)
874
0
          break;
875
190
        iKeyRef = buf[iOffset + 2]; /* pin ref */
876
190
        iMethod = SC_AC_CHV;
877
190
      }
878
879
      /* Add AC for each command-operationType into OpenSc structure */
880
1.33k
      bValue = buf[iOffset + 1];
881
12.0k
      for (i = 0; i < 8; i++) {
882
10.7k
        if((bValue & 1) && (p_idx[i] >= 0))
883
5.90k
          sc_file_add_acl_entry(file, p_idx[i], iMethod, iKeyRef);
884
10.7k
        bValue >>= 1;
885
10.7k
      }
886
1.33k
    }
887
    /* Current field treated, get next AC sub-field */
888
1.94k
    iOffset += iACLen +1;   /* AC + PTL-byte */
889
1.94k
    len     -= iACLen +1;
890
1.94k
  }
891
2.67k
}
892
893
static int setcos_select_file(sc_card_t *card,
894
            const sc_path_t *in_path, sc_file_t **file)
895
33.1k
{
896
33.1k
  int r;
897
898
33.1k
  r = iso_ops->select_file(card, in_path, file);
899
33.1k
  if (r)
900
30.1k
    return r;
901
3.02k
  if (file != NULL) {
902
2.69k
    if (card->type == SC_CARD_TYPE_SETCOS_44 ||
903
2.63k
        card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
904
2.63k
        SETCOS_IS_EID_APPLET(card))
905
2.67k
      parse_sec_attr_44(*file, (*file)->sec_attr, (*file)->sec_attr_len);
906
25
    else
907
25
      parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
908
2.69k
  }
909
3.02k
  return 0;
910
33.1k
}
911
912
static int setcos_list_files(sc_card_t *card, u8 * buf, size_t buflen)
913
0
{
914
0
  sc_apdu_t apdu;
915
0
  int r;
916
917
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xAA, 0, 0);
918
0
  if (card->type == SC_CARD_TYPE_SETCOS_44 ||
919
0
      card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
920
0
      SETCOS_IS_EID_APPLET(card))
921
0
    apdu.cla = 0x80;
922
0
  apdu.resp = buf;
923
0
  apdu.resplen = buflen;
924
0
  apdu.le = buflen > 256 ? 256 : buflen;
925
0
  r = sc_transmit_apdu(card, &apdu);
926
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
927
0
  if (card->type == SC_CARD_TYPE_SETCOS_44 && apdu.sw1 == 0x6A && apdu.sw2 == 0x82)
928
0
    return 0; /* no files found */
929
0
  if (apdu.resplen == 0)
930
0
    return sc_check_sw(card, apdu.sw1, apdu.sw2);
931
0
  return (int)apdu.resplen;
932
0
}
933
934
static int setcos_process_fci(sc_card_t *card, sc_file_t *file,
935
           const u8 *buf, size_t buflen)
936
2.66k
{
937
2.66k
  int r = iso_ops->process_fci(card, file, buf, buflen);
938
939
  /* SetCOS 4.4: RSA key file is an internal EF but it's
940
   * file descriptor doesn't seem to follow ISO7816. */
941
2.66k
  if (r >= 0 && (card->type == SC_CARD_TYPE_SETCOS_44 ||
942
2.63k
                 SETCOS_IS_EID_APPLET(card))) {
943
2.63k
    const u8 *tag;
944
2.63k
    size_t taglen = 1;
945
2.63k
    tag = (u8 *) sc_asn1_find_tag(card->ctx, buf, buflen, 0x82, &taglen);
946
2.63k
    if (tag != NULL && taglen == 1 && *tag == 0x11)
947
16
      file->type = SC_FILE_TYPE_INTERNAL_EF;
948
2.63k
  }
949
950
2.66k
  return r;
951
2.66k
}
952
953
/* Write internal data, e.g. add default pin-records to pin-file */
954
static int setcos_putdata(struct sc_card *card, struct sc_cardctl_setcos_data_obj* data_obj)
955
0
{
956
0
  int       r;
957
0
  struct sc_apdu      apdu;
958
959
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
960
961
0
  memset(&apdu, 0, sizeof(apdu));
962
0
  apdu.cse     = SC_APDU_CASE_3_SHORT;
963
0
  apdu.cla     = 0x00;
964
0
  apdu.ins     = 0xDA;
965
0
  apdu.p1      = data_obj->P1;
966
0
  apdu.p2      = data_obj->P2;
967
0
  apdu.lc      = data_obj->DataLen;
968
0
  apdu.datalen = data_obj->DataLen;
969
0
  apdu.data    = data_obj->Data;
970
971
0
  r = sc_transmit_apdu(card, &apdu);
972
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
973
974
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
975
0
  LOG_TEST_RET(card->ctx, r, "PUT_DATA returned error");
976
977
0
  LOG_FUNC_RETURN(card->ctx, r);
978
0
}
979
980
/* Read internal data, e.g. get RSA public key */
981
static int setcos_getdata(struct sc_card *card, struct sc_cardctl_setcos_data_obj* data_obj)
982
9
{
983
9
  int       r;
984
9
  struct sc_apdu      apdu;
985
986
9
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
987
988
9
  memset(&apdu, 0, sizeof(apdu));
989
9
  apdu.cse     = SC_APDU_CASE_2_SHORT;
990
9
  apdu.cla     = 0x00;
991
9
  apdu.ins     = 0xCA;      /* GET DATA */
992
9
  apdu.p1      = data_obj->P1;
993
9
  apdu.p2      = data_obj->P2;
994
9
  apdu.lc      = 0;
995
9
  apdu.datalen = 0;
996
9
  apdu.data    = data_obj->Data;
997
998
9
  apdu.le      = 256;
999
9
  apdu.resp    = data_obj->Data;
1000
9
  apdu.resplen = data_obj->DataLen;
1001
1002
9
  r = sc_transmit_apdu(card, &apdu);
1003
9
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1004
1005
9
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1006
9
  LOG_TEST_RET(card->ctx, r, "GET_DATA returned error");
1007
1008
9
  if (apdu.resplen > data_obj->DataLen)
1009
0
    r = SC_ERROR_WRONG_LENGTH;
1010
9
  else
1011
9
    data_obj->DataLen = apdu.resplen;
1012
1013
9
  LOG_FUNC_RETURN(card->ctx, r);
1014
9
}
1015
1016
/* Generate or store a key */
1017
static int setcos_generate_store_key(sc_card_t *card,
1018
  struct sc_cardctl_setcos_gen_store_key_info *data)
1019
10
{
1020
10
  struct  sc_apdu apdu;
1021
10
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1022
10
  int r, len;
1023
1024
10
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1025
1026
  /* Setup key-generation parameters */
1027
10
  len = 0;
1028
10
  if (data->op_type == OP_TYPE_GENERATE)
1029
10
    sbuf[len++] = 0x92;  /* algo ID: RSA CRT */
1030
0
  else
1031
0
    sbuf[len++] = 0x9A; /* algo ID: EXTERNALLY GENERATED RSA CRT */
1032
10
  sbuf[len++] = 0x00;
1033
10
  sbuf[len++] = data->mod_len / 256;  /* 2 bytes for modulus bitlength */
1034
10
  sbuf[len++] = data->mod_len % 256;
1035
1036
10
  sbuf[len++] = data->pubexp_len / 256;   /* 2 bytes for pubexp bitlength */
1037
10
  sbuf[len++] = data->pubexp_len % 256;
1038
10
  memcpy(sbuf + len, data->pubexp, BYTES4BITS(data->pubexp_len));
1039
10
  len += BYTES4BITS(data->pubexp_len);
1040
1041
10
  if (data->op_type == OP_TYPE_STORE) {
1042
0
    sbuf[len++] = data->primep_len / 256;
1043
0
    sbuf[len++] = data->primep_len % 256;
1044
0
    memcpy(sbuf + len, data->primep, BYTES4BITS(data->primep_len));
1045
0
    len += BYTES4BITS(data->primep_len);
1046
0
    sbuf[len++] = data->primeq_len / 256;
1047
0
    sbuf[len++] = data->primeq_len % 256;
1048
0
    memcpy(sbuf + len, data->primeq, BYTES4BITS(data->primeq_len));
1049
0
    len += BYTES4BITS(data->primeq_len);
1050
0
  }
1051
1052
10
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
1053
10
  apdu.cla = 0x00;
1054
10
  apdu.data = sbuf;
1055
10
  apdu.datalen = len;
1056
10
  apdu.lc = len;
1057
1058
10
  r = sc_transmit_apdu(card, &apdu);
1059
10
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1060
1061
10
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1062
10
  LOG_TEST_RET(card->ctx, r, "STORE/GENERATE_KEY returned error");
1063
1064
10
  LOG_FUNC_RETURN(card->ctx, r);
1065
10
}
1066
1067
static int setcos_activate_file(sc_card_t *card)
1068
0
{
1069
0
  int r;
1070
0
  u8 sbuf[2];
1071
0
  sc_apdu_t apdu;
1072
1073
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x44, 0x00, 0x00);
1074
0
  apdu.data = sbuf;
1075
1076
0
  r = sc_transmit_apdu(card, &apdu);
1077
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1078
1079
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1080
0
  LOG_TEST_RET(card->ctx, r, "ACTIVATE_FILE returned error");
1081
1082
0
  LOG_FUNC_RETURN(card->ctx, r);
1083
0
}
1084
1085
static int setcos_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
1086
206
{
1087
206
  if (card->type != SC_CARD_TYPE_SETCOS_44 && !SETCOS_IS_EID_APPLET(card))
1088
17
    return SC_ERROR_NOT_SUPPORTED;
1089
1090
189
  switch(cmd) {
1091
0
  case SC_CARDCTL_SETCOS_PUTDATA:
1092
0
    return setcos_putdata(card,
1093
0
        (struct sc_cardctl_setcos_data_obj*) ptr);
1094
0
    break;
1095
9
  case SC_CARDCTL_SETCOS_GETDATA:
1096
9
    return setcos_getdata(card,
1097
9
        (struct sc_cardctl_setcos_data_obj*) ptr);
1098
0
    break;
1099
10
  case SC_CARDCTL_SETCOS_GENERATE_STORE_KEY:
1100
10
    return setcos_generate_store_key(card,
1101
10
        (struct sc_cardctl_setcos_gen_store_key_info *) ptr);
1102
0
  case SC_CARDCTL_SETCOS_ACTIVATE_FILE:
1103
0
    return setcos_activate_file(card);
1104
189
  }
1105
1106
170
  return SC_ERROR_NOT_SUPPORTED;
1107
189
}
1108
1109
static struct sc_card_driver *sc_get_driver(void)
1110
3.69k
{
1111
3.69k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
1112
1113
3.69k
  setcos_ops = *iso_drv->ops;
1114
3.69k
  setcos_ops.match_card = setcos_match_card;
1115
3.69k
  setcos_ops.init = setcos_init;
1116
3.69k
  if (iso_ops == NULL)
1117
1
    iso_ops = iso_drv->ops;
1118
3.69k
  setcos_ops.create_file = setcos_create_file;
1119
3.69k
  setcos_ops.set_security_env = setcos_set_security_env;
1120
3.69k
  setcos_ops.select_file = setcos_select_file;
1121
3.69k
  setcos_ops.list_files = setcos_list_files;
1122
3.69k
  setcos_ops.process_fci = setcos_process_fci;
1123
3.69k
  setcos_ops.construct_fci = setcos_construct_fci;
1124
3.69k
  setcos_ops.card_ctl = setcos_card_ctl;
1125
1126
3.69k
  return &setcos_drv;
1127
3.69k
}
1128
1129
struct sc_card_driver *sc_get_setcos_driver(void)
1130
3.69k
{
1131
3.69k
  return sc_get_driver();
1132
3.69k
}