Coverage Report

Created: 2026-09-14 06:06

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
240
#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
15.2k
{
77
15.2k
  int   i, match = 0;
78
79
80
75.8k
  for (i = 0; atrust_acos_atrs[i] != NULL; i++)
81
60.8k
  {
82
60.8k
    u8 defatr[SC_MAX_ATR_SIZE];
83
60.8k
    size_t len = sizeof(defatr);
84
60.8k
    const char *atrp = atrust_acos_atrs[i];
85
86
60.8k
    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
60.8k
    if (len > card->atr.len)
91
16.8k
      continue;
92
43.9k
    if (memcmp(card->atr.value, defatr, len) != 0)
93
43.7k
      continue;
94
95
240
    match = 1;
96
240
    card->name = atrust_acos_names[i];
97
98
240
    break;
99
43.9k
    }
100
15.2k
  return match;
101
15.2k
}
102
103
/*****************************************************************************/
104
105
static int atrust_acos_init(struct sc_card *card)
106
240
{
107
240
  unsigned int flags;
108
240
  atrust_acos_ex_data *ex_data;
109
110
240
  ex_data = calloc(1, sizeof(atrust_acos_ex_data));
111
240
  if (ex_data == NULL)
112
0
    return SC_ERROR_OUT_OF_MEMORY;
113
114
240
  card->cla  = 0x00;
115
240
  card->drv_data = (void *)ex_data;
116
117
  /* set the supported algorithm */
118
119
240
  flags = SC_ALGORITHM_RSA_PAD_PKCS1
120
240
    | SC_ALGORITHM_RSA_HASH_NONE
121
240
    | SC_ALGORITHM_RSA_HASH_SHA1
122
240
    | SC_ALGORITHM_RSA_HASH_MD5
123
240
    | SC_ALGORITHM_RSA_HASH_RIPEMD160
124
240
    | SC_ALGORITHM_RSA_HASH_MD5_SHA1;
125
126
240
  if (card->name != NULL && !strcmp(card->name, ACOS_EMV_A05))
127
140
    flags |= SC_ALGORITHM_RSA_HASH_SHA256;
128
129
240
  _sc_card_add_rsa_alg(card, 1536, flags, 0x10001);
130
131
  /* we need read_binary&friends with max 128 bytes per read */
132
240
  card->max_send_size = 128;
133
240
  card->max_recv_size = 128;
134
135
240
  return 0;
136
240
}
137
138
/*****************************************************************************/
139
140
static int atrust_acos_finish(struct sc_card *card)
141
240
{
142
240
  if (card->drv_data)
143
240
    free((atrust_acos_ex_data *)card->drv_data);
144
240
  return 0;
145
240
}
146
147
/*****************************************************************************/
148
149
static int process_fci(struct sc_context *ctx, struct sc_file *file,
150
           const u8 *buf, size_t buflen)
