Coverage Report

Created: 2026-01-07 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/card-flex.c
Line
Count
Source
1
/*
2
 * card-flex.c: Support for Schlumberger cards
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <stdlib.h>
26
#include <string.h>
27
28
#include "internal.h"
29
#include "cardctl.h"
30
31
1.26k
#define FLAG_KEYGEN   0x80000000
32
48
#define IS_CYBERFLEX(card)  (card->type == SC_CARD_TYPE_FLEX_CYBER)
33
34
static const struct sc_atr_table flex_atrs[] = {
35
  /* Cryptoflex */
36
  /* 8k win2000 */
37
  { "3b:95:15:40:20:68:01:02:00:00", NULL, "Cryptoflex 8K", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
38
  /* 8k */
39
  { "3B:95:15:40:FF:68:01:02:02:01", NULL, "Cryptoflex 8K", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
40
  /* 8k */
41
  { "3B:95:15:40:FF:68:01:02:02:04", NULL, "Cryptoflex 8K", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
42
  /* 8k */
43
  { "3B:85:40:20:68:01:01:05:01", NULL, "Cryptoflex 8K", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
44
  /* 16k */
45
  { "3B:95:94:40:FF:63:01:01:02:01", NULL, "Cryptoflex 16K", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
46
  /* "16K+SS1" alias Cryptoflex 16 card with Standard Softmask V1 */
47
  /* (taken from Cryptoflex Card Programmers Guide 4.5 Page xviii) */
48
  /* last two bytes can be ignored - version of the softmask */
49
  { "3B:95:15:40:FF:63:01:01:02:01", "FF:FF:FF:FF:FF:FF:FF:FF:00:00",
50
    "Cryptoflex 16K", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
51
  /* 32K v4 */
52
  /* "32K+SS1" alias Cryptoflex 32 card with Standard Softmask V1 */
53
  /* (taken from Cryptoflex Card Programmers Guide 4.5 Page xviii) */
54
  /* last two bytes can be ignored - version of the softmask */
55
  { "3B:95:18:40:FF:64:02:01:01:02","FF:FF:FF:FF:FF:FF:FF:FF:00:00",
56
    "Cryptoflex 32K v4", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
57
  /* "32K+e-gate" alias Cryptoflex e-gate 32K card */
58
  /* (taken from Cryptoflex Card Programmers Guide 4.5 Page xviii) */
59
  /* last two bytes can be ignored - version of the softmask */
60
  { "3B:95:18:40:FF:62:01:01:00:00", "FF:FF:FF:FF:FF:FF:FF:FF:00:00",
61
    "Cryptoflex e-gate 32K", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
62
  /* 32K e-gate */
63
  { "3B:95:18:40:FF:62:01:02:01:04", NULL, "Cryptoflex 32K e-gate", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
64
  /* 32K e-gate v4 */
65
  { "3B:95:18:40:FF:62:04:01:01:05", NULL, "Cryptoflex 32K e-gate v4", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
66
67
  /* new cryptoflex 32k card - atr looks very similar to old 8k card */
68
  { "3b:95:15:40:ff:68:01:02:45:47", NULL, "Cryptoflex 32K", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
69
70
  { "3B:E2:00:00:40:20:49:06", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
71
  /* + full DES option */
72
  { "3B:E2:00:00:40:20:49:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, 0, NULL },
73
  /* + Key Generation */
74
  { "3B:E2:00:00:40:20:49:07", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
75
  /* + Key Generation */
76
  { "3B:85:40:20:68:01:01:03:05", NULL, "Cryptoflex", SC_CARD_TYPE_FLEX_CRYPTO, FLAG_KEYGEN, NULL },
77
78
  /* Multiflex */
79
  /* 3K */
80
  { "3B:02:14:50", NULL, "Multiflex 3K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
81
  /* 4K */
82
  { "3B:19:14:55:90:01:02:01:00:05:04:B0", NULL, "Multiflex 4K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
83
  /* 8K */
84
  { "3B:32:15:00:06:80", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
85
  /* 8K + full DES option */
86
  { "3B:32:15:00:06:95", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
87
  /* 8K */
88
  { "3B:19:14:59:01:01:0F:01:00:05:08:B0", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
89
  /* 8K */
90
  { "3B:19:14:55:90:01:01:01:00:05:08:B0", NULL, "Multiflex 8K", SC_CARD_TYPE_FLEX_MULTI, 0, NULL },
91
92
  /* Cyberflex Access */
93
  /* Crypto */
94
  { "3B:16:94:81:10:06:01:81:3F", NULL, "Cyberflex Access", SC_CARD_TYPE_FLEX_CYBER, 0, NULL },
95
  /* Aug. Crypto */
96
  { "3B:16:94:81:10:06:01:81:2F", NULL, "Cyberflex Access", SC_CARD_TYPE_FLEX_CYBER, 0, NULL },
97
  { NULL, NULL, NULL, 0, 0, NULL }
98
};
99
100
struct flex_private_data {
101
  int rsa_key_ref;
102
103
  /* Support card variations without having to
104
   * do the if (card->type ...) thing
105
   * all the time */
106
  u8  aak_key_ref;
107
};
108
109
3.99k
#define DRV_DATA(card)  ((struct flex_private_data *) (card)->drv_data)
110
111
static struct sc_card_operations cryptoflex_ops;
112
static struct sc_card_operations cyberflex_ops;
113
static struct sc_card_operations *iso_ops;
114
static struct sc_card_driver cryptoflex_drv = {
115
  "Schlumberger Multiflex/Cryptoflex",
116
  "flex",
117
  &cryptoflex_ops,
118
  NULL, 0, NULL
119
};
120
static struct sc_card_driver cyberflex_drv = {
121
  "Schlumberger Cyberflex",
122
  "cyberflex",
123
  &cyberflex_ops,
124
  NULL, 0, NULL
125
};
126
127
static int flex_finish(sc_card_t *card)
128
1.26k
{
129
1.26k
  free(card->drv_data);
130
1.26k
  return 0;
131
1.26k
}
132
133
static int cryptoflex_match_card(sc_card_t *card)
134
105k
{
135
105k
  int i;
136
137
105k
  i = _sc_match_atr(card, flex_atrs, NULL);
138
105k
  if (i < 0)
139
104k
    return 0;
140
1.00k
  switch (flex_atrs[i].type) {
141
1.00k
  case SC_CARD_TYPE_FLEX_CRYPTO:
142
1.00k
  case SC_CARD_TYPE_FLEX_MULTI:
143
1.00k
    card->name = flex_atrs[i].name;
144
1.00k
    card->type = flex_atrs[i].type;
145
1.00k
    card->flags = flex_atrs[i].flags;
146
1.00k
    return 1;
147
1.00k
  }
148
0
  return 0;
149
1.00k
}
150
151
static int cyberflex_match_card(sc_card_t *card)
152
105k
{
153
105k
  int i;
154
155
105k
  i = _sc_match_atr(card, flex_atrs, NULL);
156
105k
  if (i < 0)
157
104k
    return 0;
158
1.26k
  switch (flex_atrs[i].type) {
159
262
  case SC_CARD_TYPE_FLEX_CYBER:
160
262
    card->name = flex_atrs[i].name;
161
262
    card->type = flex_atrs[i].type;
162
262
    card->flags = flex_atrs[i].flags;
163
262
    return 1;
164
1.26k
  }
165
1.00k
  return 0;
166
1.26k
}
167
168
static int flex_init(sc_card_t *card)
169
1.26k
{
170
1.26k
  struct flex_private_data *data;
171
172
1.26k
  if (!(data = malloc(sizeof(*data))))
173
0
    return SC_ERROR_OUT_OF_MEMORY;
174
1.26k
  card->drv_data = data;
175
176
1.26k
  card->cla = 0xC0;
177
1.26k
  data->aak_key_ref = 1;
178
179
  /* Override Cryptoflex defaults for specific card types */
180
1.26k
  switch (card->type) {
181
262
  case SC_CARD_TYPE_FLEX_CYBER:
182
262
    card->cla = 0x00;
183
262
    data->aak_key_ref = 0;
184
262
    break;
185
1.26k
  }
186
187
  /* FIXME: Card type detection */
188
1.26k
  if (1) {
189
1.26k
    unsigned long flags;
190
191
1.26k
    flags = SC_ALGORITHM_RSA_RAW;
192
1.26k
    flags |= SC_ALGORITHM_RSA_HASH_NONE;
193
1.26k
    if (card->flags & FLAG_KEYGEN)
194
973
      flags |= SC_ALGORITHM_ONBOARD_KEY_GEN;
195
196
1.26k
    _sc_card_add_rsa_alg(card, 512, flags, 0);
197
1.26k
    _sc_card_add_rsa_alg(card, 768, flags, 0);
198
1.26k
    _sc_card_add_rsa_alg(card, 1024, flags, 0);
199
1.26k
    _sc_card_add_rsa_alg(card, 2048, flags, 0);
200
1.26k
  }
201
202
  /* SCardTransmit failed: 8010002f
203
   * this can be solved with a small delay. */
204
1.26k
  msleep(100);
205
206
  /* State that we have an RNG */
207
1.26k
  card->caps |= SC_CARD_CAP_RNG;
208
209
1.26k
  return 0;
210
1.26k
}
211
212
static void
213
add_acl_entry(sc_card_t *card, sc_file_t *file, unsigned int op, u8 nibble)
214
3.98k
{
215
3.98k
  struct flex_private_data *prv = DRV_DATA(card);
216
217
3.98k
  switch (nibble) {
218
1.22k
  case 0:
219
1.22k
    sc_file_add_acl_entry(file, op, SC_AC_NONE, SC_AC_KEY_REF_NONE);
220
1.22k
    break;
221
317
  case 1:
222
317
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 1);
223
317
    break;
224
254
  case 2:
225
254
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 2);
226
254
    break;
227
157
  case 3:
228
157
    sc_file_add_acl_entry(file, op, SC_AC_PRO, SC_AC_KEY_REF_NONE);
229
157
    break;
230
221
  case 4:
231
    /* Assume the key is the AAK */
232
221
    sc_file_add_acl_entry(file, op, SC_AC_AUT, prv->aak_key_ref);
233
221
    break;
234
296
  case 6:
235
296
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 1);
236
296
    sc_file_add_acl_entry(file, op, SC_AC_PRO, SC_AC_KEY_REF_NONE);
237
296
    break;
238
199
  case 7:
239
199
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 2);
240
199
    sc_file_add_acl_entry(file, op, SC_AC_PRO, SC_AC_KEY_REF_NONE);
241
199
    break;
242
134
  case 8:
243
134
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 1);
244
    /* Assume the key is the AAK */
245
134
    sc_file_add_acl_entry(file, op, SC_AC_AUT, prv->aak_key_ref);
246
134
    break;
247
265
  case 9:
248
265
    sc_file_add_acl_entry(file, op, SC_AC_CHV, 2);
249
    /* Assume the key is the AAK */
250
265
    sc_file_add_acl_entry(file, op, SC_AC_AUT, prv->aak_key_ref);
251
265
    break;
252
498
  case 15:
253
498
    sc_file_add_acl_entry(file, op, SC_AC_NEVER, SC_AC_KEY_REF_NONE);
254
498
    break;
255
411
  default:
256
411
    sc_file_add_acl_entry(file, op, SC_AC_UNKNOWN, SC_AC_KEY_REF_NONE);
257
411
    break;
258
3.98k
  }
259
3.98k
}
260
261
static int
262
cryptoflex_get_ac_keys(sc_card_t *card, sc_file_t *file)
263
866
{
264
866
  return 0;
265
866
}
266
267
static int
268
cryptoflex_process_file_attrs(sc_card_t *card, sc_file_t *file,
269
      const u8 *buf, size_t buflen)
270
1.01k
{
271
1.01k
  sc_context_t *ctx = card->ctx;
272
1.01k
  const u8 *p = buf + 2;
273
1.01k
  u8 b1, b2;
274
1.01k
  int is_mf = 0;
275
276
1.01k
  if (buflen < 14)
277
0
    return -1;
278
1.01k
  b1 = *p++;
279
1.01k
  b2 = *p++;
280
1.01k
  file->size = (b1 << 8) + b2;
281
1.01k
  b1 = *p++;
282
1.01k
  b2 = *p++;
283
1.01k
  file->id = (b1 << 8) + b2;
284
1.01k
  if (file->id == 0x3F00)
285
65
    is_mf = 1;
286
1.01k
  switch (*p) {
287
260
  case 0x01:
288
260
    file->type = SC_FILE_TYPE_WORKING_EF;
289
260
    file->ef_structure = SC_FILE_EF_TRANSPARENT;
290
260
    break;
291
299
  case 0x02:
292
299
    file->type = SC_FILE_TYPE_WORKING_EF;
293
299
    file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
294
299
    break;
295
132
  case 0x04:
296
132
    file->type = SC_FILE_TYPE_WORKING_EF;
297
132
    file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
298
132
    break;
299
124
  case 0x06:
300
124
    file->type = SC_FILE_TYPE_WORKING_EF;
301
124
    file->ef_structure = SC_FILE_EF_CYCLIC;
302
124
    break;
303
51
  case 0x38:
304
51
    file->type = SC_FILE_TYPE_DF;
305
51
    break;
306
151
  default:
307
151
    sc_log(ctx,  "invalid file type: 0x%02X\n", *p);
308
151
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
309
1.01k
  }
310
866
  p += 2;
311
866
  if (file->type == SC_FILE_TYPE_DF) {
312
51
    add_acl_entry(card, file, SC_AC_OP_LIST_FILES, (u8)(p[0] >> 4));
313
51
    add_acl_entry(card, file, SC_AC_OP_DELETE, (u8)(p[1] >> 4));
314
51
    add_acl_entry(card, file, SC_AC_OP_CREATE, (u8)(p[1] & 0x0F));
315
815
  } else { /* EF */
316
815
    add_acl_entry(card, file, SC_AC_OP_READ, (u8)(p[0] >> 4));
317
815
    switch (file->ef_structure) {
318
260
    case SC_FILE_EF_TRANSPARENT:
319
260
      add_acl_entry(card, file, SC_AC_OP_UPDATE, (u8)(p[0] & 0x0F));
320
260
      break;
321
299
    case SC_FILE_EF_LINEAR_FIXED:
322
431
    case SC_FILE_EF_LINEAR_VARIABLE:
323
431
      add_acl_entry(card, file, SC_AC_OP_UPDATE, (u8)(p[0] & 0x0F));
324
431
      break;
325
124
    case SC_FILE_EF_CYCLIC:
326
124
      break;
327
815
    }
328
815
  }
329
866
  if (file->type != SC_FILE_TYPE_DF || is_mf) {
330
838
    add_acl_entry(card, file, SC_AC_OP_REHABILITATE, (u8)(p[2] >> 4));
331
838
    add_acl_entry(card, file, SC_AC_OP_INVALIDATE, (u8)(p[2] & 0x0F));
332
838
  }
333
866
  p += 3;
334
866
  if (*p)
335
603
    file->status = SC_FILE_STATUS_ACTIVATED;
336
263
  else
337
263
    file->status = SC_FILE_STATUS_INVALIDATED;
338
339
866
  return cryptoflex_get_ac_keys(card, file);
340
866
}
341
342
static int
343
cyberflex_process_file_attrs(sc_card_t *card, sc_file_t *file,
344
      const u8 *buf, size_t buflen)
345
201
{
346
201
  sc_context_t *ctx = card->ctx;
347
201
  const u8 *p = buf + 2;
348
201
  const u8 *pos;
349
201
  u8 b1, b2;
350
201
  int is_mf = 0;
351
352
201
  if (buflen < 14)
353
0
    return -1;
354
201
  b1 = *p++;
355
201
  b2 = *p++;
356
201
  file->size = (b1 << 8) + b2;
357
201
  b1 = *p++;
358
201
  b2 = *p++;
359
201
  file->id = (b1 << 8) + b2;
360
201
  switch (*p) {
361
15
  case 0x01:
362
15
    is_mf = 1;
363
15
    break;
364
111
  case 0x02:
365
111
    file->type = SC_FILE_TYPE_DF;
366
111
    break;
367
50
  case 0x04:
368
50
    file->type = SC_FILE_TYPE_WORKING_EF;
369
50
    break;
370
25
  default:
371
25
    sc_log(ctx,  "invalid file type: 0x%02X\n", *p);
372
25
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
373
201
  }
374
375
176
  if (is_mf) {
376
15
    sc_file_add_acl_entry(file, SC_AC_OP_LIST_FILES, SC_AC_AUT, 0);
377
15
    sc_file_add_acl_entry(file, SC_AC_OP_DELETE, SC_AC_AUT, 0);
378
15
    sc_file_add_acl_entry(file, SC_AC_OP_CREATE, SC_AC_AUT, 0);
379
161
  } else {
380
161
    p += 2;
381
161
    if (file->type == SC_FILE_TYPE_DF) {
382
111
      add_acl_entry(card, file, SC_AC_OP_LIST_FILES, (u8)(p[0] >> 4));
383
111
      add_acl_entry(card, file, SC_AC_OP_DELETE, (u8)(p[1] >> 4));
384
111
      add_acl_entry(card, file, SC_AC_OP_CREATE, (u8)(p[1] & 0x0F));
385
111
    } else { /* EF */
386
50
      add_acl_entry(card, file, SC_AC_OP_READ, (u8)(p[0] >> 4));
387
50
    }
388
161
  }
389
176
  if (file->type != SC_FILE_TYPE_DF) {
390
65
    add_acl_entry(card, file, SC_AC_OP_REHABILITATE, (u8)(p[2] >> 4));
391
65
    add_acl_entry(card, file, SC_AC_OP_INVALIDATE, (u8)(p[2] & 0x0F));
392
65
  }
393
176
  pos = p;
394
176
  p += 3;
395
176
  if (*p++)
396
113
    file->status = SC_FILE_STATUS_ACTIVATED;
397
63
  else
398
63
    file->status = SC_FILE_STATUS_INVALIDATED;
399
176
  p++;
400
176
  if (0 == is_mf) {
401
161
    p++;
402
161
    switch (*p) {
403
82
    case  0x00:
404
82
      file->ef_structure = SC_FILE_EF_TRANSPARENT;
405
82
      break;
406
20
    case  0x01:
407
20
      file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
408
20
      break;
409
30
    case  0x02:
410
30
      file->ef_structure = SC_FILE_EF_LINEAR_VARIABLE;
411
30
      break;
412
2
    case  0x03:
413
2
      file->ef_structure = SC_FILE_EF_CYCLIC;
414
2
      break;
415
6
    case  0x04:
416
6
      break;
417
21
    default:
418
21
      sc_log(ctx,  "invalid file type: 0x%02X\n", *p);
419
21
      return SC_ERROR_UNKNOWN_DATA_RECEIVED;
420
161
    }
421
140
    switch (file->ef_structure) {
422
82
    case SC_FILE_EF_TRANSPARENT:
423
82
      add_acl_entry(card, file, SC_AC_OP_UPDATE, (u8)(pos[0] & 0x0F));
424
82
      break;
425
20
    case SC_FILE_EF_LINEAR_FIXED:
426
50
    case SC_FILE_EF_LINEAR_VARIABLE:
427
50
      add_acl_entry(card, file, SC_AC_OP_UPDATE, (u8)(pos[0] & 0x0F));
428
50
      break;
429
2
    case SC_FILE_EF_CYCLIC:
430
2
      break;
431
140
    }
432
140
  }
433
155
  return 0;
434
176
}
435
436
static int select_file_id(sc_card_t *card, const u8 *buf, size_t buflen,
437
        u8 p1, sc_file_t **file_out)
438
9.38k
{
439
9.38k
  int r;
440
9.38k
  sc_apdu_t apdu;
441
9.38k
        u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
442
9.38k
        sc_file_t *file;
443
444
9.38k
  sc_log(card->ctx,  "called, p1=%u\n", p1);
445
9.38k
  sc_log_hex(card->ctx, "path", buf, buflen);
446
447
9.38k
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, p1, 0);
448
9.38k
  apdu.resp = rbuf;
449
9.38k
  apdu.resplen = sizeof(rbuf);
450
9.38k
  apdu.datalen = buflen;
451
9.38k
  apdu.data = buf;
452
9.38k
  apdu.lc = buflen;
453
9.38k
  apdu.le = 252;
454
455
  /* No need to get file information, if file is NULL. */
456
9.38k
  if (file_out == NULL) {
457
7.62k
    apdu.cse = SC_APDU_CASE_3_SHORT;
458
7.62k
    apdu.le = 0;
459
7.62k
  }
460
9.38k
  r = sc_transmit_apdu(card, &apdu);
461
9.38k
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
462
9.27k
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
463
9.27k
  LOG_TEST_RET(card->ctx, r, "Card returned error");
464
465
4.57k
  if (file_out == NULL)
466
3.11k
    return 0;
467
468
1.46k
  if (apdu.resplen < 14)
469
183
    return SC_ERROR_UNKNOWN_DATA_RECEIVED;
470
1.27k
  if (apdu.resp[0] == 0x6F) {
471
60
    sc_log(card->ctx,  "unsupported: card returned FCI\n");
472
60
    return SC_ERROR_UNKNOWN_DATA_RECEIVED; /* FIXME */
473
60
  }
474
1.21k
  file = sc_file_new();
475
1.21k
  if (file == NULL)
476
1.21k
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
477
478
  /* We abuse process_fci here even though it's not the real FCI. */
479
1.21k
  r = card->ops->process_fci(card, file, apdu.resp, apdu.resplen);
480
1.21k
  if (r) {
481
197
    sc_file_free(file);
482
197
    return r;
483
197
  }
484
485
1.02k
  *file_out = file;
486
1.02k
  return 0;
487
1.21k
}
488
489
static int flex_select_file(sc_card_t *card, const sc_path_t *path,
490
           sc_file_t **file_out)
491
7.09k
{
492
7.09k
  int r;
493
7.09k
  const u8 *pathptr = path->value;
494
7.09k
  size_t pathlen = path->len;
495
7.09k
  int locked = 0;
496
7.09k
  u8 p1 = 0;
497
498
7.09k
  switch (path->type) {
499
4.54k
  case SC_PATH_TYPE_PATH:
500
4.54k
    if ((pathlen & 1) != 0) /* not divisible by 2 */
501
0
      return SC_ERROR_INVALID_ARGUMENTS;
502
4.54k
    if (pathlen == 0)
503
13
      return 0;
504
4.52k
    if (pathlen != 2 || memcmp(pathptr, "\x3F\x00", 2) != 0) {
505
4.41k
      locked = 1;
506
4.41k
      r = sc_lock(card);
507
4.41k
      LOG_TEST_RET(card->ctx, r, "sc_lock() failed");
508
4.41k
      if (memcmp(pathptr, "\x3F\x00", 2) != 0) {
509
478
        r = select_file_id(card, (const u8 *) "\x3F\x00", 2, 0, NULL);
510
478
        if (r)
511
247
          sc_unlock(card);
512
478
        LOG_TEST_RET(card->ctx, r, "Unable to select Master File (MF)");
513
478
      }
514
6.26k
      while (pathlen > 2) {
515
4.41k
        r = select_file_id(card, pathptr, 2, 0, NULL);
516
4.41k
        if (r)
517
2.30k
          sc_unlock(card);
518
4.41k
        LOG_TEST_RET(card->ctx, r, "Unable to select DF");
519
2.10k
        pathptr += 2;
520
2.10k
        pathlen -= 2;
521
2.10k
      }
522
4.16k
    }
523
1.97k
    break;
524
2.49k
  case SC_PATH_TYPE_DF_NAME:
525
2.49k
    p1 = 0x04;
526
2.49k
    break;
527
64
  case SC_PATH_TYPE_FILE_ID:
528
64
    if (pathlen != 2)
529
31
      return SC_ERROR_INVALID_ARGUMENTS;
530
33
    break;
531
7.09k
  }
532
4.49k
  r = select_file_id(card, pathptr, pathlen, p1, file_out);
533
4.49k
  if (locked)
534
1.85k
    sc_unlock(card);
535
4.49k
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, r);
536
4.49k
}
537
538
static int cryptoflex_list_files(sc_card_t *card, u8 *buf, size_t buflen)
539
53
{
540
53
  sc_apdu_t apdu;
541
53
  u8 rbuf[4];
542
53
  int r;
543
53
  size_t count = 0;
544
545
53
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA8, 0, 0);
546
53
  apdu.cla = 0xF0;
547
53
  apdu.le = 4;
548
53
  apdu.resplen = 4;
549
53
  apdu.resp = rbuf;
550
621
  while (buflen > 2) {
551
621
    r = sc_transmit_apdu(card, &apdu);
552
621
    if (r)
553
6
      return r;
554
615
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x82)
555
1
      break;
556
614
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
557
614
    if (r)
558
43
      return r;
559
571
    if (apdu.resplen != 4) {
560
3
      sc_log(card->ctx,
561
3
         "expected 4 bytes, got %"SC_FORMAT_LEN_SIZE_T"u.\n",
562
3
         apdu.resplen);
563
3
      return SC_ERROR_UNKNOWN_DATA_RECEIVED;
564
3
    }
565
568
    memcpy(buf, rbuf + 2, 2);
566
568
    buf += 2;
567
568
    count += 2;
568
568
    buflen -= 2;
569
568
  }
570
1
  return (int)count;
571
53
}
572
573
/*
574
 * The Cyberflex LIST FILES command is slightly different...
575
 */
576
static int cyberflex_list_files(sc_card_t *card, u8 *buf, size_t buflen)
577
0
{
578
0
  sc_apdu_t apdu;
579
0
  u8 rbuf[6];
580
0
  int r, p2 = 0;
581
0
  size_t count = 0;
582
583
0
  while (buflen > 2) {
584
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xA8, 0, ++p2);
585
0
    apdu.le = 6;
586
0
    apdu.resplen = 6;
587
0
    apdu.resp = rbuf;
588
0
    r = sc_transmit_apdu(card, &apdu);
589
0
    if (r)
590
0
      return r;
591
0
    if (apdu.sw1 == 0x6A && apdu.sw2 == 0x83)
592
0
      break;
593
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
594
0
    if (r)
595
0
      return r;
596
0
    if (apdu.resplen != 6) {
597
0
      sc_log(card->ctx,
598
0
         "expected 6 bytes, got %"SC_FORMAT_LEN_SIZE_T"u.\n",
599
0
         apdu.resplen);
600
0
      return SC_ERROR_UNKNOWN_DATA_RECEIVED;
601
0
    }
602
0
    memcpy(buf, rbuf + 4, 2);
603
0
    buf += 2;
604
0
    count += 2;
605
0
    buflen -= 2;
606
0
  }
607
0
  return (int)count;
608
0
}
609
610
static int flex_delete_file(sc_card_t *card, const sc_path_t *path)
611
21
{
612
21
  sc_apdu_t apdu;
613
21
  int r;
614
615
21
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
616
21
  if (path->type != SC_PATH_TYPE_FILE_ID && path->len != 2) {
617
0
    sc_log(card->ctx,  "File type has to be SC_PATH_TYPE_FILE_ID\n");
618
0
    LOG_FUNC_RETURN(card->ctx, SC_ERROR_INVALID_ARGUMENTS);
619
0
  }
620
21
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE4, 0x00, 0x00);
621
21
  if (!IS_CYBERFLEX(card))
622
19
    apdu.cla = 0xF0; /* Override CLA byte */
623
21
  apdu.data = path->value;
624
21
  apdu.lc = 2;
625
21
  apdu.datalen = 2;
626
627
21
  r = sc_transmit_apdu(card, &apdu);
628
21
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
629
20
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
630
21
}
631
632
static int acl_to_ac_nibble(const sc_acl_entry_t *e)
633
136
{
634
136
  if (e == NULL)
635
0
    return -1;
636
136
  if (e->next != NULL)  /* FIXME */
637
1
    return -1;
638
135
  switch (e->method) {
639
73
  case SC_AC_NONE:
640
73
    return 0x00;
641
27
  case SC_AC_CHV:
642
27
    switch (e->key_ref) {
643
26
    case 1:
644
26
      return 0x01;
645
0
      break;
646
0
    case 2:
647
0
      return 0x02;
648
0
      break;
649
27
    }
650
1
    return -1;
651
1
  case SC_AC_PRO:
652
1
    return 0x03;
653
1
  case SC_AC_AUT:
654
1
    return 0x04;
655
3
  case SC_AC_NEVER:
656
3
    return 0x0f;
657
135
  }
658
30
  return -1;
659
135
}
660
661
static int acl_to_keynum_nibble(const sc_acl_entry_t *e)
662
104
{
663
207
  while (e != NULL && e->method != SC_AC_AUT)
664
103
    e = e->next;
665
104
  if (e == NULL || e->key_ref == SC_AC_KEY_REF_NONE)
666
103
    return 0;
667
668
1
  return e->key_ref & 0x0F;
669
104
}
670
671
static int
672
cryptoflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
673
         u8 *buf, size_t *buflen)
674
49
{
675
49
  u8 *p = buf;
676
49
  int r, i;
677
49
  int ops[6];
678
679
49
  p[0] = 0xFF;
680
49
  p[1] = 0xFF;
681
49
  p[2] = file->size >> 8;
682
49
  p[3] = file->size & 0xFF;
683
49
  p[4] = file->id >> 8;
684
49
  p[5] = file->id & 0xFF;
685
49
  if (file->type == SC_FILE_TYPE_DF)
686
48
    p[6] = 0x38;
687
1
  else
688
1
    switch (file->ef_structure) {
689
0
    case SC_FILE_EF_TRANSPARENT:
690
0
      p[6] = 0x01;
691
0
      break;
692
0
    case SC_FILE_EF_LINEAR_FIXED:
693
0
      p[6] = 0x02;
694
0
      break;
695
0
    case SC_FILE_EF_LINEAR_VARIABLE:
696
0
      p[6] = 0x04;
697
0
      break;
698
0
    case SC_FILE_EF_CYCLIC:
699
0
      p[6] = 0x06;
700
0
      break;
701
1
    default:
702
1
      sc_log(card->ctx,  "Invalid EF structure\n");
703
1
      return -1;
704
1
    }
705
48
  p[7] = 0xFF;  /* allow Decrease and Increase */
706
336
  for (i = 0; i < 6; i++)
707
288
    ops[i] = -1;
708
48
  if (file->type == SC_FILE_TYPE_DF) {
709
48
    ops[0] = SC_AC_OP_LIST_FILES;
710
48
    ops[2] = SC_AC_OP_DELETE;
711
48
    ops[3] = SC_AC_OP_CREATE;
712
48
  } else {
713
0
    ops[0] = SC_AC_OP_READ;
714
0
    ops[1] = SC_AC_OP_UPDATE;
715
0
    ops[2] = SC_AC_OP_READ;
716
0
    ops[3] = SC_AC_OP_UPDATE;
717
0
    ops[4] = SC_AC_OP_REHABILITATE;
718
0
    ops[5] = SC_AC_OP_INVALIDATE;
719
0
  }
720
48
  p[8] = p[9] = p[10] = 0;
721
48
  p[13] = p[14] = p[15] = 0; /* Key numbers */
722
231
  for (i = 0; i < 6; i++) {
723
215
    const sc_acl_entry_t *entry;
724
215
    if (ops[i] == -1)
725
79
      continue;
726
136
    entry = sc_file_get_acl_entry(file, ops[i]);
727
136
    r = acl_to_ac_nibble(entry);
728
136
    LOG_TEST_RET(card->ctx, r, "Invalid ACL value");
729
    /* Do some magic to get the nibbles right */
730
104
    p[8 + i/2] |= (r & 0x0F) << (((i+1) % 2) * 4);
731
104
    r = acl_to_keynum_nibble(entry);
732
104
    p[13 + i/2] |= (r & 0x0F) << (((i+1) % 2) * 4);
733
104
  }
734
16
  p[11] = (file->status == SC_FILE_STATUS_INVALIDATED) ? 0x00 : 0x01;
735
16
  if (file->type != SC_FILE_TYPE_DF &&
736
0
      (file->ef_structure == SC_FILE_EF_LINEAR_FIXED ||
737
0
      file->ef_structure == SC_FILE_EF_CYCLIC))
738
0
    p[12] = 0x04;
739
16
  else
740
16
    p[12] = 0x03;
741
16
  if (p[12] == 0x04) {
742
0
    p[16] = file->record_length;
743
0
    *buflen = 17;
744
0
  } else
745
16
    *buflen = 16;
746
747
16
  return 0;
748
48
}
749
750
static int
751
cyberflex_construct_file_attrs(sc_card_t *card, const sc_file_t *file,
752
         u8 *buf, size_t *buflen)
753
6
{
754
6
  u8 *p = buf;
755
6
  size_t size = file->size;
756
757
  /* cyberflex wants input parameters length added */
758
6
  switch (file->type) {
759
1
  case SC_FILE_TYPE_DF:
760
1
    size += 24;
761
1
    break;
762
4
  case SC_FILE_TYPE_WORKING_EF:
763
5
  default:
764
5
    size += 16;
765
5
    break;
766
6
  }
767
768
6
  sc_log(card->ctx,
769
6
     "Creating %02x:%02x, size %"SC_FORMAT_LEN_SIZE_T"u %02"SC_FORMAT_LEN_SIZE_T"x:%02"SC_FORMAT_LEN_SIZE_T"x\n",
770
6
     file->id >> 8,
771
6
     file->id & 0xFF,
772
6
     size,
773
6
     size >> 8,
774
6
     size & 0xFF);
775
776
6
  p[0] = size >> 8;
777
6
  p[1] = size & 0xFF;
778
6
  p[2] = file->id >> 8;
779
6
  p[3] = file->id & 0xFF;
780
6
  if (file->type == SC_FILE_TYPE_DF)
781
1
    p[4] = 0x20;
782
5
  else
783
5
    switch (file->ef_structure) {
784
3
    case SC_FILE_EF_TRANSPARENT:
785
3
      p[4] = 0x02;
786
3
      break;
787
0
    case SC_FILE_EF_LINEAR_FIXED:
788
0
      p[4] = 0x0C;
789
0
      break;
790
0
    case SC_FILE_EF_LINEAR_VARIABLE:
791
0
      p[4] = 0x19;
792
0
      break;
793
0
    case SC_FILE_EF_CYCLIC:
794
0
      p[4] = 0x1D;
795
0
      break;
796
2
    default:
797
2
      sc_log(card->ctx,  "Invalid EF structure\n");
798
2
      return -1;
799
5
    }
800
4
  p[5] = 0x01;  /* status?? */
801
4
  p[6] = p[7] = 0;
802
803
4
  *buflen = 16;
804
805
4
  p[8] = p[9] = p[11] = 0xFF;
806
4
  p[10] = p[12] = p[13] = p[14] = p[15] = 0x00;
807
4
  return 0;
808
6
}
809
810
static int flex_create_file(sc_card_t *card, sc_file_t *file)
811
55
{
812
55
  u8 sbuf[18];
813
55
  size_t sendlen;
814
55
  int r, rec_nr;
815
55
  sc_apdu_t apdu;
816
817
  /* Build the file attrs. These are not the real FCI bytes
818
   * in the standard sense, but its a convenient way of
819
   * abstracting the Cryptoflex/Cyberflex differences */
820
55
  r = card->ops->construct_fci(card, file, sbuf, &sendlen);
821
55
  if (r) {
822
35
    sc_log(card->ctx,  "File structure encoding failed.\n");
823
35
    return SC_ERROR_INVALID_ARGUMENTS;
824
35
  }
825
20
  if (file->type != SC_FILE_TYPE_DF && file->ef_structure != SC_FILE_EF_TRANSPARENT)
826
0
    rec_nr = (int)file->record_count;
827
20
  else
828
20
    rec_nr = 0;
829
20
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xE0, 0x00, rec_nr);
830
20
  if (!IS_CYBERFLEX(card))
831
16
    apdu.cla = 0xF0;
832
20
  apdu.data = sbuf;
833
20
  apdu.datalen = sendlen;
834
20
  apdu.lc = sendlen;
835
836
20
  r = sc_transmit_apdu(card, &apdu);
837
20
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
838
19
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
839
19
  LOG_TEST_RET(card->ctx, r, "Card returned error");
840
5
  return SC_SUCCESS;
841
19
}
842
843
static int flex_set_security_env(sc_card_t *card,
844
         const sc_security_env_t *env,
845
         int se_num)
846
0
{
847
0
  struct flex_private_data *prv = (struct flex_private_data *) card->drv_data;
848
849
0
  if (env->operation != SC_SEC_OPERATION_SIGN &&
850
0
      env->operation != SC_SEC_OPERATION_DECIPHER) {
851
0
    sc_log(card->ctx,  "Invalid crypto operation supplied.\n");
852
0
    return SC_ERROR_NOT_SUPPORTED;
853
0
  }
854
0
  if (env->algorithm != SC_ALGORITHM_RSA) {
855
0
    sc_log(card->ctx,  "Invalid crypto algorithm supplied.\n");
856
0
    return SC_ERROR_NOT_SUPPORTED;
857
0
  }
858
0
  if ((env->algorithm_flags & SC_ALGORITHM_RSA_PADS) ||
859
0
      (env->algorithm_flags & SC_ALGORITHM_RSA_HASHES)) {
860
0
        sc_log(card->ctx,  "Card supports only raw RSA.\n");
861
0
    return SC_ERROR_NOT_SUPPORTED;
862
0
  }
863
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
864
0
    if (env->key_ref_len != 1 ||
865
0
        (env->key_ref[0] != 0 && env->key_ref[0] != 1)) {
866
0
      sc_log(card->ctx,  "Invalid key reference supplied.\n");
867
0
      return SC_ERROR_NOT_SUPPORTED;
868
0
    }
869
0
    prv->rsa_key_ref = env->key_ref[0];
870
0
  }
871
0
  if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
872
0
    sc_log(card->ctx,  "Algorithm reference not supported.\n");
873
0
    return SC_ERROR_NOT_SUPPORTED;
874
0
  }
875
0
  if (env->flags & SC_SEC_ENV_FILE_REF_PRESENT)
876
0
    if (memcmp(env->file_ref.value, "\x00\x12", 2) != 0) {
877
0
      sc_log(card->ctx,  "File reference is not 0012.\n");
878
0
      return SC_ERROR_NOT_SUPPORTED;
879
0
    }
880
0
  return 0;
881
0
}
882
883
static int flex_restore_security_env(sc_card_t *card, int se_num)
884
0
{
885
0
  return 0;
886
0
}
887
888
static int
889
cryptoflex_compute_signature(sc_card_t *card, const u8 *data,
890
        size_t data_len, u8 * out, size_t outlen)
891
0
{
892
0
  struct flex_private_data *prv = (struct flex_private_data *) card->drv_data;
893
0
  sc_apdu_t apdu;
894
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
895
0
  int r;
896
0
  size_t i, i2;
897
898
0
  if (data_len != 64 && data_len != 96 && data_len != 128  && data_len != 256) {
899
0
    sc_log(card->ctx,
900
0
       "Illegal input length: %"SC_FORMAT_LEN_SIZE_T"u\n",
901
0
       data_len);
902
0
    return SC_ERROR_INVALID_ARGUMENTS;
903
0
  }
904
0
  if (outlen < data_len) {
905
0
    sc_log(card->ctx,  "Output buffer too small.\n");
906
0
    return SC_ERROR_BUFFER_TOO_SMALL;
907
0
  }
908
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x00, prv->rsa_key_ref);
909
910
  /* This works around a problem with some PC/SC IFD drivers that don't grok
911
   * lc=00 (Chaskiel M Grundman <cg2v@andrew.cmu.edu>) */
912
0
  if (data_len == 256) {
913
0
    apdu.cla=0x10;
914
0
    apdu.cse= SC_APDU_CASE_3_SHORT;
915
0
    apdu.lc=10;
916
0
    apdu.datalen=10;
917
0
    apdu.data = sbuf;
918
0
    for (i2 = 0; i2 < 10; i2++)
919
0
      sbuf[i2]=data[data_len-1-i2];
920
0
    r = sc_transmit_apdu(card, &apdu);
921
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
922
0
    r = sc_check_sw(card, apdu.sw1, apdu.sw2);
923
0
    LOG_TEST_RET(card->ctx, r, "Card returned error");
924
0
    data_len -= 10;
925
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x00, prv->rsa_key_ref);
926
0
    apdu.cla=0x0;
927
0
  }
928
929
0
  apdu.lc = data_len;
930
0
  apdu.datalen = data_len;
931
0
  for (i = 0; i < data_len; i++)
932
0
    sbuf[i] = data[data_len-1-i];
933
0
  apdu.data = sbuf;
934
0
  apdu.resplen = outlen > sizeof(sbuf) ? sizeof(sbuf) : outlen;
935
0
  apdu.le      = apdu.resplen > 256 ? 256 : apdu.resplen;
936
0
  apdu.resp    = sbuf;
937
0
  r = sc_transmit_apdu(card, &apdu);
938
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
939
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
940
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
941
0
  for (i = 0; i < apdu.resplen; i++)
942
0
    out[i] = sbuf[apdu.resplen-1-i];
943
0
  return (int)apdu.resplen;
944
0
}
945
946
static int
947
cyberflex_compute_signature(sc_card_t *card, const u8 *data,
948
    size_t data_len, u8 * out, size_t outlen)
949
0
{
950
0
  struct flex_private_data *prv = DRV_DATA(card);
951
0
  sc_apdu_t apdu;
952
0
  u8 alg_id, key_id;
953
0
  int r;
954
955
0
  switch (data_len) {
956
0
  case 64:  alg_id = 0xC4; break;
957
0
  case 96:  alg_id = 0xC6; break;
958
0
  case 128: alg_id = 0xC8; break;
959
0
  default:
960
0
    sc_log(card->ctx,
961
0
       "Illegal input length: %"SC_FORMAT_LEN_SIZE_T"u\n",
962
0
       data_len);
963
0
    return SC_ERROR_INVALID_ARGUMENTS;
964
0
  }
965
0
  key_id = prv->rsa_key_ref + 1; /* Why? */
966
967
0
  if (outlen < data_len) {
968
0
    sc_log(card->ctx,  "Output buffer too small.\n");
969
0
    return SC_ERROR_BUFFER_TOO_SMALL;
970
0
  }
971
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x88, alg_id, key_id);
972
973
0
  apdu.lc = data_len;
974
0
  apdu.datalen = data_len;
975
0
  apdu.data = data;
976
0
  apdu.resplen = outlen;
977
0
  apdu.resp = out;
978
0
  r = sc_transmit_apdu(card, &apdu);
979
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
980
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
981
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
982
0
  return (int)apdu.resplen;
983
0
}
984
985
static int flex_decipher(sc_card_t *card,
986
          const u8 * crgram, size_t crgram_len,
987
          u8 * out, size_t outlen)
