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-atrust-acos.c
Line
Count
Source
1
/*
2
 * atrust-acos.c: Support for A-Trust ACOS based cards
3
 *
4
 * Copyright (C) 2005  Franz Brandl <brandl@a-trust.at> based on work from
5
 *                     Jörn Zukowski <zukowski@trustcenter.de> and
6
 *                     Nils Larsch   <larsch@trustcenter.de>, TrustCenter AG
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
/*****************************************************************************/
35
36
#define ACOS_EMV_A03    "A-TRUST ACOS"
37
221
#define ACOS_EMV_A05    "A-TRUST ACOS A05"
38
39
static const char *atrust_acos_atrs[] = {
40
  "3B:BF:11:00:81:31:fe:45:45:50:41",
41
  "3B:BF:11:00:81:31:fe:45:4d:43:41",
42
  "3B:BF:13:00:81:31:fe:45:45:50:41",
43
  "3B:BF:13:00:81:31:fe:45:4d:43:41",
44
  NULL
45
};
46
47
/* sequence and number has to match atr table ! */
48
static const char *atrust_acos_names[] = {
49
  ACOS_EMV_A03,
50
  ACOS_EMV_A03,
51
  ACOS_EMV_A05,
52
  ACOS_EMV_A05,
53
  NULL
54
};
55
56
static struct sc_card_operations atrust_acos_ops;
57
static struct sc_card_operations *iso_ops = NULL;
58
59
static struct sc_card_driver atrust_acos_drv = {
60
  "A-Trust ACOS cards",
61
  "atrust-acos",
62
  &atrust_acos_ops,
63
  NULL, 0, NULL
64
};
65
66
/* internal structure to save the current security environment */
67
typedef struct atrust_acos_ex_data_st {
68
  int    sec_ops; /* the currently selected security operation,
69
       * i.e. SC_SEC_OPERATION_AUTHENTICATE etc. */
70
  unsigned long    fix_digestInfo;
71
} atrust_acos_ex_data;
72
73
/*****************************************************************************/
74
75
static int atrust_acos_match_card(struct sc_card *card)
76
12.7k
{
77
12.7k
  int   i, match = 0;
78
79
80
63.2k
  for (i = 0; atrust_acos_atrs[i] != NULL; i++)
81
50.7k
  {
82
50.7k
    u8 defatr[SC_MAX_ATR_SIZE];
83
50.7k
    size_t len = sizeof(defatr);
84
50.7k
    const char *atrp = atrust_acos_atrs[i];
85
86
50.7k
    if (sc_hex_to_bin(atrp, defatr, &len))
87
0
      continue;
88
    /* we may only verify part of ATR since */
89
    /* part of the hist chars is variable */
90
50.7k
    if (len > card->atr.len)
91
18.7k
      continue;
92
31.9k
    if (memcmp(card->atr.value, defatr, len) != 0)
93
31.7k
      continue;
94
95
221
    match = 1;
96
221
    card->name = atrust_acos_names[i];
97
98
221
    break;
99
31.9k
    }
100
12.7k
  return match;
101
12.7k
}
102
103
/*****************************************************************************/
104
105
static int atrust_acos_init(struct sc_card *card)
106
221
{
107
221
  unsigned int flags;
108
221
  atrust_acos_ex_data *ex_data;
109
110
221
  ex_data = calloc(1, sizeof(atrust_acos_ex_data));
111
221
  if (ex_data == NULL)
112
0
    return SC_ERROR_OUT_OF_MEMORY;
113
114
221
  card->cla  = 0x00;
115
221
  card->drv_data = (void *)ex_data;
116
117
  /* set the supported algorithm */
118
119
221
  flags = SC_ALGORITHM_RSA_PAD_PKCS1
120
221
    | SC_ALGORITHM_RSA_HASH_NONE
121
221
    | SC_ALGORITHM_RSA_HASH_SHA1
122
221
    | SC_ALGORITHM_RSA_HASH_MD5
123
221
    | SC_ALGORITHM_RSA_HASH_RIPEMD160
124
221
    | SC_ALGORITHM_RSA_HASH_MD5_SHA1;
125
126
221
  if (card->name != NULL && !strcmp(card->name, ACOS_EMV_A05))
127
144
    flags |= SC_ALGORITHM_RSA_HASH_SHA256;
128
129
221
  _sc_card_add_rsa_alg(card, 1536, flags, 0x10001);
130
131
  /* we need read_binary&friends with max 128 bytes per read */
132
221
  card->max_send_size = 128;
133
221
  card->max_recv_size = 128;
134
135
221
  return 0;
136
221
}
137
138
/*****************************************************************************/
139
140
static int atrust_acos_finish(struct sc_card *card)
141
221
{
142
221
  if (card->drv_data)
143
221
    free((atrust_acos_ex_data *)card->drv_data);
144
221
  return 0;
145
221
}
146
147
/*****************************************************************************/
148
149
static int process_fci(struct sc_context *ctx, struct sc_file *file,
150
           const u8 *buf, size_t buflen)
