Coverage Report

Created: 2026-06-10 06:48

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
360
#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.45k
{
65
4.45k
  const char *src = (const char *) card->reader->atr_info.hist_bytes;
66
4.45k
  size_t srclen = card->reader->atr_info.hist_bytes_len;
67
4.45k
  size_t offset = 0;
68
69
4.45k
  if (len == 0)
70
4.45k
    len = strlen(str);
71
4.45k
  if (srclen < len)
72
3.25k
    return 0;
73
8.12k
  while (srclen - offset > len) {
74
6.96k
    if (memcmp(src + offset, str, len) == 0) {
75
31
      return 1;
76
31
    }
77
6.93k
    offset++;
78
6.93k
  }
79
1.16k
  return 0;
80
1.19k
}
81
82
static int setcos_match_card(sc_card_t *card)
83
4.46k
{
84
4.46k
  sc_apdu_t apdu;
85
4.46k
  u8 buf[6];
86
4.46k
  int i;
87
88
4.46k
  i = _sc_match_atr(card, setcos_atrs, &card->type);
89
4.46k
  if (i < 0) {
90
4.45k
    if (match_hist_bytes(card, "FISE", 0)) {
91
31
      card->type = SC_CARD_TYPE_SETCOS_GENERIC;
92
31
      return 1;
93
31
    }
94
    /* Check if it's a EID2.x applet by reading the version info */
95
4.42k
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xCA, 0xDF, 0x30);
96
4.42k
    apdu.cla = 0x00;
97
4.42k
    apdu.resp = buf;
98
4.42k
    apdu.resplen = 5;
99
4.42k
    apdu.le = 5;
100
4.42k
    i = sc_transmit_apdu(card, &apdu);
101
4.42k
    if (i == 0 && apdu.sw1 == 0x90 && apdu.sw2 == 0x00 && apdu.resplen == 5) {
102
133
      if (memcmp(buf, "v2.0", 4) == 0)
103
94
        card->type = SC_CARD_TYPE_SETCOS_EID_V2_0;
104
39
      else if (memcmp(buf, "v2.1", 4) == 0)
105
33
        card->type = SC_CARD_TYPE_SETCOS_EID_V2_1;
106
6
      else {
107
6
        buf[sizeof(buf) - 1] = '\0';
108
6
        sc_log(card->ctx,  "SetCOS EID applet %s is not supported", (char *) buf);
109
6
        return 0;
110
6
      }
111
127
      return 1;
112
133
    }
113
114
4.28k
    return 0;
115
4.42k
  }
116
11
  card->flags = setcos_atrs[i].flags;
117
11
  return 1;