988
0
{
989
  /* There seems to be no Decipher command, but an RSA signature
990
   * is the same operation as an RSA decryption.
991
   * Of course, the (PKCS#1) padding is different, but at least
992
   * a Cryptoflex 32K e-gate doesn't seem to check this. */
993
0
  return card->ops->compute_signature(card, crgram, crgram_len, out, outlen);
994
0
}
995
996
/* Return the default AAK for this type of card */
997
static int flex_get_default_key(sc_card_t *card,
998
        struct sc_cardctl_default_key *data)
999
14
{
1000
14
  struct flex_private_data *prv = DRV_DATA(card);
1001
14
  const char *key;
1002
1003
14
  if (data->method != SC_AC_AUT || data->key_ref != prv->aak_key_ref)
1004
0
    return SC_ERROR_NO_DEFAULT_KEY;
1005
1006
  /* These seem to be the default AAKs used by Schlumberger */
1007
14
  switch (card->type) {
1008
7
  case SC_CARD_TYPE_FLEX_CRYPTO:
1009
7
    key = "2c:15:e5:26:e9:3e:8a:19";
1010
7
    break;
1011
7
  case SC_CARD_TYPE_FLEX_CYBER:
1012
7
    key = "ad:9f:61:fe:fa:20:ce:63";
1013
7
    break;
1014
0
  default:
1015
0
    return SC_ERROR_NO_DEFAULT_KEY;
1016
14
  }
1017
1018
14
  return sc_hex_to_bin(key, data->key_data, &data->len);
1019
14
}
1020
1021
/* Generate key on-card */
1022
static int flex_generate_key(sc_card_t *card, struct sc_cardctl_cryptoflex_genkey_info *data)
1023
0
{
1024
0
  sc_apdu_t apdu;
1025
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1026
0
  int r, p1, p2;
1027
1028
0
  switch (data->key_bits) {
1029
0
  case  512:  p2 = 0x40; break;
1030
0
  case  768:  p2 = 0x60; break;
1031
0
  case 1024:  p2 = 0x80; break;
1032
0
  case 2048:  p2 = 0x00; break;
1033
0
  default:
1034
0
    sc_log(card->ctx,  "Illegal key length: %zu\n", data->key_bits);
1035
0
    return SC_ERROR_INVALID_ARGUMENTS;
1036
0
  }
1037
1038
0
  p1 = data->key_num;
1039
1040
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x46, p1, p2);
1041
0
  if (!IS_CYBERFLEX(card))