151
98
{
152
153
98
  size_t taglen, len = buflen;
154
98
  const u8 *tag = NULL, *p;
155
156
98
  sc_log(ctx,  "processing FCI bytes\n");
157
158
98
  if (buflen < 2)
159
16
    return SC_ERROR_INTERNAL;
160
82
  if (buf[0] != 0x6f)          /* FCI template */
161
12
    return SC_ERROR_INVALID_DATA;
162
70
  len = (size_t)buf[1];
163
70
  if (buflen - 2 < len)
164
3
    return SC_ERROR_INVALID_DATA;
165
67
  p = buf + 2;
166
167
  /* defaults */
168
67
  file->type = SC_FILE_TYPE_WORKING_EF;
169
67
  file->ef_structure = SC_FILE_EF_UNKNOWN;
170
67
  file->shareable = 0;
171
67
  file->record_length = 0;
172
67
  file->size = 0;
173
174
  /* get file size */
175
67
  tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
176
67
  if (tag != NULL && taglen >= 2) {
177
13
    int bytes = (tag[0] << 8) + tag[1];
178
13
    sc_log(ctx,  "  bytes in file: %d\n", bytes);
179
13
    file->size = bytes;
180
13
  }
181
182
  /* get file type */
183
67
    tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
184
67
  if (tag != NULL) {
185
28
    const char *type = "unknown";
186
28
    const char *structure = "unknown";
187
188
28
    if (taglen == 1 && tag[0] == 0x01) {
189
      /* transparent EF */
190
3
      type = "working EF";
191
3
      structure = "transparent";
192
3
      file->type = SC_FILE_TYPE_WORKING_EF;
193
3
      file->ef_structure = SC_FILE_EF_TRANSPARENT;
194
25
    } else if (taglen == 1 && tag[0] == 0x11) {
195
      /* object EF */
196
3
      type = "working EF";
197
3
      structure = "object";
198
3
      file->type = SC_FILE_TYPE_WORKING_EF;
199
3
      file->ef_structure = SC_FILE_EF_TRANSPARENT; /* TODO */
200
22
    } else if (taglen == 3 && tag[1] == 0x21) {
201
6
      type = "working EF";
202
6
      file->record_length = tag[2];
203
6
      file->type = SC_FILE_TYPE_WORKING_EF;
204
      /* linear fixed, cyclic or compute */
205
6
      switch ( tag[0] )
206
6
      {
207
1
        case 0x02:
208
1
          structure = "linear fixed";
209
1
          file->ef_structure = SC_FILE_EF_LINEAR_FIXED;
210
1
          break;
211
1
        case 0x07:
212
1
          structure = "cyclic";
213
1
          file->ef_structure = SC_FILE_EF_CYCLIC;
214
1
          break;
215
1
        case 0x17:
216
1
          structure = "compute";
217
1
          file->ef_structure = SC_FILE_EF_UNKNOWN;
218
1
          break;
219
3
        default:
220
3
          structure = "unknown";
221
3
          file->ef_structure = SC_FILE_EF_UNKNOWN;
222
3
          file->record_length = 0;
223
3
          break;
224
6
      }
225
6
    }
226
227
28
    sc_log(ctx,  "  type: %s\n", type);
228
28
    sc_log(ctx,  "  EF structure: %s\n", structure);
229
28
  }
230
67
  file->magic = SC_FILE_MAGIC;
231
232
67
  return SC_SUCCESS;
233
67
}
234
235
/*****************************************************************************/
236
237
static int atrust_acos_select_aid(struct sc_card *card,
238
            u8 aid[16], size_t len,
239
            struct sc_file **file_out)