118
4.46k
}
119
120
static int select_pkcs15_app(sc_card_t * card)
121
5
{
122
5
  sc_path_t app;
123
5
  int r;
124
125
  /* Regular PKCS#15 AID */
126
5
  sc_format_path("A000000063504B43532D3135", &app);
127
5
  app.type = SC_PATH_TYPE_DF_NAME;
128
5
  r = sc_select_file(card, &app, NULL);
129
5
  return r;
130
5
}
131
132
static int setcos_init(sc_card_t *card)
133
169
{
134
169
  card->name = "SetCOS";
135
136
  /* Handle unknown or forced cards */
137
169
  if (card->type < 0) {
138
0
    card->type = SC_CARD_TYPE_SETCOS_GENERIC;
139
0
  }
140
141
169
  switch (card->type) {
142
5
  case SC_CARD_TYPE_SETCOS_NIDEL:
143
5
    card->cla = 0x00;
144
5
    select_pkcs15_app(card);
145
5
    if (card->flags & SC_CARD_FLAG_RNG)
146
0
      card->caps |= SC_CARD_CAP_RNG;
147
5
    break;
148
5
  case SC_CARD_TYPE_SETCOS_44:
149
99
  case SC_CARD_TYPE_SETCOS_EID_V2_0:
150
132
  case SC_CARD_TYPE_SETCOS_EID_V2_1:
151
132
    card->cla = 0x00;
152
132
    card->caps |= SC_CARD_CAP_USE_FCI_AC;
153
132
    card->caps |= SC_CARD_CAP_RNG;
154
132
    card->caps |= SC_CARD_CAP_APDU_EXT;
155
132
    break;
156
32
  default:
157
    /* XXX: Get SetCOS version */
158
32
    card->cla = 0x80; /* SetCOS 4.3.x */
159
    /* State that we have an RNG */
160
32
    card->caps |= SC_CARD_CAP_RNG;
161
32
    break;
162
169
  }
163
164
169
  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
5
  case SC_CARD_TYPE_SETCOS_44:
175
10
  case SC_CARD_TYPE_SETCOS_NIDEL:
176
104
  case SC_CARD_TYPE_SETCOS_EID_V2_0:
177
137
  case SC_CARD_TYPE_SETCOS_EID_V2_1:
178
137
    {
179
137
      unsigned long flags;
180
181
137
      flags = SC_ALGORITHM_RSA_RAW | SC_ALGORITHM_RSA_PAD_PKCS1;
182
137
      flags |= SC_ALGORITHM_RSA_HASH_NONE | SC_ALGORITHM_RSA_HASH_SHA1;
183
137
      flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
184
185
137
      _sc_card_add_rsa_alg(card, 512, flags, 0);
186
137
      _sc_card_add_rsa_alg(card, 768, flags, 0);
187
137
      _sc_card_add_rsa_alg(card, 1024, flags, 0);
188
137
      _sc_card_add_rsa_alg(card, 2048, flags, 0);
189
137
    }
190
137
    break;
191
169
  }
192
169
  return 0;
193
169
}
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
  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
0
{
383
0
  const u8 bFileStatus = file->status == SC_FILE_STATUS_CREATION ?
384
0
    SETEC_LCSI_CREATE : SETEC_LCSI_ACTIVATED;
385
0
  u8 bCommands_always = 0;
386
0
  int pins[] = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};
387
0
  u8 bCommands_pin[sizeof(pins)/sizeof(pins[0])]; /* both 7 entries big */
388
0
  u8 bCommands_key = 0;
389
0
  u8 bNumber = 0;
390
0
  u8 bKeyNumber = 0;
391
0
  unsigned int bMethod = 0;
392
393
  /* -1 means RFU */
394
0
  const int df_idx[8] = {  /* byte 1 = OpenSC type of AC Bit0,  byte 2 = OpenSC type of AC Bit1 ...*/
395
0
    SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE,
396
0
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
397
0
    SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1};
398
0
  const int ef_idx[8] = {  /* note: SC_AC_OP_SELECT to be ignored, actually RFU */
399
0
    SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
400
0
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
401
0
    -1, SC_AC_OP_ERASE, -1};
402
0
  const int efi_idx[8] = {  /* internal EF used for RSA keys */
403
0
    SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE,
404
0
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
405
0
    -1, SC_AC_OP_ERASE, -1};
406
407
  /* Set file creation status  */
408
0
  sc_file_set_prop_attr(file, &bFileStatus, 1);
409
410
  /* Build ACL from local structure = get AC for each operation group */