1042
0
    apdu.cla = 0xF0;
1043
0
  apdu.data = sbuf;
1044
0
  apdu.datalen = 4;
1045
0
  apdu.lc = 4;
1046
1047
  /* Little endian representation of exponent */
1048
0
  sbuf[0] = data->exponent & 0xFF;
1049
0
  sbuf[1] = (data->exponent >> 8) & 0xFF;
1050
0
  sbuf[2] = (data->exponent >> 16) & 0xFF;
1051
0
  sbuf[3] = (data->exponent >> 24) & 0xFF;
1052
1053
0
  r = sc_transmit_apdu(card, &apdu);
1054
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1055
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1056
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1057
1058
0
  data->pubkey_len = (unsigned)apdu.resplen;
1059
0
  return 0;
1060
0
}
1061
1062
/* read the card serial number from the EF_gdo system file */
1063
static int flex_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
1064
173
{
1065
173
  int       r;
1066
173
  u8        buf[16];
1067
173
  size_t    len;
1068
173
  sc_path_t tpath;
1069
173
  sc_file_t *tfile = NULL;
1070
1071
173
  if (!serial)
1072
0
    return SC_ERROR_INVALID_ARGUMENTS;
1073
  /* see if we have cached serial number */
1074
173
  if (card->serialnr.len) {
1075
0
    memcpy(serial, &card->serialnr, sizeof(*serial));
1076
0
    return SC_SUCCESS;
1077
0
  }
1078
  /* read EF_ICCSN */
1079
173
  sc_format_path("3F000002", &tpath);
1080
173
  r = sc_select_file(card, &tpath, &tfile);
1081
173
  if (r < 0)
1082
93
    return r;
1083
80
  len = tfile->size;
1084
80
  sc_file_free(tfile);
1085
80
  if (len != 8) {
1086
65
    sc_log(card->ctx,  "unexpected file length of EF_ICCSN (%lu)\n",
1087
65
      (unsigned long) len);
1088
65
    return SC_ERROR_INTERNAL;
1089
65
  }
1090
15
  r = sc_read_binary(card, 0, buf, len, 0);
1091
15
  if (r < 0)
1092
9
    return r;
1093
6
  card->serialnr.len = len;
1094
6
  memcpy(card->serialnr.value, buf, len);
1095
1096
6
  memcpy(serial, &card->serialnr, sizeof(*serial));
1097
1098
6
  return SC_SUCCESS;
1099
15
}
1100
1101
static int flex_card_ctl(sc_card_t *card, unsigned long cmd, void *ptr)
1102
620
{
1103
620
  switch (cmd) {
1104
14
  case SC_CARDCTL_GET_DEFAULT_KEY:
1105
14
    return flex_get_default_key(card,
1106
14
        (struct sc_cardctl_default_key *) ptr);
1107
0
  case SC_CARDCTL_CRYPTOFLEX_GENERATE_KEY:
1108
0
    return flex_generate_key(card,
1109
0
        (struct sc_cardctl_cryptoflex_genkey_info *) ptr);
1110
173
  case SC_CARDCTL_GET_SERIALNR:
1111
173
    return flex_get_serialnr(card, (sc_serial_number_t *) ptr);
1112
620
  }
1113
1114
433
  return SC_ERROR_NOT_SUPPORTED;
1115
620
}
1116
1117
static int flex_build_verify_apdu(sc_card_t *card, sc_apdu_t *apdu,
1118
          struct sc_pin_cmd_data *data)