240
412
{
241
412
  sc_apdu_t apdu;
242
412
  int r;
243
412
  size_t i = 0;
244
245
412
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C);
246
412
  apdu.lc = len;
247
412
  apdu.data = (u8*)aid;
248
412
  apdu.datalen = len;
249
412
  apdu.resplen = 0;
250
412
  apdu.le = 0;
251
412
  r = sc_transmit_apdu(card, &apdu);
252
412
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
253
254
  /* check return value */
255
409
  if (!(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) && apdu.sw1 != 0x61)
256
355
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
257
258
54
  if (file_out) {
259
0
    sc_file_t *file = sc_file_new();
260
0
    if (!file)
261
0
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
262
0
    file->type = SC_FILE_TYPE_DF;
263
0
    file->ef_structure = SC_FILE_EF_UNKNOWN;
264
0
    file->path.len = 0;
265
0
    file->size = 0;
266
    /* AID */
267
0
    for (i = 0; i < len; i++)
268
0
      file->name[i] = aid[i];
269
0
    file->namelen = len;
270
0
    file->id = 0x0000;
271
0
    file->magic = SC_FILE_MAGIC;
272
0
    *file_out = file;
273
0
  }
274
54
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
275
54
}
276
277
/*****************************************************************************/
278
279
static int atrust_acos_select_fid(struct sc_card *card,
280
            unsigned int id_hi, unsigned int id_lo,
281
            struct sc_file **file_out)
282
784
{
283
784
  sc_apdu_t apdu;
284
784
  u8 data[] = {id_hi & 0xff, id_lo & 0xff};
285
784
  u8 resp[SC_MAX_APDU_BUFFER_SIZE];
286
784
  int bIsDF = 0, r;
287
288
  /* request FCI to distinguish between EFs and DFs */
289
784
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00);
290
784
  apdu.resp = (u8*)resp;
291
784
  apdu.resplen = SC_MAX_APDU_BUFFER_SIZE;
292
784
  apdu.le = 256;
293
784
  apdu.lc = 2;
294
784
  apdu.data = (u8*)data;
295
784
  apdu.datalen = 2;
296
297
784
  r = sc_transmit_apdu(card, &apdu);
298
784
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
299
300
760
  if (apdu.p2 == 0x00 && apdu.sw1 == 0x62 && apdu.sw2 == 0x84 ) {
301
    /* no FCI => we have a DF (see comment in process_fci()) */
302
9
    bIsDF = 1;
303
9
    apdu.p2 = 0x0C;
304
9
    apdu.cse = SC_APDU_CASE_3_SHORT;
305
9
    apdu.resplen = 0;
306
9
    apdu.le = 0;
307
9
    r = sc_transmit_apdu(card, &apdu);
308
9
    LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
309
751
      } else if (apdu.sw1 == 0x61 || (apdu.sw1 == 0x90 && apdu.sw2 == 0x00)) {
310
    /* SELECT returned some data (possible FCI) =>
311
     * try a READ BINARY to see if a EF is selected */
312
281
    sc_apdu_t apdu2;
313
281
    u8 resp2[2];
314
281
    sc_format_apdu(card, &apdu2, SC_APDU_CASE_2_SHORT, 0xB0, 0, 0);
315
281
    apdu2.resp = (u8*)resp2;
316
281
    apdu2.resplen = 2;
317
281
    apdu2.le = 1;
318
281
    apdu2.lc = 0;
319
281
    r = sc_transmit_apdu(card, &apdu2);
320
281
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
321
271
    if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86)
322
      /* no current EF is selected => we have a DF */
323
17
      bIsDF = 1;
324
271
  }
325
326
744
  if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00))