411
0
  if (file->sec_attr_len == 0) {
412
0
    const int* p_idx;
413
0
    int        i;
414
0
    int        len = 0;
415
0
    u8         bBuf[64];
416
417
    /* Get specific operation groups for specified file-type */
418
0
    switch (file->type){
419
0
    case SC_FILE_TYPE_DF:           /* DF */
420
0
      p_idx = df_idx;
421
0
      break;
422
0
    case SC_FILE_TYPE_INTERNAL_EF:  /* EF for RSA keys */
423
0
      p_idx = efi_idx;
424
0
      break;
425
0
    default:                        /* SC_FILE_TYPE_WORKING_EF */
426
0
      p_idx = ef_idx;
427
0
      break;
428
0
    }
429
430
    /* Get enabled commands + required Keys/Pins  */
431
0
    memset(bCommands_pin, 0, sizeof(bCommands_pin));
432
0
    for (i = 7; i >= 0; i--) {  /* for each AC Setcos operation */
433
0
      int pin_index;
434
0
      bCommands_always <<= 1;
435
0
      bCommands_key <<= 1;
436
437
0
      if (p_idx[i] == -1)  /* -1 means that bit is RFU -> set to 0 */
438
0
        continue;
439
440
0
      bMethod = acl_to_byte_44(file->acl[ p_idx[i] ], &bNumber);
441
      /* Convert to OpenSc-index, convert to pin/key number */
442
0
      switch(bMethod){
443
0
      case SC_AC_NONE:     /* always allowed */
444
0
        bCommands_always |= 1;
445
0
        break;
446
0
      case SC_AC_CHV:       /* pin */
447
0
        if ((bNumber & 0x7F) == 0 || (bNumber & 0x7F) > 7) {
448
0
          sc_log(card->ctx,  "SetCOS 4.4 PIN refs can only be 1..7\n");
449
0
          return SC_ERROR_INVALID_ARGUMENTS;
450
0
        }
451
0
        pin_index = setcos_pin_index_44(pins, sizeof(pins) / sizeof(pins[0]), (int)bNumber);
452
0
        if (pin_index < 0) {
453
0
          return SC_ERROR_INTERNAL;
454
0
        }
455
0
        bCommands_pin[pin_index] |= 1 << i;
456
0
        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
0
      }
462
0
    }
463
464
    /* Add the commands that are always allowed */
465
0
    if (bCommands_always) {
466
0
      bBuf[len++] = 1;
467
0
      bBuf[len++] = bCommands_always;
468
0
    }
469
    /* Add commands that require pins */
470
0
    for (i = 0; i < (int)sizeof(bCommands_pin) && pins[i] != -1; i++) {
471
0
      bBuf[len++] = 2;
472
0
      bBuf[len++] = bCommands_pin[i];
473
0
      if (SETCOS_IS_EID_APPLET(card))
474
0
        bBuf[len++] = pins[i];  /* pin ref */
475
0
      else
476
0
        bBuf[len++] = pins[i] & 0x07;  /* pin ref */
477
0
    }
478
    /* Add commands that require the key */
479
0
    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
0
    if ( (file->type == SC_FILE_TYPE_INTERNAL_EF) &&
487
0
         (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
0
    sc_file_set_sec_attr(file, bBuf, len);
495
0
  }
496
497
0
  return iso_ops->create_file(card, file);
498
0
}
499
500
static int setcos_create_file(sc_card_t *card, sc_file_t *file)
501
0
{
502
0
  if (card->type == SC_CARD_TYPE_SETCOS_44 || SETCOS_IS_EID_APPLET(card))
503
0
    return setcos_create_file_44(card, file);
504
505
0
  if (file->prop_attr_len == 0)
506
0
    sc_file_set_prop_attr(file, (const u8 *) "\x03\x00\x00", 3);
507
0
  if (file->sec_attr_len == 0) {
508
0
    int idx[6], i;
509
0
    u8 buf[6];
510
511
0
    if (file->type == SC_FILE_TYPE_DF) {
512
0
      const int df_idx[6] = {
513
0
        SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
514
0
        SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
515
0
        SC_AC_OP_INVALIDATE
516
0
      };
517
0
      for (i = 0; i < 6; i++)
518
0
        idx[i] = df_idx[i];
519
0
    } else {
520
0
      const int ef_idx[6] = {
521
0
        SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
522
0
        SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
523
0
        SC_AC_OP_INVALIDATE
524
0
      };
525
0
      for (i = 0; i < 6; i++)
526
0
        idx[i] = ef_idx[i];
527
0
    }
528
0
    for (i = 0; i < 6; i++) {
529
0
      const struct sc_acl_entry *entry;
530
0
      entry = sc_file_get_acl_entry(file, idx[i]);
531
0
      buf[i] = acl_to_byte(entry);
532
0
    }
533
534
0
    sc_file_set_sec_attr(file, buf, 6);
535
0
  }
536
537
0
  return iso_ops->create_file(card, file);
538
0
}
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
150
{
684
150
  unsigned int method, key_ref = SC_AC_KEY_REF_NONE;
685
686
150
  switch (byte >> 4) {
687
26
  case 0:
688
26
    method = SC_AC_NONE;
689
26
    break;
690
23
  case 1:
691
23
    method = SC_AC_CHV;
692
23
    key_ref = 1;
693
23
    break;
694
18
  case 2:
695
18
    method = SC_AC_CHV;
696
18
    key_ref = 2;
697
18
    break;
698
18
  case 4:
699
18
    method = SC_AC_TERM;
700
18
    break;
701
31
  case 15:
702
31
    method = SC_AC_NEVER;
703
31
    break;
704
34
  default:
705
34
    method = SC_AC_UNKNOWN;
706
34
    break;
707
150
  }
708
150
  sc_file_add_acl_entry(file, op, method, key_ref);
709
150
}
710
711
static void parse_sec_attr(sc_file_t *file, const u8 * buf, size_t len)
712
37
{
713
37
  int i;
714
37
  int idx[6];
715
716
37
  if (len < 6)
717
12
    return;
718
25
  if (file->type == SC_FILE_TYPE_DF) {
719
2
    const int df_idx[6] = {
720
2
      SC_AC_OP_SELECT, SC_AC_OP_LOCK, SC_AC_OP_DELETE,
721
2
      SC_AC_OP_CREATE, SC_AC_OP_REHABILITATE,
722
2
      SC_AC_OP_INVALIDATE
723
2
    };
724
14
    for (i = 0; i < 6; i++)
725
12
      idx[i] = df_idx[i];
726
23
  } else {
727
23
    const int ef_idx[6] = {
728
23
      SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
729
23
      SC_AC_OP_ERASE, SC_AC_OP_REHABILITATE,
730
23
      SC_AC_OP_INVALIDATE
731
23
    };
732
161
    for (i = 0; i < 6; i++)
733
138
      idx[i] = ef_idx[i];
734
23
  }
735
175
  for (i = 0; i < 6; i++)
736
150
    add_acl_entry(file, idx[i], buf[i]);
737
25
}
738
739
static void parse_sec_attr_44(sc_file_t *file, const u8 *buf, size_t len)
740
153
{
741
  /* OpenSc Operation values for each command operation-type */
742
153
  const int df_idx[8] = {  /* byte 1 = OpenSC type of AC Bit0,  byte 2 = OpenSC type of AC Bit1 ...*/
743
153
    SC_AC_OP_DELETE, SC_AC_OP_CREATE, SC_AC_OP_CREATE,
744
153
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
745
153
    SC_AC_OP_LOCK, SC_AC_OP_DELETE, -1};
746
153
  const int ef_idx[8] = {
747
153
    SC_AC_OP_READ, SC_AC_OP_UPDATE, SC_AC_OP_WRITE,
748
153
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
749
153
    -1, SC_AC_OP_ERASE, -1};
750
153
  const int efi_idx[8] = { /* internal EF used for RSA keys */
751
153
    SC_AC_OP_READ, SC_AC_OP_ERASE, SC_AC_OP_UPDATE,
752
153
    SC_AC_OP_INVALIDATE, SC_AC_OP_REHABILITATE,
753
153
    -1, SC_AC_OP_ERASE, -1};
754
755
153
  u8    bValue;
756
153
  int   i;
757
153
  int   iKeyRef = 0;
758
153
  int   iMethod;
759
153
  int   iPinCount;
760
153
  int   iOffset = 0;
761
153
  int   iOperation;
762
153
  const int*  p_idx;
763
764
  /* Check all sub-AC definitions within the total AC */
765
989
  while (len > 1 && (size_t)iOffset < len) { /* minimum length = 2 */
766
849
    size_t iACLen   = buf[iOffset] & 0x0F;
767
849
    if (iACLen >= len)
768
10
      break;
769
770
839
    iMethod = SC_AC_NONE;   /* default no authentication required */
771
772
839
    if (buf[iOffset] & 0X80) { /* AC in adaptive coding */
773
      /* Evaluates only the command-byte, not the optional P1/P2/Option bytes */
774
306
      size_t  iParmLen = 1;     /* command-byte is always present */
775
306
      size_t  iKeyLen  = 0;     /* Encryption key is optional */
776
777
306
      if (buf[iOffset]   & 0x20) iKeyLen++;
778
306
      if (buf[iOffset+1] & 0x40) iParmLen++;
779
306
      if (buf[iOffset+1] & 0x20) iParmLen++;
780
306
      if (buf[iOffset+1] & 0x10) iParmLen++;
781
306
      if (buf[iOffset+1] & 0x08) iParmLen++;
782
783
      /* Get KeyNumber if available */
784
306
      if(iKeyLen) {
785
162
        int iSC;
786
162
        if (len < 1 + iACLen)
787
0
          break;
788
162
        iSC = buf[iOffset+iACLen];
789
790
162
        switch( (iSC>>5) & 0x03 ){
791
13
        case 0:
792
13
          iMethod = SC_AC_TERM;   /* key authentication */
793
13
          break;
794
79
        case 1:
795
79
          iMethod = SC_AC_AUT;   /* key authentication  */
796
79
          break;
797
15
        case 2:
798
70
        case 3:
799
70
          iMethod = SC_AC_PRO;   /* secure messaging */
800
70
          break;
801
162
        }
802
162
        iKeyRef = iSC & 0x1F;     /* get key number */
803
162
      }
804
805
      /* Get PinNumber if available */
806
306
      if (iACLen > (1+iParmLen+iKeyLen)) {  /* check via total length if pin is present */
807
19
        if (len < 1+1+1+(size_t)iParmLen)
808
0
          break;
809
19
        iKeyRef = buf[iOffset+1+1+iParmLen];  /* PTL + AM-header + parameter-bytes */
810
19
        iMethod = SC_AC_CHV;
811
19
      }
812
813
      /* Convert SETCOS command to OpenSC command group */
814
306
      if (len < 1+2)
815
3
        break;
816
303
      switch(buf[iOffset+2]){
817
10
      case 0x2A:      /* crypto operation */
818
10
        iOperation = SC_AC_OP_CRYPTO;
819
10
        break;
820
9
      case 0x46:      /* key-generation operation */
821
9
        iOperation = SC_AC_OP_UPDATE;
822
9
        break;
823
284
      default:
824
284
        iOperation = SC_AC_OP_SELECT;
825
284
        break;
826
303
      }
827
303
      sc_file_add_acl_entry(file, iOperation, iMethod, iKeyRef);
828
303
    }
829
533
    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
533
      switch (file->type) {
834
121
      case SC_FILE_TYPE_DF:            /* DF */
835
121
        p_idx = df_idx;
836
121
        break;
837
85
      case SC_FILE_TYPE_INTERNAL_EF:   /* EF for RSA keys */
838
85
        p_idx = efi_idx;
839
85
        break;
840
327
      default:                         /* EF */
841
327
        p_idx = ef_idx;
842
327
        break;
843
533
      }
844
845
      /* Encryption key present ? */
846
533
      iPinCount = iACLen > 0 ? (int)iACLen - 1 : 0;
847
848
533
      if (buf[iOffset] & 0x20) {
849
355
        int iSC;
850
355
        if (len < 1 + (size_t)iACLen)
851
0
          break;
852
355
        iSC = buf[iOffset + iACLen];
853
854
355
        switch( (iSC>>5) & 0x03 ) {
855
36
        case 0:
856
36
          iMethod = SC_AC_TERM;   /* key authentication */
857
36
          break;
858
83
        case 1:
859
83
          iMethod = SC_AC_AUT;   /* key authentication  */
860
83
          break;
861
16
        case 2:
862
236
        case 3:
863
236
          iMethod = SC_AC_PRO;   /* secure messaging */
864
236
          break;
865
355
        }
866
355
        iKeyRef = iSC & 0x1F;     /* get key number */
867
868
355
        iPinCount--;        /* one byte used for keyReference  */
869
355
      }
870
871
      /* Pin present ? */
872
533
      if ( iPinCount > 0 ) {
873
74
        if (len < 1 + 2)
874
0
          break;
875
74
        iKeyRef = buf[iOffset + 2]; /* pin ref */
876
74
        iMethod = SC_AC_CHV;
877
74
      }
878
879
      /* Add AC for each command-operationType into OpenSc structure */
880
533
      bValue = buf[iOffset + 1];
881
4.79k
      for (i = 0; i < 8; i++) {
882
4.26k
        if((bValue & 1) && (p_idx[i] >= 0))
883
974
          sc_file_add_acl_entry(file, p_idx[i], iMethod, iKeyRef);
884
4.26k
        bValue >>= 1;
885
4.26k
      }
886
533
    }
887
    /* Current field treated, get next AC sub-field */
888
836
    iOffset += iACLen +1;   /* AC + PTL-byte */
889
836
    len     -= iACLen +1;
890
836
  }
891
153
}
892
893
static int setcos_select_file(sc_card_t *card,
894
            const sc_path_t *in_path, sc_file_t **file)