1119
26
{
1120
26
  static u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
1121
26
  int r, len;
1122
26
  int cla = card->cla, ins;
1123
1124
26
  switch (data->pin_type) {
1125
19
  case SC_AC_CHV:
1126
19
    ins = 0x20;
1127
19
    break;
1128
7
  case SC_AC_AUT:
1129
    /* AUT keys cannot be entered through terminal */
1130
7
    if (data->flags & SC_PIN_CMD_USE_PINPAD)
1131
0
      return SC_ERROR_INVALID_ARGUMENTS;
1132
    /* Override CLA byte */
1133
7
    if (!IS_CYBERFLEX(card))
1134
4
      cla = 0xF0;
1135
7
    ins = 0x2A;
1136
7
    break;
1137
0
  default:
1138
0
    return SC_ERROR_INVALID_ARGUMENTS;
1139
26
  }
1140
  /* Copy the PIN, with padding */
1141
26
  if ((r = sc_build_pin(sbuf, sizeof(sbuf), &data->pin1, 1)) < 0)
1142
0
    return r;
1143
26
  len = r;
1144
1145
26
  sc_format_apdu(card, apdu, SC_APDU_CASE_3_SHORT, ins, 0, data->pin_reference);
1146
26
  apdu->cla = cla;
1147
26
  apdu->data = sbuf;
1148
26
  apdu->datalen = len;
1149
26
  apdu->lc = len;
1150
1151
26
  return 0;
1152
26
}
1153
1154
static void flex_init_pin_info(struct sc_pin_cmd_pin *pin, unsigned int num)
1155
398
{
1156
398
  pin->encoding   = SC_PIN_ENCODING_ASCII;
1157
398
  pin->min_length = 4;
1158
398
  pin->max_length = 8;
1159
398
  pin->pad_length = 8;
1160
398
  pin->offset     = 5 + num * 8;
1161
398
}
1162
1163
static int flex_pin_cmd(sc_card_t *card, struct sc_pin_cmd_data *data,
1164
      int *tries_left)