327
473
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
328
329
271
  if (file_out) {
330
104
    sc_file_t *file = sc_file_new();
331
104
    if (!file)
332
104
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
333
104
    file->id = (id_hi << 8) + id_lo;
334
335
104
    if (bIsDF) {
336
      /* we have a DF */
337
6
      file->type = SC_FILE_TYPE_DF;
338
6
      file->ef_structure = SC_FILE_EF_UNKNOWN;
339
6
      file->size = 0;
340
6
      file->namelen = 0;
341
6
      file->magic = SC_FILE_MAGIC;
342
6
      *file_out = file;
343
98
    } else {
344
      /* ok, assume we have a EF */
345
98
      r = process_fci(card->ctx, file, apdu.resp,
346
98
          apdu.resplen);
347
98
      if (r != SC_SUCCESS) {
348
31
        sc_file_free(file);
349
31
        return r;
350
31
      }
351
352
67
      *file_out = file;
353
67
    }
354
104
  }
355
356
240
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
357
240
}
358
359
/*****************************************************************************/
360
361
static int atrust_acos_select_file(struct sc_card *card,
362
             const struct sc_path *in_path,
363
             struct sc_file **file_out)
364
1.04k
{
365
1.04k
  u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
366
1.04k
  int    r;
367
1.04k
  size_t i, pathlen;
368
369
1.04k
  memcpy(path, in_path->value, in_path->len);
370
1.04k
  pathlen = in_path->len;
371
372
1.04k
  if (in_path->type == SC_PATH_TYPE_FILE_ID) {
373
    /* SELECT EF/DF with ID */
374
    /* Select with 2byte File-ID */
375
0
    if (pathlen != 2)
376
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,SC_ERROR_INVALID_ARGUMENTS);
377
0
    return atrust_acos_select_fid(card, path[0], path[1], file_out);
378
1.04k
  } else if (in_path->type == SC_PATH_TYPE_DF_NAME) {
379
    /* SELECT DF with AID */
380
    /* Select with 1-16byte Application-ID */
381
412
    return atrust_acos_select_aid(card, pathbuf, pathlen, file_out);
382
635
  } else if (in_path->type == SC_PATH_TYPE_PATH) {
383
635
    u8 n_pathbuf[SC_MAX_PATH_SIZE];
384
385
    /* Select with path (sequence of File-IDs) */
386
    /* ACOS only supports one
387
     * level of subdirectories, therefore a path is
388
     * at most 3 FID long (the last one being the FID
389
     * of a EF) => pathlen must be even and less than 6
390
     */
391
635
    if (pathlen%2 != 0 || pathlen > 6 || pathlen <= 0)
392
1
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
393
    /* if pathlen == 6 then the first FID must be MF (== 3F00) */
394
634
    if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
395
6
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
396
397
    /* unify path (the first FID should be MF) */
398
628
    if (path[0] != 0x3f || path[1] != 0x00)
399
21
    {
400
21
      n_pathbuf[0] = 0x3f;
401
21
      n_pathbuf[1] = 0x00;
402
21
      memcpy(n_pathbuf+2, path, pathlen);
403
21
      path = n_pathbuf;
404
21
      pathlen += 2;
405
21
    }
406
407
784
    for (i = 0; i < pathlen - 2; i += 2) {
408
633
      r = atrust_acos_select_fid(card, path[i], path[i + 1], NULL);
409
633
      LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
410
633
    }
411
151
    return atrust_acos_select_fid(card, path[pathlen - 2], path[pathlen - 1], file_out);
412
628
  } else
413
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
414
1.04k
}
415
416
/** atrust_acos_set_security_env
417
 * sets the security environment
418
 * \param card pointer to the sc_card object
419
 * \param env pointer to a sc_security_env object
420
 * \param se_num not used here
421
 * \return SC_SUCCESS on success or an error code
422
 *
423
 * This function sets the security environment (using the
424
 * command MANAGE SECURITY ENVIRONMENT). In case a COMPUTE SIGNATURE
425
 * operation is requested , this function tries to detect whether
426
 * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE must be used for signature
427
 * calculation.
428
 */
429
static int atrust_acos_set_security_env(struct sc_card *card,
430
            const struct sc_security_env *env,
431
            int se_num)