895
818
{
896
818
  int r;
897
898
818
  r = iso_ops->select_file(card, in_path, file);
899
818
  if (r)
900
583
    return r;
901
235
  if (file != NULL) {
902
190
    if (card->type == SC_CARD_TYPE_SETCOS_44 ||
903
184
        card->type == SC_CARD_TYPE_SETCOS_NIDEL ||
904
177
        SETCOS_IS_EID_APPLET(card))
905
153
      parse_sec_attr_44(*file, (*file)->sec_attr, (*file)->sec_attr_len);
906
37
    else
907
37
      parse_sec_attr(*file, (*file)->sec_attr, (*file)->sec_attr_len);
908
190
  }
909
235
  return 0;
910
818
}
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
185
{
937
185
  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
185
  if (r >= 0 && (card->type == SC_CARD_TYPE_SETCOS_44 ||
942
179
                 SETCOS_IS_EID_APPLET(card))) {
943
144
    const u8 *tag;
944
144
    size_t taglen = 1;
945
144
    tag = (u8 *) sc_asn1_find_tag(card->ctx, buf, buflen, 0x82, &taglen);
946
144
    if (tag != NULL && taglen == 1 && *tag == 0x11)
947
5
      file->type = SC_FILE_TYPE_INTERNAL_EF;
948
144
  }
949
950
185
  return r;
951
185
}
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
0
{
983
0
  int       r;
984
0
  struct sc_apdu      apdu;
985
986
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
987
988
0
  memset(&apdu, 0, sizeof(apdu));
989
0
  apdu.cse     = SC_APDU_CASE_2_SHORT;
990
0
  apdu.cla     = 0x00;
991
0
  apdu.ins     = 0xCA;      /* GET DATA */
992
0
  apdu.p1      = data_obj->P1;
993
0
  apdu.p2      = data_obj->P2;
994
0
  apdu.lc      = 0;
995
0
  apdu.datalen = 0;
996
0
  apdu.data    = data_obj->Data;
997
998
0
  apdu.le      = 256;
999
0
  apdu.resp    = data_obj->Data;
1000
0
  apdu.resplen = data_obj->DataLen;
1001
1002
0
  r = sc_transmit_apdu(card, &apdu);
1003
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1004
1005
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1006
0
  LOG_TEST_RET(card->ctx, r, "GET_DATA returned error");
1007
1008
0
  if (apdu.resplen > data_obj->DataLen)
1009
0
    r = SC_ERROR_WRONG_LENGTH;
1010
0
  else
1011
0
    data_obj->DataLen = apdu.resplen;
1012
1013
0
  LOG_FUNC_RETURN(card->ctx, r);
1014
0
}
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
0
{
1020
0
  struct  sc_apdu apdu;
1021
0
  u8  sbuf[SC_MAX_APDU_BUFFER_SIZE];
1022
0
  int r, len;
1023
1024
0
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1025
1026
  /* Setup key-generation parameters */
1027
0
  len = 0;
1028
0
  if (data->op_type == OP_TYPE_GENERATE)
1029
0
    sbuf[len++] = 0x92; /* algo ID: RSA CRT */
1030
0
  else
1031
0
    sbuf[len++] = 0x9A; /* algo ID: EXTERNALLY GENERATED RSA CRT */
1032
0
  sbuf[len++] = 0x00;
1033
0
  sbuf[len++] = data->mod_len / 256;  /* 2 bytes for modulus bitlength */
1034
0
  sbuf[len++] = data->mod_len % 256;
1035
1036
0
  sbuf[len++] = data->pubexp_len / 256;   /* 2 bytes for pubexp bitlength */
1037
0
  sbuf[len++] = data->pubexp_len % 256;
1038
0
  memcpy(sbuf + len, data->pubexp, BYTES4BITS(data->pubexp_len));
1039
0
  len += BYTES4BITS(data->pubexp_len);
1040
1041
0
  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
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, 0x00, 0x00);
1053
0
  apdu.cla = 0x00;