151
123
{
152
153
123
  size_t taglen, len = buflen;
154
123
  const u8 *tag = NULL, *p;
155
156
123
  sc_log(ctx,  "processing FCI bytes\n");
157
158
123
  if (buflen < 2)
159
14
    return SC_ERROR_INTERNAL;
160
109
  if (buf[0] != 0x6f)          /* FCI template */
161
16
    return SC_ERROR_INVALID_DATA;
162
93
  len = (size_t)buf[1];
163
93
  if (buflen - 2 < len)
164
7
    return SC_ERROR_INVALID_DATA;
165
86
  p = buf + 2;
166
167
  /* defaults */
168
86
  file->type = SC_FILE_TYPE_WORKING_EF;
169
86
  file->ef_structure = SC_FILE_EF_UNKNOWN;
170
86
  file->shareable = 0;
171
86
  file->record_length = 0;
172
86
  file->size = 0;
173
174
  /* get file size */
175
86
  tag = sc_asn1_find_tag(ctx, p, len, 0x80, &taglen);
176
86
  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
86
    tag = sc_asn1_find_tag(ctx, p, len, 0x82, &taglen);
184
86
  if (tag != NULL) {
185
30
    const char *type = "unknown";
186
30
    const char *structure = "unknown";
187
188
30
    if (taglen == 1 && tag[0] == 0x01) {
189
      /* transparent EF */
190
6
      type = "working EF";
191
6
      structure = "transparent";
192
6
      file->type = SC_FILE_TYPE_WORKING_EF;
193
6
      file->ef_structure = SC_FILE_EF_TRANSPARENT;
194
24
    } else if (taglen == 1 && tag[0] == 0x11) {
195
      /* object EF */
196
6
      type = "working EF";
197
6
      structure = "object";
198
6
      file->type = SC_FILE_TYPE_WORKING_EF;
199
6
      file->ef_structure = SC_FILE_EF_TRANSPARENT; /* TODO */
200
18
    } else if (taglen == 3 && tag[1] == 0x21) {
201
4
      type = "working EF";
202
4
      file->record_length = tag[2];
203
4
      file->type = SC_FILE_TYPE_WORKING_EF;
204
      /* linear fixed, cyclic or compute */
205
4
      switch ( tag[0] )
206
4
      {
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
1
        default:
220
1
          structure = "unknown";
221
1
          file->ef_structure = SC_FILE_EF_UNKNOWN;
222
1
          file->record_length = 0;
223
1
          break;
224
4
      }
225
4
    }
226
227
30
    sc_log(ctx,  "  type: %s\n", type);
228
30
    sc_log(ctx,  "  EF structure: %s\n", structure);
229
30
  }
230
86
  file->magic = SC_FILE_MAGIC;
231
232
86
  return SC_SUCCESS;
233
86
}
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
480
{
241
480
  sc_apdu_t apdu;
242
480
  int r;
243
480
  size_t i = 0;
244
245
480
  sc_format_apdu(card, &apdu, SC_APDU_CASE_3_SHORT, 0xA4, 0x04, 0x0C);
246
480
  apdu.lc = len;
247
480
  apdu.data = (u8*)aid;
248
480
  apdu.datalen = len;
249
480
  apdu.resplen = 0;
250
480
  apdu.le = 0;
251
480
  r = sc_transmit_apdu(card, &apdu);
252
480
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
253
254
  /* check return value */
255
472
  if (!(apdu.sw1 == 0x90 && apdu.sw2 == 0x00) && apdu.sw1 != 0x61)
256
410
        SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
257
258
62
  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
62
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
275
62
}
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
927
{
283
927
  sc_apdu_t apdu;
284
927
  u8 data[] = {id_hi & 0xff, id_lo & 0xff};
285
927
  u8 resp[SC_MAX_APDU_BUFFER_SIZE];
286
927
  int bIsDF = 0, r;
287
288
  /* request FCI to distinguish between EFs and DFs */
289
927
  sc_format_apdu(card, &apdu, SC_APDU_CASE_4_SHORT, 0xA4, 0x00, 0x00);
290
927
  apdu.resp = (u8*)resp;
291
927
  apdu.resplen = SC_MAX_APDU_BUFFER_SIZE;
292
927
  apdu.le = 256;
293
927
  apdu.lc = 2;
294
927
  apdu.data = (u8*)data;
295
927
  apdu.datalen = 2;
296
297
927
  r = sc_transmit_apdu(card, &apdu);
298
927
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
299
300
910
  if (apdu.p2 == 0x00 && apdu.sw1 == 0x62 && apdu.sw2 == 0x84 ) {
301
    /* no FCI => we have a DF (see comment in process_fci()) */
302
35
    bIsDF = 1;
303
35
    apdu.p2 = 0x0C;
304
35
    apdu.cse = SC_APDU_CASE_3_SHORT;
305
35
    apdu.resplen = 0;
306
35
    apdu.le = 0;
307
35
    r = sc_transmit_apdu(card, &apdu);
308
35
    LOG_TEST_RET(card->ctx, r, "APDU re-transmit failed");
309
875
      } 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
335
    sc_apdu_t apdu2;
313
335
    u8 resp2[2];
314
335
    sc_format_apdu(card, &apdu2, SC_APDU_CASE_2_SHORT, 0xB0, 0, 0);
315
335
    apdu2.resp = (u8*)resp2;
316
335
    apdu2.resplen = 2;
317
335
    apdu2.le = 1;
318
335
    apdu2.lc = 0;
319
335
    r = sc_transmit_apdu(card, &apdu2);
320
335
    LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
321
321
    if (apdu2.sw1 == 0x69 && apdu2.sw2 == 0x86)
322
      /* no current EF is selected => we have a DF */
323
19
      bIsDF = 1;
324
321
  }
325
326
888
  if (apdu.sw1 != 0x61 && (apdu.sw1 != 0x90 || apdu.sw2 != 0x00))
327
551
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, sc_check_sw(card, apdu.sw1, apdu.sw2));
328
329
337
  if (file_out) {
330
134
    sc_file_t *file = sc_file_new();
331
134
    if (!file)
332
134
      LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY);
333
134
    file->id = (id_hi << 8) + id_lo;
334
335
134
    if (bIsDF) {
336
      /* we have a DF */
337
11
      file->type = SC_FILE_TYPE_DF;
338
11
      file->ef_structure = SC_FILE_EF_UNKNOWN;
339
11
      file->size = 0;
340
11
      file->namelen = 0;
341
11
      file->magic = SC_FILE_MAGIC;
342
11
      *file_out = file;
343
123
    } else {
344
      /* ok, assume we have a EF */
345
123
      r = process_fci(card->ctx, file, apdu.resp,
346
123
          apdu.resplen);
347
123
      if (r != SC_SUCCESS) {
348
37
        sc_file_free(file);
349
37
        return r;
350
37
      }
351
352
86
      *file_out = file;
353
86
    }
354
134
  }
355
356
300
  SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_SUCCESS);