432
0
{
433
0
  u8              *p, *pp;
434
0
  int              r, operation = env->operation;
435
0
  struct sc_apdu   apdu;
436
0
  u8               sbuf[SC_MAX_APDU_BUFFER_SIZE];
437
0
  atrust_acos_ex_data *ex_data = (atrust_acos_ex_data *)card->drv_data;
438
439
0
  p     = sbuf;
440
441
  /* copy key reference, if present */
442
0
  if (env->flags & SC_SEC_ENV_KEY_REF_PRESENT) {
443
0
    if (env->flags & SC_SEC_ENV_KEY_REF_SYMMETRIC)
444
0
      *p++ = 0x83;
445
0
    else
446
0
      *p++ = 0x84;
447
0
    *p++ = env->key_ref_len;
448
0
    memcpy(p, env->key_ref, env->key_ref_len);
449
0
    p += env->key_ref_len;
450
0
  }
451
0
  pp = p;
452
0
  if (operation == SC_SEC_OPERATION_DECIPHER){
453
0
    if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_02) {
454
0
      *p++ = 0x80;
455
0
      *p++ = 0x01;
456
0
      *p++ = 0x02;
457
0
    } else
458
0
      return SC_ERROR_INVALID_ARGUMENTS;
459
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x81,
460
0
                   0xb8);
461
0
    apdu.data    = sbuf;
462
0
    apdu.datalen = p - sbuf;
463
0
    apdu.lc      = p - sbuf;
464
0
    apdu.le      = 0;
465
0
    r = sc_transmit_apdu(card, &apdu);
466
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
467
0
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
468
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
469
0
    return SC_SUCCESS;
470
0
  }
471
  /* try COMPUTE SIGNATURE */
472
0
  if (operation == SC_SEC_OPERATION_SIGN && (
473
0
      env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01 ||
474
0
      env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796)) {
475
0
    if (env->flags & SC_SEC_ENV_ALG_REF_PRESENT) {
476
0
      *p++ = 0x80;
477
0
      *p++ = 0x01;
478
0
      *p++ = env->algorithm_ref & 0xFF;
479
0
    } else if (env->flags & SC_SEC_ENV_ALG_PRESENT &&
480
0
                env->algorithm == SC_ALGORITHM_RSA) {
481
      /* set the method to use based on the algorithm_flags */
482
0
      *p++ = 0x80;
483
0
      *p++ = 0x01;
484
0
      if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1_TYPE_01) {
485
0
        if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
486
0
          *p++ = 0x12;
487
0
        else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
488
0
          *p++ = 0x22;
489
0
        else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_MD5)
490
0
          *p++ = 0x32;
491
0
        else {
492
          /* can't use COMPUTE SIGNATURE =>
493
           * try INTERNAL AUTHENTICATE */
494
0
          p = pp;
495
0
          operation = SC_SEC_OPERATION_AUTHENTICATE;
496
0
          goto try_authenticate;
497
0
        }
498
0
      } else if (env->algorithm_flags & SC_ALGORITHM_RSA_PAD_ISO9796) {
499
0
        if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_SHA1)
500
0
          *p++ = 0x11;
501
0
        else if (env->algorithm_flags & SC_ALGORITHM_RSA_HASH_RIPEMD160)
502
0
          *p++ = 0x21;
503
0
        else
504
0
          return SC_ERROR_INVALID_ARGUMENTS;
505
0
      } else
506
0
        return SC_ERROR_INVALID_ARGUMENTS;
507
0
    }
508
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xb6);
509
0
    apdu.data    = sbuf;
510
0
    apdu.datalen = p - sbuf;
511
0
    apdu.lc      = p - sbuf;
512
0
    apdu.le      = 0;
513
    /* we don't know whether to use
514
     * COMPUTE SIGNATURE or INTERNAL AUTHENTICATE */
515
0
    r = sc_transmit_apdu(card, &apdu);
516
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
517
0
    if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
518
0
      ex_data->fix_digestInfo = 0;
519
0
      ex_data->sec_ops        = SC_SEC_OPERATION_SIGN;
520
0
      return SC_SUCCESS;
521
0
    }