1165
199
{
1166
199
  sc_apdu_t apdu;
1167
199
  int r;
1168
199
  int old_cla = -1;
1169
1170
  /* Fix pin data */
1171
199
  data->flags |= SC_PIN_CMD_NEED_PADDING;
1172
199
  flex_init_pin_info(&data->pin1, 0);
1173
199
  flex_init_pin_info(&data->pin2, 1);
1174
1175
199
  if (data->cmd == SC_PIN_CMD_VERIFY) {
1176
26
    r = flex_build_verify_apdu(card, &apdu, data);
1177
26
    if (r < 0)
1178
0
      return r;
1179
26
    data->apdu = &apdu;
1180
173
  } else if (data->cmd == SC_PIN_CMD_CHANGE || data->cmd == SC_PIN_CMD_UNBLOCK) {
1181
0
    if (data->pin_type != SC_AC_CHV)
1182
0
      return SC_ERROR_INVALID_ARGUMENTS;
1183
0
    old_cla = card->cla;
1184
0
    if (!IS_CYBERFLEX(card))
1185
0
      card->cla = 0xF0;
1186
0
  }
1187
1188
  /* According to the Cryptoflex documentation, the card
1189
   * does not return the number of attempts left using
1190
   * the 63C0xx convention, hence we don't pass the
1191
   * tries_left pointer. */
1192
199
  r = iso_ops->pin_cmd(card, data, NULL);
1193
199
  if (old_cla != -1)
1194
0
    card->cla = old_cla;
1195
199
  data->apdu = NULL;
1196
199
  return r;
1197
199
}
1198
1199
static int flex_logout(sc_card_t *card)
1200
0
{
1201
0
  sc_apdu_t apdu;
1202
0
  int r;
1203
1204
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_1, 0x22, 0x07, 0x00);
1205
0
  apdu.cla = 0xF0;