357
300
}
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.21k
{
365
1.21k
  u8 pathbuf[SC_MAX_PATH_SIZE], *path = pathbuf;
366
1.21k
  int    r;
367
1.21k
  size_t i, pathlen;
368
369
1.21k
  memcpy(path, in_path->value, in_path->len);
370
1.21k
  pathlen = in_path->len;
371
372
1.21k
  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.21k
  } else if (in_path->type == SC_PATH_TYPE_DF_NAME) {
379
    /* SELECT DF with AID */
380
    /* Select with 1-16byte Application-ID */
381
480
    return atrust_acos_select_aid(card, pathbuf, pathlen, file_out);
382
738
  } else if (in_path->type == SC_PATH_TYPE_PATH) {
383
738
    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
738
    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
737
    if (pathlen == 6 && ( path[0] != 0x3f || path[1] != 0x00 ))
395
2
      SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
396
397
    /* unify path (the first FID should be MF) */
398
735
    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
927
    for (i = 0; i < pathlen - 2; i += 2) {
408
745
      r = atrust_acos_select_fid(card, path[i], path[i + 1], NULL);
409
745
      LOG_TEST_RET(card->ctx, r, "SELECT FILE (DF-ID) failed");
410
745
    }
411
182
    return atrust_acos_select_fid(card, path[pathlen - 2], path[pathlen - 1], file_out);
412
735
  } else
413
0
    SC_FUNC_RETURN(card->ctx, SC_LOG_DEBUG_VERBOSE, SC_ERROR_INVALID_ARGUMENTS);
414
1.21k
}
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.22k
{
694
695
1.22k
  sc_log(card->ctx,  "sw1 = 0x%02x, sw2 = 0x%02x\n", sw1, sw2);
696
697
1.22k
  if (sw1 == 0x90 && sw2 == 0x00)
698
119
    return SC_SUCCESS;
699
1.10k
  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
1.09k
  return iso_ops->check_sw(card, sw1, sw2);
708
1.10k
}
709
710
/*****************************************************************************/
711
712
static int acos_get_serialnr(sc_card_t *card, sc_serial_number_t *serial)
713
20
{
714
20
  int r;
715
20
  u8  rbuf[SC_MAX_APDU_BUFFER_SIZE];
716
20
  sc_apdu_t apdu;
717
718
20
  if (!serial)
719
0
    return SC_ERROR_INVALID_ARGUMENTS;
720
  /* see if we have cached serial number */
721
20
  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
20
  sc_format_apdu(card, &apdu, SC_APDU_CASE_2_SHORT, 0xf6, 0x00, 0x00);
727
20
  apdu.cla |= 0x80;
728
20
  apdu.resp = rbuf;
729
20
  apdu.resplen = sizeof(rbuf);
730
20
  apdu.le   = 256;
731
20
  apdu.lc   = 0;
732
20
  apdu.datalen = 0;
733
20
        r = sc_transmit_apdu(card, &apdu);
734
20
  LOG_TEST_RET(card->ctx, r, "APDU transmit failed");
735
17
  if (apdu.sw1 != 0x90 || apdu.sw2 != 0x00)
736
9
    return SC_ERROR_INTERNAL;
737
  /* cache serial number */
738
8
  memcpy(card->serialnr.value, apdu.resp, MIN(apdu.resplen, SC_MAX_SERIALNR));
739
8
  card->serialnr.len = MIN(apdu.resplen, SC_MAX_SERIALNR);
740
  /* copy and return serial number */
741
8
  memcpy(serial, &card->serialnr, sizeof(*serial));
742
8
  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
20
{
749
750
20
  switch (cmd)
751
20
  {
752
20
  case SC_CARDCTL_GET_SERIALNR:
753
20
    return acos_get_serialnr(card, (sc_serial_number_t *)ptr);
754
0
  default:
755
0
    return SC_ERROR_NOT_SUPPORTED;
756
20
  }
757
20
}
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
15.4k
{
790
15.4k
  struct sc_card_driver *iso_drv = sc_get_iso7816_driver();
791
15.4k
  if (iso_ops == NULL)
792
1
    iso_ops = iso_drv->ops;
793
794
15.4k
  atrust_acos_ops = *iso_drv->ops;
795
15.4k
  atrust_acos_ops.match_card = atrust_acos_match_card;
796
15.4k
  atrust_acos_ops.init   = atrust_acos_init;
797
15.4k
  atrust_acos_ops.finish = atrust_acos_finish;
798
15.4k
  atrust_acos_ops.select_file = atrust_acos_select_file;
799
15.4k
  atrust_acos_ops.check_sw    = atrust_acos_check_sw;
800
15.4k
  atrust_acos_ops.create_file = NULL;
801
15.4k
  atrust_acos_ops.delete_file = NULL;
802
15.4k
  atrust_acos_ops.set_security_env  = atrust_acos_set_security_env;
803
15.4k
  atrust_acos_ops.compute_signature = atrust_acos_compute_signature;
804
15.4k
  atrust_acos_ops.decipher    = atrust_acos_decipher;
805
15.4k
  atrust_acos_ops.card_ctl    = atrust_acos_card_ctl;
806
15.4k
  atrust_acos_ops.logout      = atrust_acos_logout;
807
808
15.4k
  return &atrust_acos_drv;
809
15.4k
}
810
811
/*****************************************************************************/
812
813
struct sc_card_driver * sc_get_atrust_acos_driver(void)
814
15.4k
{
815
15.4k
  return sc_get_driver();
816
15.4k
}