522
    /* reset pointer */
523
0
    p = pp;
524
    /* doesn't work => try next op */
525
0
    operation = SC_SEC_OPERATION_AUTHENTICATE;
526
0
  }
527
0
try_authenticate:
528
  /* try INTERNAL AUTHENTICATE */
529
0
  if (operation == SC_SEC_OPERATION_AUTHENTICATE &&
530
0
      env->algorithm_flags & SC_ALGORITHM_RSA_PAD_PKCS1) {
531
0
    *p++ = 0x80;
532
0
    *p++ = 0x01;
533
0
    *p++ = 0x01;
534
535
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x22, 0x41, 0xa4);
536
0
    apdu.data    = sbuf;
537
0
    apdu.datalen = p - sbuf;
538
0
    apdu.lc      = p - sbuf;
539
0
    apdu.le      = 0;
540
0
    r = sc_transmit_apdu(card, &apdu);
541
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
542
0
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
543
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
544
0
    ex_data->fix_digestInfo = env->algorithm_flags;
545
0
    ex_data->sec_ops        = SC_SEC_OPERATION_AUTHENTICATE;
546
0
    return SC_SUCCESS;
547
0
  }
548
549
0
  return SC_ERROR_INVALID_ARGUMENTS;
550
0
}
551
552
/*****************************************************************************/
553
554
static int atrust_acos_compute_signature(struct sc_card *card,
555
             const u8 * data, size_t datalen,
556
             u8 * out, size_t outlen)
557
0
{
558
0
  int r;
559
0
  struct sc_apdu apdu;
560
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
561
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
562
0
  atrust_acos_ex_data *ex_data = (atrust_acos_ex_data *)card->drv_data;
563
564
0
  if (datalen > SC_MAX_APDU_BUFFER_SIZE)
565
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
566
567
0
  if (ex_data->sec_ops == SC_SEC_OPERATION_SIGN) {
568
    /* compute signature with the COMPUTE SIGNATURE command */
569
570
    /* set the hash value     */
571
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0x2A,
572
0
             0x90, 0x81);
573
0
    apdu.resp = rbuf;
574
0
    apdu.resplen = sizeof(rbuf);
575
0
    apdu.le = 0;
576
0
    memcpy(sbuf, data, datalen);
577
0
    apdu.data = sbuf;
578
0
    apdu.lc = datalen;
579
0
    apdu.datalen = datalen;
580
0
    r = sc_transmit_apdu(card, &apdu);
581
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
582
0
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
583
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE,
584
0
               sc_check_sw(card, apdu.sw1, apdu.sw2));
585
586
    /* call COMPUTE SIGNATURE */
587
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0x2A,
588
0
             0x9E, 0x9A);
589
0
    apdu.resp = rbuf;
590
0
    apdu.resplen = sizeof(rbuf);
591
0
    apdu.le = 256;
592
593
0
    apdu.lc = 0;
594
0
    apdu.datalen = 0;
595
0
    r = sc_transmit_apdu(card, &apdu);
596
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
597
0
    if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
598
0
      size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
599
0
      memcpy(out, apdu.resp, len);
600
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
601
0
    }
602
0
  } else if (ex_data->sec_ops == SC_SEC_OPERATION_AUTHENTICATE) {
603
0
    size_t tmp_len;
604
    /* call INTERNAL AUTHENTICATE */
605
0
    sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x88, 0x10, 0x00);
606
    /* fix/create DigestInfo structure (if necessary) */
607
0
    if (ex_data->fix_digestInfo) {
608
0
      unsigned int flags = ex_data->fix_digestInfo & SC_ALGORITHM_RSA_HASHES;
609
0
      if (flags == 0x0)
610
        /* XXX: assume no hash is wanted */
611
0
        flags = SC_ALGORITHM_RSA_HASH_NONE;
612
0
      tmp_len = sizeof(sbuf);
613
0
      r = sc_pkcs1_encode(card->ctx, flags, data, datalen,
614
0
          sbuf, &tmp_len, sizeof(sbuf)*8, NULL);
615
0
      if (r < 0)
616
0
        return r;
617
0
    } else {
618
0
      memcpy(sbuf, data, datalen);
619
0
      tmp_len = datalen;
620
0
    }
