Coverage Report

Created: 2026-03-21 06:15

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