1054
0
  apdu.data = sbuf;
1055
0
  apdu.datalen = len;
1056
0
  apdu.lc = len;
1057
1058
0
  r = sc_transmit_apdu(card, &apdu);
1059
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1060
1061
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1062
0
  LOG_TEST_RET(card->ctx, r, "STORE/GENERATE_KEY returned error");
1063
1064
0
  LOG_FUNC_RETURN(card->ctx, r);
1065
0
}
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
5
{
1087
5
  if (card->type != SC_CARD_TYPE_SETCOS_44 && !SETCOS_IS_EID_APPLET(card))
1088
2
    return SC_ERROR_NOT_SUPPORTED;
1089
1090
3
  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
0
  case SC_CARDCTL_SETCOS_GETDATA:
1096
0
    return setcos_getdata(card,
1097
0
        (struct sc_cardctl_setcos_data_obj*) ptr);
1098
0
    break;
1099
0
  case SC_CARDCTL_SETCOS_GENERATE_STORE_KEY:
1100
0
    return setcos_generate_store_key(card,
1101
0
        (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
3
  }
1105
1106
3
  return SC_ERROR_NOT_SUPPORTED;
1107
3
}
1108
1109
static struct sc_card_driver *sc_get_driver(void)
1110
12.7k
{
1111
12.7k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
1112
1113
12.7k
  setcos_ops = *iso_drv->ops;
1114
12.7k
  setcos_ops.match_card = setcos_match_card;
1115
12.7k
  setcos_ops.init = setcos_init;
1116
12.7k
  if (iso_ops == NULL)
1117
1
    iso_ops = iso_drv->ops;
1118
12.7k
  setcos_ops.create_file = setcos_create_file;
1119
12.7k
  setcos_ops.set_security_env = setcos_set_security_env;
1120
12.7k
  setcos_ops.select_file = setcos_select_file;
1121
12.7k
  setcos_ops.list_files = setcos_list_files;
1122
12.7k
  setcos_ops.process_fci = setcos_process_fci;
1123
12.7k
  setcos_ops.construct_fci = setcos_construct_fci;
1124
12.7k
  setcos_ops.card_ctl = setcos_card_ctl;
1125
1126
12.7k
  return &setcos_drv;
1127
12.7k
}
1128
1129
struct sc_card_driver *sc_get_setcos_driver(void)
1130
12.7k
{
1131
12.7k
  return sc_get_driver();
1132
12.7k
}