621
0
    apdu.lc = tmp_len;
622
0
    apdu.data = sbuf;
623
0
    apdu.datalen = tmp_len;
624
0
    apdu.resp = rbuf;
625
0
    apdu.resplen = sizeof(rbuf);
626
0
    apdu.le = 256;
627
0
    r = sc_transmit_apdu(card, &apdu);
628
0
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
629
0
    if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
630
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
631
0
    {
632
0
      size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
633
634
0
      memcpy(out, apdu.resp, len);
635
0
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
636
0
    }
637
0
  } else
638
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
639
640
  /* clear old state */
641
0
  ex_data->sec_ops = 0;
642
0
  ex_data->fix_digestInfo = 0;
643
644
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
645
0
}
646
647
/*****************************************************************************/
648
649
static int atrust_acos_decipher(struct sc_card *card,
650
          const u8 * crgram, size_t crgram_len,
651
          u8 * out, size_t outlen)
652
0
{
653
0
  int r;
654
0
  struct sc_apdu apdu;
655
0
  u8 rbuf[SC_MAX_APDU_BUFFER_SIZE];
656
0
  u8 sbuf[SC_MAX_APDU_BUFFER_SIZE];
657
658
0
  if (card == NULL || crgram == NULL || out == NULL)
659
0
    return SC_ERROR_INTERNAL;
660
0
  LOG_FUNC_CALLED(card->ctx);
661
0
  if (crgram_len > 255)
662
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
663
664
  /* INS: 0x2A  PERFORM SECURITY OPERATION
665
   * P1:  0x80  Resp: Plain value
666
   * P2:  0x86  Cmd: Padding indicator byte followed by cryptogram */
667
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0x2A, 0x80, 0x86);
668
0
  apdu.resp = rbuf;
669
0
  apdu.resplen = sizeof(rbuf);
670
671
0
  sbuf[0] = 0; /* padding indicator byte, 0x00 = No further indication */
672
0
  memcpy(sbuf + 1, crgram, crgram_len);
673
0
  apdu.data = sbuf;
674
0
  apdu.lc = crgram_len + 1;
675
0
  apdu.datalen = crgram_len + 1;
676
0
  apdu.le = 256;
677
0
  r = sc_transmit_apdu(card, &apdu);
678
0
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
679
0
  if (apdu.sw1 == 0x90 && apdu.sw2 == 0x00) {
680
0
    size_t len = apdu.resplen > outlen ? outlen : apdu.resplen;
681
682
0
    memcpy(out, apdu.resp, len);
683
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, (int)len);
684
0
  }
685
686
0
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
687
0
}
688
689
/*****************************************************************************/
690
691
static int atrust_acos_check_sw(struct sc_card *card, unsigned int sw1,
692
  unsigned int sw2)
693
1.39k
{
694
695
1.39k
  sc_log(card->ctx,  "sw1 = 0x%02x, sw2 = 0x%02x\n", sw1, sw2);
696
697
1.39k
  if (sw1 == 0x90 && sw2 == 0x00)
698
408
    return SC_SUCCESS;
699
985
  if (sw1 == 0x63 && (sw2 & ~0x0fU) == 0xc0 )
700
10
  {
701
10
    sc_log(card->ctx,  "Verification failed (remaining tries: %d)\n",
702
10
    (sw2 & 0x0f));
703
10
    return SC_ERROR_PIN_CODE_INCORRECT;
704
10
  }
705
706
  /* iso error */
707
975
  return iso_ops->check_sw(card, sw1, sw2);
708
985
}
709
710
/*****************************************************************************/
711
712
static int acos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
713
18
{
714
18
  int r;
715
18
  u8  rbuf[SC_MAX_APDU_BUFFER_SIZE];
716
18
  sc_apdu_t apdu;
717
718
18
  if (!serial)
719
0
    return SC_ERROR_INVALID_ARGUMENTS;
720
  /* see if we have cached serial number */
721
18
  if (card->serialnr.len) {
722
0
    memcpy(serial, &card->serialnr, sizeof(*serial));
723
0
    return SC_SUCCESS;
724
0
  }
725
  /* get serial number via GET CARD DATA */
726
18
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00);
727
18
  apdu.cla |= 0x80;