1206
1207
0
  r = sc_transmit_apdu(card, &apdu);
1208
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
1209
1210
0
  r = sc_check_sw(card, apdu.sw1, apdu.sw2);
1211
0
  LOG_TEST_RET(card->ctx, r, "Card returned error");
1212
1213
0
  LOG_FUNC_RETURN(card->ctx, r);
1214
0
}
1215
1216
1217
struct sc_card_driver * sc_get_cryptoflex_driver(void)
1218
110k
{
1219
110k
  if (iso_ops == NULL)
1220
0
    iso_ops = sc_get_iso7816_driver()->ops;
1221
1222
110k
  cryptoflex_ops = *iso_ops;
1223
110k
  cryptoflex_ops.match_card = cryptoflex_match_card;
1224
110k
  cryptoflex_ops.init = flex_init;
1225
110k
  cryptoflex_ops.finish = flex_finish;
1226
110k
  cryptoflex_ops.process_fci = cryptoflex_process_file_attrs;
1227
110k
  cryptoflex_ops.construct_fci = cryptoflex_construct_file_attrs;
1228
110k
  cryptoflex_ops.select_file = flex_select_file;
1229
110k
  cryptoflex_ops.list_files = cryptoflex_list_files;
1230
110k
  cryptoflex_ops.delete_file = flex_delete_file;
1231
110k
  cryptoflex_ops.create_file = flex_create_file;
1232
110k
  cryptoflex_ops.card_ctl = flex_card_ctl;
1233
110k
  cryptoflex_ops.set_security_env = flex_set_security_env;
1234
110k
  cryptoflex_ops.restore_security_env = flex_restore_security_env;
1235
110k
  cryptoflex_ops.compute_signature = cryptoflex_compute_signature;
1236
110k
  cryptoflex_ops.decipher = flex_decipher;
1237
110k
  cryptoflex_ops.pin_cmd = flex_pin_cmd;
1238
110k
  cryptoflex_ops.logout = flex_logout;
1239
110k
  return &cryptoflex_drv;
1240
110k
}
1241
1242
struct sc_card_driver * sc_get_cyberflex_driver(void)
1243
110k
{
1244
110k
  if (iso_ops == NULL)
1245
10
    iso_ops = sc_get_iso7816_driver()->ops;
1246
1247
110k
  cyberflex_ops = *iso_ops;
1248
110k
  cyberflex_ops.match_card = cyberflex_match_card;
1249
110k
  cyberflex_ops.init = flex_init;
1250
110k
  cyberflex_ops.finish = flex_finish;
1251
110k
  cyberflex_ops.process_fci = cyberflex_process_file_attrs;
1252
110k
  cyberflex_ops.construct_fci = cyberflex_construct_file_attrs;
1253
110k
  cyberflex_ops.select_file = flex_select_file;
1254
110k
  cyberflex_ops.list_files = cyberflex_list_files;
1255
110k
  cyberflex_ops.delete_file = flex_delete_file;
1256
110k
  cyberflex_ops.create_file = flex_create_file;
1257
110k
  cyberflex_ops.card_ctl = flex_card_ctl;
1258
110k
  cyberflex_ops.set_security_env = flex_set_security_env;
1259
110k
  cyberflex_ops.restore_security_env = flex_restore_security_env;
1260
110k
  cyberflex_ops.compute_signature = cyberflex_compute_signature;
1261
110k
  cyberflex_ops.decipher = flex_decipher;
1262
110k
  cyberflex_ops.pin_cmd = flex_pin_cmd;
1263
110k
  cyberflex_ops.logout = flex_logout;
1264
110k
  return &cyberflex_drv;
1265
110k
}