728
18
  apdu.resp = rbuf;
729
18
  apdu.resplen = sizeof(rbuf);
730
18
  apdu.le   = 256;
731
18
  apdu.lc   = 0;
732
18
  apdu.datalen = 0;
733
18
        r = sc_transmit_apdu(card, &apdu);
734
18
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
735
17
  if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
736
5
    return SC_ERROR_INTERNAL;
737
  /* cache serial number */
738
12
  memcpy(card->serialnr.value, apdu.resp, MIN(apdu.resplen, SC_MAX_SERIALNR));
739
12
  card->serialnr.len = MIN(apdu.resplen, SC_MAX_SERIALNR);
740
  /* copy and return serial number */
741
12
  memcpy(serial, &card->serialnr, sizeof(*serial));
742
12
  return SC_SUCCESS;
743
17
}
744
745
/*****************************************************************************/
746
747
static int atrust_acos_card_ctl(struct sc_card *card, unsigned long cmd, void *ptr)
748
18
{
749
750
18
  switch (cmd)
751
18
  {
752
18
  case SC_CARDCTL_GET_SERIALNR:
753
18
    return acos_get_serialnr(card, (sc_serial_number_t *)ptr);
754
0
  default:
755
0
    return SC_ERROR_NOT_SUPPORTED;
756
18
  }
757
18
}
758
759
/*****************************************************************************/
760
761
static int atrust_acos_logout(struct sc_card *card)
762
0
{
763
0
  int r;
764
0
  struct sc_apdu apdu;
765
0
  const u8 mf_buf[2] = {0x3f, 0x00};
766
767
0
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x00, 0x0C);
768
0
  apdu.le = 0;
769
0
  apdu.lc = 2;
770
0
  apdu.data    = mf_buf;
771
0
  apdu.datalen = 2;
772
0
  apdu.resplen = 0;
773
774
0
  r = sc_transmit_apdu(card, &apdu);
775
0
  LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
776
777
0
  if (apdu.sw1 == 0x69 && apdu.sw2 == 0x85)
778
    /* the only possible reason for this error here is, afaik,
779
     * that no MF exists, but then there's no need to logout
780
     * => return SC_SUCCESS
781
     */
782
0
    return SC_SUCCESS;
783
0
  return sc_check_sw(card, apdu.sw1, apdu.sw2);
784
0
}
785
786
/*****************************************************************************/
787
788
static struct sc_card_driver * sc_get_driver(void)
789
12.7k
{
790
12.7k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
791
12.7k
  if (iso_ops == NULL)
792
1
    iso_ops = iso_drv->ops;
793
794
12.7k
  atrust_acos_ops = *iso_drv->ops;
795
12.7k
  atrust_acos_ops.match_card = atrust_acos_match_card;
796
12.7k
  atrust_acos_ops.init   = atrust_acos_init;
797
12.7k
  atrust_acos_ops.finish = atrust_acos_finish;
798
12.7k
  atrust_acos_ops.select_file = atrust_acos_select_file;
799
12.7k
  atrust_acos_ops.check_sw    = atrust_acos_check_sw;
800
12.7k
  atrust_acos_ops.create_file = NULL;
801
12.7k
  atrust_acos_ops.delete_file = NULL;
802
12.7k
  atrust_acos_ops.set_security_env  = atrust_acos_set_security_env;
803
12.7k
  atrust_acos_ops.compute_signature = atrust_acos_compute_signature;
804
12.7k
  atrust_acos_ops.decipher    = atrust_acos_decipher;
805
12.7k
  atrust_acos_ops.card_ctl    = atrust_acos_card_ctl;
806
12.7k
  atrust_acos_ops.logout      = atrust_acos_logout;
807
808
12.7k
  return &atrust_acos_drv;
809
12.7k
}
810
811
/*****************************************************************************/
812
813
struct sc_card_driver * sc_get_atrust_acos_driver(void)
814
12.7k
{
815
12.7k
  return sc_get_driver();
816
12.7k
}