Coverage Report

Created: 2026-09-01 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-oberthur.c
Line
Count
Source
1
/*
2
 * PKCS15 emulation layer for Oberthur card.
3
 *
4
 * Copyright (C) 2010, Viktor Tarasov <vtarasov@opentrust.com>
5
 * Copyright (C) 2005, Andrea Frigido <andrea@frisoft.it>
6
 * Copyright (C) 2005, Sirio Capizzi <graaf@virgilio.it>
7
 * Copyright (C) 2004, Antonino Iacono <ant_iacono@tin.it>
8
 * Copyright (C) 2003, Olaf Kirch <okir@suse.de>
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU Lesser General Public
12
 * License as published by the Free Software Foundation; either
13
 * version 2.1 of the License, or (at your option) any later version.
14
 *
15
 * This library is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18
 * Lesser General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Lesser General Public
21
 * License along with this library; if not, write to the Free Software
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
 */
24
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
27
#endif
28
29
#include <stdlib.h>
30
#include <string.h>
31
#include <stdio.h>
32
#include "../common/compat_strlcpy.h"
33
34
#include "pkcs15.h"
35
#include "log.h"
36
#include "asn1.h"
37
#include "internal.h"
38
39
#ifdef ENABLE_OPENSSL
40
#include <openssl/bio.h>
41
#include <openssl/x509.h>
42
#include <openssl/x509v3.h>
43
#endif
44
45
331
#define OBERTHUR_ATTR_MODIFIABLE  0x0001
46
#define OBERTHUR_ATTR_TRUSTED   0x0002
47
#define OBERTHUR_ATTR_LOCAL   0x0004
48
308
#define OBERTHUR_ATTR_ENCRYPT   0x0008
49
308
#define OBERTHUR_ATTR_DECRYPT   0x0010
50
308
#define OBERTHUR_ATTR_SIGN    0x0020
51
308
#define OBERTHUR_ATTR_VERIFY    0x0040
52
308
#define OBERTHUR_ATTR_RSIGN   0x0080
53
308
#define OBERTHUR_ATTR_RVERIFY   0x0100
54
308
#define OBERTHUR_ATTR_WRAP    0x0200
55
308
#define OBERTHUR_ATTR_UNWRAP    0x0400
56
308
#define OBERTHUR_ATTR_DERIVE    0x0800
57
58
#define USAGE_PRV_ENC (SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_DECRYPT |\
59
       SC_PKCS15_PRKEY_USAGE_WRAP | SC_PKCS15_PRKEY_USAGE_UNWRAP)
60
#define USAGE_PRV_AUT  SC_PKCS15_PRKEY_USAGE_SIGN
61
#define USAGE_PRV_SIGN  (SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION)
62
#define USAGE_PUB_ENC (SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP)
63
#define USAGE_PUB_AUT  SC_PKCS15_PRKEY_USAGE_VERIFY
64
#define USAGE_PUB_SIGN  (SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER)
65
66
22
#define PIN_DOMAIN_LABEL  "SCM"
67
const unsigned char PinDomainID[3] = {0x53, 0x43, 0x4D};
68
69
895
#define AWP_PIN_DF    "3F005011"
70
#define AWP_TOKEN_INFO    "3F0050111000"
71
#define AWP_PUK_FILE    "3F0050112000"
72
#define AWP_CONTAINERS_MS "3F0050113000"
73
#define AWP_OBJECTS_LIST_PUB  "3F0050114000"
74
0
#define AWP_OBJECTS_LIST_PRV  "3F0050115000"
75
205
#define AWP_OBJECTS_DF_PUB  "3F0050119001"
76
573
#define AWP_OBJECTS_DF_PRV  "3F0050119002"
77
#define AWP_BASE_RSA_PRV  "3F00501190023000"
78
#define AWP_BASE_RSA_PUB  "3F00501190011000"
79
#define AWP_BASE_CERTIFICATE  "3F00501190012000"
80
81
62
#define BASE_ID_PUB_RSA   0x10
82
36
#define BASE_ID_CERT    0x20
83
348
#define BASE_ID_PRV_RSA   0x30
84
6
#define BASE_ID_PRV_DES   0x40
85
59
#define BASE_ID_PUB_DATA  0x50
86
25
#define BASE_ID_PRV_DATA  0x60
87
10
#define BASE_ID_PUB_DES   0x70
88
89
static int sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *, unsigned, unsigned);
90
static int sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *, unsigned, unsigned);
91
static int sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *, unsigned);
92
static int sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *, unsigned, unsigned, int);
93
94
static int sc_oberthur_parse_tokeninfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
95
static int sc_oberthur_parse_containers (struct sc_pkcs15_card *, unsigned char *, size_t, int);
96
static int sc_oberthur_parse_publicinfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
97
static int sc_oberthur_parse_privateinfo (struct sc_pkcs15_card *, unsigned char *, size_t, int);
98
99
static int sc_awp_parse_df(struct sc_pkcs15_card *, struct sc_pkcs15_df *);
100
static void sc_awp_clear(struct sc_pkcs15_card *);
101
102
struct crypto_container {
103
  unsigned  id_pub;
104
  unsigned  id_prv;
105
  unsigned  id_cert;
106
};
107
108
struct container {
109
  char uuid[37];
110
  struct crypto_container exchange;
111
  struct crypto_container sign;
112
113
  struct container *next;
114
  struct container *prev;
115
};
116
117
struct container *Containers = NULL;
118
119
static struct {
120
  const char *name;
121
  const char *path;
122
  unsigned char *content;
123
  size_t len;
124
  int (*parser)(struct sc_pkcs15_card *, unsigned char *, size_t, int);
125
  int postpone_allowed;
126
} oberthur_infos[] = {
127
  /* Never change the following order */
128
  { "Token info",     AWP_TOKEN_INFO,   NULL, 0, sc_oberthur_parse_tokeninfo,   0},
129
  { "Containers MS",    AWP_CONTAINERS_MS,  NULL, 0, sc_oberthur_parse_containers,  0},
130
  { "Public objects list",  AWP_OBJECTS_LIST_PUB,   NULL, 0, sc_oberthur_parse_publicinfo,  0},
131
  { "Private objects list", AWP_OBJECTS_LIST_PRV, NULL, 0, sc_oberthur_parse_privateinfo, 1},
132
  { NULL, NULL, NULL, 0, NULL, 0}
133
};
134
135
136
static unsigned
137
sc_oberthur_decode_usage(unsigned flags)
138
308
{
139
308
  unsigned ret = 0;
140
141
308
  if (flags & OBERTHUR_ATTR_ENCRYPT)
142
258
    ret |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
143
308
  if (flags & OBERTHUR_ATTR_DECRYPT)
144
250
    ret |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
145
308
  if (flags & OBERTHUR_ATTR_SIGN)
146
43
    ret |= SC_PKCS15_PRKEY_USAGE_SIGN;
147
308
  if (flags & OBERTHUR_ATTR_RSIGN)
148
254
    ret |= SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
149
308
  if (flags & OBERTHUR_ATTR_WRAP)
150
291
    ret |= SC_PKCS15_PRKEY_USAGE_WRAP;
151
308
  if (flags & OBERTHUR_ATTR_UNWRAP)
152
16
    ret |= SC_PKCS15_PRKEY_USAGE_UNWRAP;
153
308
  if (flags & OBERTHUR_ATTR_VERIFY)
154
259
    ret |= SC_PKCS15_PRKEY_USAGE_VERIFY;
155
308
  if (flags & OBERTHUR_ATTR_RVERIFY)
156
14
    ret |= SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
157
308
  if (flags & OBERTHUR_ATTR_DERIVE)
158
13
    ret |= SC_PKCS15_PRKEY_USAGE_DERIVE;
159
308
  return ret;
160
308
}
161
162
163
static int
164
sc_oberthur_get_friends (unsigned int id, struct crypto_container *ccont)
165
338
{
166
338
  struct container *cont;
167
168
31.6k
  for (cont = Containers; cont; cont = cont->next)   {
169
31.6k
    if (cont->exchange.id_pub == id || cont->exchange.id_prv == id || cont->exchange.id_cert == id)   {
170
301
      if (ccont)
171
301
        memcpy(ccont, &cont->exchange, sizeof(struct crypto_container));
172
301
      break;
173
301
    }
174
175
31.3k
    if (cont->sign.id_pub == id || cont->sign.id_prv == id || cont->sign.id_cert == id)   {
176
10
      if (ccont)
177
10
        memcpy(ccont, &cont->sign, sizeof(struct crypto_container));
178
10
      break;
179
10
    }
180
31.3k
  }
181
182
338
  return cont ? 0 : SC_ERROR_TEMPLATE_NOT_FOUND;
183
338
}
184
185
186
static int
187
sc_oberthur_get_certificate_authority(sc_context_t *ctx, struct sc_pkcs15_der *der, int *out_authority)
188
3
{
189
3
#ifdef ENABLE_OPENSSL
190
3
  X509  *x;
191
3
  BUF_MEM buf_mem;
192
3
  BIO *bio = NULL;
193
3
  BASIC_CONSTRAINTS *bs = NULL;
194
195
3
  if (!der)
196
0
    return SC_ERROR_INVALID_ARGUMENTS;
197
198
3
  buf_mem.data = malloc(der->len);
199
3
  if (!buf_mem.data)
200
0
    return SC_ERROR_OUT_OF_MEMORY;
201
202
3
  memcpy(buf_mem.data, der->value, der->len);
203
3
  buf_mem.max = buf_mem.length = der->len;
204
205
3
  bio = BIO_new(BIO_s_mem());
206
3
  if (!bio) {
207
0
    free(buf_mem.data);
208
0
    sc_log_openssl(ctx);
209
0
    return SC_ERROR_OUT_OF_MEMORY;
210
0
  }
211
212
3
  BIO_set_mem_buf(bio, &buf_mem, BIO_NOCLOSE);
213
3
  x = d2i_X509_bio(bio, 0);
214
3
  free(buf_mem.data);
215
3
  BIO_free(bio);
216
3
  if (!x) {
217
3
    sc_log_openssl(ctx);
218
3
    return SC_ERROR_INVALID_DATA;
219
3
  }
220
221
0
  bs = (BASIC_CONSTRAINTS *)X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL);
222
0
  if (out_authority)
223
0
    *out_authority = (bs && bs->ca);
224
225
0
  X509_free(x);
226
227
0
  return SC_SUCCESS;
228
#else
229
  return SC_ERROR_NOT_SUPPORTED;
230
#endif
231
3
}
232
233
234
static int
235
sc_oberthur_read_file(struct sc_pkcs15_card *p15card, const char *in_path,
236
    unsigned char **out, size_t *out_len,
237
    int verify_pin)
238
2.21k
{
239
2.21k
  struct sc_context *ctx = p15card->card->ctx;
240
2.21k
  struct sc_card *card = p15card->card;
241
2.21k
  struct sc_file *file = NULL;
242
2.21k
  struct sc_path path;
243
2.21k
  size_t sz;
244
2.21k
  int rv;
245
246
2.21k
  LOG_FUNC_CALLED(ctx);
247
2.21k
  if (!in_path || !out || !out_len)
248
2.21k
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot read oberthur file");
249
250
2.21k
  sc_log(ctx, "read file '%s'; verify_pin:%i", in_path, verify_pin);
251
252
2.21k
  *out = NULL;
253
2.21k
  *out_len = 0;
254
255
2.21k
  sc_format_path(in_path, &path);
256
2.21k
  rv = sc_select_file(card, &path, &file);
257
2.21k
  if (rv != SC_SUCCESS) {
258
124
    sc_file_free(file);
259
124
    LOG_TEST_RET(ctx, rv, "Cannot select oberthur file to read");
260
124
  }
261
262
2.09k
  if (file->ef_structure == SC_FILE_EF_TRANSPARENT)
263
99
    sz = file->size;
264
1.99k
  else
265
1.99k
    sz = (file->record_length + 2) * file->record_count;
266
267
2.09k
  *out = calloc(1, sz);
268
2.09k
  if (*out == NULL) {
269
0
    sc_file_free(file);
270
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot read oberthur file");
271
0
  }
272
273
2.09k
  if (file->ef_structure == SC_FILE_EF_TRANSPARENT)   {
274
99
    rv = sc_read_binary(card, 0, *out, sz, 0);
275
99
  }
276
1.99k
  else  {
277
1.99k
    unsigned int rec;
278
1.99k
    size_t offs = 0;
279
1.99k
    size_t rec_len = file->record_length;
280
281
176k
    for (rec = 1; ; rec++)   {
282
176k
      if (rec > file->record_count) {
283
1.96k
        rv = 0;
284
1.96k
        break;
285
1.96k
      }
286
174k
      rv = sc_read_record(card, rec, 0, *out + offs + 2, rec_len, SC_RECORD_BY_REC_NR);
287
174k
      if (rv == SC_ERROR_RECORD_NOT_FOUND)   {
288
1
        rv = 0;
289
1
        break;
290
1
      }
291
174k
      else if (rv < 0)   {
292
30
        break;
293
30
      }
294
295
174k
      rec_len = rv;
296
297
174k
      *(*out + offs) = 'R';
298
174k
      *(*out + offs + 1) = rv;
299
300
174k
      offs += rv + 2;
301
174k
    }
302
303
1.99k
    sz = offs;
304
1.99k
  }
305
306
2.09k
  sc_log(ctx, "read oberthur file result %i", rv);
307
2.09k
  if (verify_pin && rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   {
308
3
    struct sc_pkcs15_object *objs[0x10], *pin_obj = NULL;
309
3
    const struct sc_acl_entry *acl = sc_file_get_acl_entry(file, SC_AC_OP_READ);
310
3
    int ii, nobjs;
311
312
3
    if (acl == NULL) {
313
1
      sc_file_free(file);
314
1
      free(*out);
315
1
      *out = NULL;
316
1
      LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_DATA);
317
1
    }
318
319
2
    nobjs = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_AUTH_PIN, objs, 0x10);
320
2
    if (nobjs < 1) {
321
0
      sc_file_free(file);
322
0
      free(*out);
323
0
      *out = NULL;
324
0
      LOG_TEST_RET(ctx, SC_ERROR_DATA_OBJECT_NOT_FOUND,
325
0
        "Cannot read oberthur file: get AUTH objects error");
326
0
    }
327
328
3
    for (ii = 0; ii < nobjs; ii++) {
329
2
      struct sc_pkcs15_auth_info *auth_info = (struct sc_pkcs15_auth_info *) objs[ii]->data;
330
2
      sc_log(ctx, "compare PIN/ACL refs:%i/%i, method:%i/%i",
331
2
        auth_info->attrs.pin.reference, acl->key_ref, auth_info->auth_method, acl->method);
332
2
      if (auth_info->attrs.pin.reference == (int)acl->key_ref && auth_info->auth_method == (unsigned)acl->method)   {
333
1
        pin_obj = objs[ii];
334
1
        break;
335
1
      }
336
2
    }
337
338
2
    if (!pin_obj || !pin_obj->content.value)    {
339
2
      rv = SC_ERROR_SECURITY_STATUS_NOT_SATISFIED;
340
2
    }
341
0
    else    {
342
0
      rv = sc_pkcs15_verify_pin(p15card, pin_obj, pin_obj->content.value, pin_obj->content.len);
343
0
      if (!rv)
344
0
        rv = sc_oberthur_read_file(p15card, in_path, out, out_len, 0);
345
0
    }
346
2
  }
347
348
2.09k
  sc_file_free(file);
349
350
2.09k
  if (rv < 0)   {
351
30
    free(*out);
352
30
    *out = NULL;
353
30
    *out_len = 0;
354
30
  }
355
356
2.09k
  *out_len = sz;
357
358
2.09k
  LOG_FUNC_RETURN(ctx, rv);
359
2.09k
}
360
361
362
static int
363
sc_oberthur_parse_tokeninfo (struct sc_pkcs15_card *p15card,
364
    unsigned char *buff, size_t len, int postpone_allowed)
365
493
{
366
493
  struct sc_context *ctx = p15card->card->ctx;
367
493
  char label[0x21];
368
493
  unsigned flags;
369
493
  int ii;
370
371
493
  LOG_FUNC_CALLED(ctx);
372
493
  if (!buff || len < 0x24)
373
493
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Cannot parse token info");
374
375
469
  memset(label, 0, sizeof(label));
376
377
469
  memcpy(label, buff, 0x20);
378
469
  ii = 0x20;
379
542
  while (*(label + --ii)==' ' && ii)
380
73
    ;
381
469
  *(label + ii + 1) = '\0';
382
383
469
  flags = *(buff + 0x22) * 0x100 + *(buff + 0x23);
384
385
469
  set_string(&p15card->tokeninfo->label, label);
386
469
  set_string(&p15card->tokeninfo->manufacturer_id, "Oberthur/OpenSC");
387
388
469
  if (flags & 0x01)
389
4
    p15card->tokeninfo->flags |= SC_PKCS15_TOKEN_PRN_GENERATION;
390
391
469
  sc_log(ctx, "label %s", p15card->tokeninfo->label);
392
469
  sc_log(ctx, "manufacturer_id %s", p15card->tokeninfo->manufacturer_id);
393
394
469
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
395
469
}
396
397
398
static int
399
sc_oberthur_parse_containers (struct sc_pkcs15_card *p15card,
400
    unsigned char *buff, size_t len, int postpone_allowed)
401
445
{
402
445
  struct sc_context *ctx = p15card->card->ctx;
403
445
  size_t offs;
404
405
445
  LOG_FUNC_CALLED(ctx);
406
407
22.3k
  while (Containers)   {
408
21.9k
    struct container *next = Containers->next;
409
410
21.9k
    free (Containers);
411
21.9k
    Containers = next;
412
21.9k
  }
413
414
22.3k
  for (offs=0; offs + 2 + 2+2+2 + 2+2+2 + 2+36 <= len;)  {
415
21.9k
    struct container *cont;
416
21.9k
    unsigned char *ptr =  buff + offs + 2;
417
418
21.9k
    sc_log(ctx, "parse contaniers offs:%zu, len:%zu", offs, len);
419
21.9k
    if (*(buff + offs) != 'R')
420
3
      return SC_ERROR_INVALID_DATA;
421
422
21.9k
    cont = (struct container *)calloc(1, sizeof(struct container));
423
21.9k
    if (!cont)
424
0
      return SC_ERROR_OUT_OF_MEMORY;
425
426
21.9k
    cont->exchange.id_pub = *ptr * 0x100 + *(ptr + 1);  ptr += 2;
427
21.9k
    cont->exchange.id_prv = *ptr * 0x100 + *(ptr + 1);  ptr += 2;
428
21.9k
    cont->exchange.id_cert = *ptr * 0x100 + *(ptr + 1); ptr += 2;
429
430
21.9k
    cont->sign.id_pub = *ptr * 0x100 + *(ptr + 1);  ptr += 2;
431
21.9k
    cont->sign.id_prv = *ptr * 0x100 + *(ptr + 1);  ptr += 2;
432
21.9k
    cont->sign.id_cert = *ptr * 0x100 + *(ptr + 1); ptr += 2;
433
434
21.9k
    memcpy(cont->uuid, ptr + 2, 36);
435
21.9k
    sc_log(ctx, "UUID: %s; 0x%X, 0x%X, 0x%X", cont->uuid,
436
21.9k
        cont->exchange.id_pub, cont->exchange.id_prv, cont->exchange.id_cert);
437
438
21.9k
    if (!Containers)  {
439
246
      Containers = cont;
440
246
    }
441
21.6k
    else   {
442
21.6k
      cont->next = Containers;
443
21.6k
      Containers->prev = (void *)cont;
444
21.6k
      Containers = cont;
445
21.6k
    }
446
447
21.9k
    offs += *(buff + offs + 1) + 2;
448
21.9k
  }
449
450
442
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
451
442
}
452
453
454
static int
455
sc_oberthur_parse_publicinfo (struct sc_pkcs15_card *p15card,
456
    unsigned char *buff, size_t len, int postpone_allowed)
457
423
{
458
423
  struct sc_context *ctx = p15card->card->ctx;
459
423
  size_t ii;
460
423
  int rv;
461
462
423
  LOG_FUNC_CALLED(ctx);
463
27.4k
  for (ii=0; ii+5<=len; ii+=5)   {
464
27.1k
    unsigned int file_id, size;
465
466
27.1k
    if(*(buff+ii) != 0xFF)
467
26.9k
      continue;
468
469
182
    file_id = 0x100 * *(buff+ii + 1) + *(buff+ii + 2);
470
182
    size = 0x100 * *(buff+ii + 3) + *(buff+ii + 4);
471
182
    sc_log(ctx, "add public object(file-id:%04X,size:%X)", file_id, size);
472
473
182
    switch (*(buff+ii + 1))   {
474
62
    case BASE_ID_PUB_RSA :
475
62
      rv = sc_pkcs15emu_oberthur_add_pubkey(p15card, file_id, size);
476
62
      LOG_TEST_RET(ctx, rv, "Cannot parse public key info");
477
13
      break;
478
36
    case BASE_ID_CERT :
479
36
      rv = sc_pkcs15emu_oberthur_add_cert(p15card, file_id);
480
36
      LOG_TEST_RET(ctx, rv, "Cannot parse certificate info");
481
0
      break;
482
10
    case BASE_ID_PUB_DES :
483
10
      break;
484
59
    case BASE_ID_PUB_DATA :
485
59
      rv = sc_pkcs15emu_oberthur_add_data(p15card, file_id, size, 0);
486
59
      LOG_TEST_RET(ctx, rv, "Cannot parse data info");
487
18
      break;
488
18
    default:
489
15
      LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Public object parse error");
490
182
    }
491
182
  }
492
493
282
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
494
282
}
495
496
497
static int
498
sc_oberthur_parse_privateinfo (struct sc_pkcs15_card *p15card,
499
    unsigned char *buff, size_t len, int postpone_allowed)
500
253
{
501
253
  struct sc_context *ctx = p15card->card->ctx;
502
253
  size_t ii;
503
253
  int rv;
504
253
  int no_more_private_keys = 0, no_more_private_data = 0;
505
506
253
  LOG_FUNC_CALLED(ctx);
507
508
32.4k
  for (ii=0; ii+5<=len; ii+=5)   {
509
32.3k
    unsigned int file_id, size;
510
511
32.3k
    if(*(buff+ii) != 0xFF)
512
31.9k
      continue;
513
514
386
    file_id = 0x100 * *(buff+ii + 1) + *(buff+ii + 2);
515
386
    size = 0x100 * *(buff+ii + 3) + *(buff+ii + 4);
516
386
    sc_log(ctx, "add private object (file-id:%04X, size:%X)", file_id, size);
517
518
386
    switch (*(buff+ii + 1))   {
519
348
    case BASE_ID_PRV_RSA :
520
348
      if (no_more_private_keys)
521
10
        break;
522
523
338
      rv = sc_pkcs15emu_oberthur_add_prvkey(p15card, file_id, size);
524
338
      if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed)   {
525
5
        struct sc_path path;
526
527
5
        sc_log(ctx, "postpone adding of the private keys");
528
5
        sc_format_path("5011A5A5", &path);
529
5
        rv = sc_pkcs15_add_df(p15card, SC_PKCS15_PRKDF, &path);
530
5
        LOG_TEST_RET(ctx, rv, "Add PrkDF error");
531
5
        no_more_private_keys = 1;
532
5
      }
533
338
      LOG_TEST_RET(ctx, rv, "Cannot parse private key info");
534
254
      break;
535
254
    case BASE_ID_PRV_DES :
536
6
      break;
537
25
    case BASE_ID_PRV_DATA :
538
25
      sc_log(ctx, "*(buff+ii + 1):%X", *(buff+ii + 1));
539
25
      if (no_more_private_data)
540
10
        break;
541
542
15
      rv = sc_pkcs15emu_oberthur_add_data(p15card, file_id, size, 1);
543
15
      if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED && postpone_allowed)   {
544
4
        struct sc_path path;
545
546
4
        sc_log(ctx, "postpone adding of the private data");
547
4
        sc_format_path("5011A6A6", &path);
548
4
        rv = sc_pkcs15_add_df(p15card, SC_PKCS15_DODF, &path);
549
4
        LOG_TEST_RET(ctx, rv, "Add DODF error");
550
4
        no_more_private_data = 1;
551
4
      }
552
15
      LOG_TEST_RET(ctx, rv, "Cannot parse private data info");
553
9
      break;
554
9
    default:
555
7
      LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Private object parse error");
556
386
    }
557
386
  }
558
559
156
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
560
156
}
561
562
563
/* Public key info:
564
 *  flags:2,
565
 *  CN(len:2,value:<variable length>),
566
 *  ID(len:2,value:(SHA1 value)),
567
 *  StartDate(Ascii:8)
568
 *  EndDate(Ascii:8)
569
 *  ??(0x00:2)
570
 */
571
static int
572
sc_pkcs15emu_oberthur_add_pubkey(struct sc_pkcs15_card *p15card,
573
    unsigned int file_id, unsigned int size)
574
62
{
575
62
  struct sc_context *ctx = p15card->card->ctx;
576
62
  struct sc_pkcs15_pubkey_info key_info;
577
62
  struct sc_pkcs15_object key_obj;
578
62
  char ch_tmp[0x100];
579
62
  unsigned char *info_blob = NULL;
580
62
  size_t len, info_len, offs;
581
62
  unsigned flags;
582
62
  int rv;
583
584
62
  LOG_FUNC_CALLED(ctx);
585
62
  sc_log(ctx, "public key(file-id:%04X,size:%X)", file_id, size);
586
587
62
  memset(&key_info, 0, sizeof(key_info));
588
62
  memset(&key_obj, 0, sizeof(key_obj));
589
590
62
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100);
591
62
  rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
592
62
  LOG_TEST_RET(ctx, rv, "Failed to add public key: read oberthur file error");
593
594
  /* Flags */
595
60
  offs = 2;
596
60
  if (offs > info_len) {
597
1
    free(info_blob);
598
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'tag'");
599
1
  }
600
59
  flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
601
59
  key_info.usage = sc_oberthur_decode_usage(flags);
602
59
  if (flags & OBERTHUR_ATTR_MODIFIABLE)
603
22
    key_obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE;
604
59
  sc_log(ctx, "Public key key-usage:%04X", key_info.usage);
605
606
  /* Label */
607
59
  if (offs + 2 > info_len) {
608
1
    free(info_blob);
609
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'Label'");
610
1
  }
611
58
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
612
58
  if (offs + 2 + len > info_len) {
613
10
    free(info_blob);
614
10
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'Label' length");
615
48
  } else if (len) {
616
32
    if (len > sizeof(key_obj.label) - 1)
617
13
      len = sizeof(key_obj.label) - 1;
618
32
    memcpy(key_obj.label, info_blob + offs + 2, len);
619
32
  }
620
48
  offs += 2 + len;
621
622
  /* ID */
623
48
  if (offs + 2 > info_len) {
624
1
    free(info_blob);
625
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add public key: no 'ID'");
626
1
  }
627
47
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
628
47
  if (len == 0
629
32
      || len > sizeof(key_info.id.value)
630
34
      || offs + 2 + len > info_len) {
631
34
    free(info_blob);
632
34
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add public key: invalid 'ID' length");
633
34
  }
634
13
  memcpy(key_info.id.value, info_blob + offs + 2, len);
635
13
  key_info.id.len = len;
636
637
13
  free(info_blob);
638
639
  /* Ignore Start/End dates */
640
641
13
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
642
13
  sc_format_path(ch_tmp, &key_info.path);
643
644
13
  key_info.native = 1;
645
13
  key_info.key_reference = file_id & 0xFF;
646
13
  key_info.modulus_length = size;
647
648
13
  rv = sc_pkcs15emu_add_rsa_pubkey(p15card, &key_obj, &key_info);
649
650
13
  LOG_FUNC_RETURN(ctx, rv);
651
13
}
652
653
654
/* Certificate info:
655
 *  flags:2,
656
 *  Label(len:2,value:),
657
 *  ID(len:2,value:(SHA1 value)),
658
 *  Subject in ASN.1(len:2,value:)
659
 *  Issuer in ASN.1(len:2,value:)
660
 *  Serial encoded in LV or ASN.1 FIXME
661
 */
662
static int
663
sc_pkcs15emu_oberthur_add_cert(struct sc_pkcs15_card *p15card, unsigned int file_id)
664
36
{
665
36
  struct sc_context *ctx = p15card->card->ctx;
666
36
  struct sc_pkcs15_cert_info cinfo;
667
36
  struct sc_pkcs15_object cobj;
668
36
  unsigned char *info_blob = NULL, *cert_blob = NULL;
669
36
  size_t info_len, cert_len, len, offs;
670
36
  unsigned flags;
671
36
  int rv;
672
36
  char ch_tmp[0x20];
673
674
36
  LOG_FUNC_CALLED(ctx);
675
36
  sc_log(ctx, "add certificate(file-id:%04X)", file_id);
676
677
36
  memset(&cinfo, 0, sizeof(cinfo));
678
36
  memset(&cobj, 0, sizeof(cobj));
679
680
36
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id | 0x100);
681
36
  rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
682
36
  LOG_TEST_RET(ctx, rv, "Failed to add certificate: read oberthur file error");
683
684
35
  if (info_len < 2) {
685
1
    free(info_blob);
686
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
687
1
  }
688
34
  flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
689
34
  offs = 2;
690
691
  /* Label */
692
34
  if (offs + 2 > info_len) {
693
1
    free(info_blob);
694
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'CN'");
695
1
  }
696
33
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
697
33
  if (len + offs + 2 > info_len) {
698
3
    free(info_blob);
699
3
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
700
30
  } else if (len) {
701
19
    if (len > sizeof(cobj.label) - 1)
702
16
      len = sizeof(cobj.label) - 1;
703
19
    memcpy(cobj.label, info_blob + offs + 2, len);
704
19
  }
705
30
  offs += 2 + len;
706
707
  /* ID */
708
30
  if (offs + 2 > info_len) {
709
1
    free(info_blob);
710
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'ID'");
711
1
  }
712
29
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
713
29
  if (len + offs + 2 > info_len) {
714
11
    free(info_blob);
715
11
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
716
18
  } else if (len > sizeof(cinfo.id.value)) {
717
1
    free(info_blob);
718
1
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add certificate: invalid 'ID' length");
719
1
  }
720
17
  memcpy(cinfo.id.value, info_blob + offs + 2, len);
721
17
  cinfo.id.len = len;
722
723
17
  free(info_blob);
724
725
  /* Ignore subject, issuer and serial */
726
727
17
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PUB, file_id);
728
17
  sc_format_path(ch_tmp, &cinfo.path);
729
17
  rv = sc_oberthur_read_file(p15card, ch_tmp, &cert_blob, &cert_len, 1);
730
17
  LOG_TEST_RET(ctx, rv, "Failed to add certificate: read certificate error");
731
732
3
  cinfo.value.value = cert_blob;
733
3
  cinfo.value.len = cert_len;
734
735
3
  rv = sc_oberthur_get_certificate_authority(ctx, &cinfo.value, &cinfo.authority);
736
3
  if (rv != SC_SUCCESS) {
737
3
    free(cinfo.value.value);
738
3
    LOG_TEST_RET(ctx, rv, "Failed to add certificate: get certificate attributes error");
739
3
  }
740
741
0
  if (flags & OBERTHUR_ATTR_MODIFIABLE)
742
0
    cobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
743
744
0
  rv = sc_pkcs15emu_add_x509_cert(p15card, &cobj, &cinfo);
745
746
0
  LOG_FUNC_RETURN(p15card->card->ctx, rv);
747
0
}
748
749
750
/* Private key info:
751
 *  flags:2,
752
 *  CN(len:2,value:),
753
 *  ID(len:2,value:(SHA1 value)),
754
 *  StartDate(Ascii:8)
755
 *  EndDate(Ascii:8)
756
 *  Subject in ASN.1(len:2,value:)
757
 *  modulus(value:)
758
 *  exponent(length:1, value:3)
759
 */
760
static int
761
sc_pkcs15emu_oberthur_add_prvkey(struct sc_pkcs15_card *p15card,
762
    unsigned int file_id, unsigned int size)
763
338
{
764
338
  struct sc_context *ctx = p15card->card->ctx;
765
338
  struct sc_pkcs15_prkey_info kinfo;
766
338
  struct sc_pkcs15_object kobj;
767
338
  struct crypto_container ccont;
768
338
  unsigned char *info_blob = NULL;
769
338
  size_t info_len = 0;
770
338
  unsigned flags;
771
338
  size_t offs, len;
772
338
  char ch_tmp[0x100];
773
338
  int rv;
774
775
338
  LOG_FUNC_CALLED(ctx);
776
338
  sc_log(ctx, "add private key(file-id:%04X,size:%04X)", file_id, size);
777
778
338
  memset(&kinfo, 0, sizeof(kinfo));
779
338
  memset(&kobj, 0, sizeof(kobj));
780
338
  memset(&ccont, 0, sizeof(ccont));
781
782
338
  rv = sc_oberthur_get_friends (file_id, &ccont);
783
338
  LOG_TEST_RET(ctx, rv, "Failed to add private key: get friends error");
784
785
311
  if (ccont.id_cert)   {
786
7
    struct sc_pkcs15_object *objs[32];
787
7
    int ii;
788
789
7
    sc_log(ctx, "friend certificate %04X", ccont.id_cert);
790
7
    rv = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509, objs, 32);
791
7
    LOG_TEST_RET(ctx, rv, "Failed to add private key: get certificates error");
792
793
7
    for (ii=0; ii<rv; ii++) {
794
0
      struct sc_pkcs15_cert_info *cert = (struct sc_pkcs15_cert_info *)objs[ii]->data;
795
0
      struct sc_path path = cert->path;
796
0
      unsigned int id = path.value[path.len - 2] * 0x100 + path.value[path.len - 1];
797
798
0
      if (id == ccont.id_cert)   {
799
0
        strlcpy(kobj.label, objs[ii]->label, sizeof(kobj.label));
800
0
        break;
801
0
      }
802
0
    }
803
804
7
    if (ii == rv)
805
7
      LOG_TEST_RET(ctx, SC_ERROR_INCONSISTENT_PROFILE, "Failed to add private key: friend not found");
806
7
  }
807
808
304
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id | 0x100);
809
304
  rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
810
304
  LOG_TEST_RET(ctx, rv, "Failed to add private key: read oberthur file error");
811
812
287
  if (info_len < 2) {
813
3
    free(info_blob);
814
3
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'tag'");
815
3
  }
816
284
  flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
817
284
  offs = 2;
818
819
  /* CN */
820
284
  if (offs + 2 > info_len) {
821
1
    free(info_blob);
822
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'CN'");
823
1
  }
824
283
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
825
283
  if (len + offs + 2 > info_len) {
826
12
    free(info_blob);
827
12
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'CN' length");
828
12
  }
829
271
  if (len && !strlen(kobj.label))   {
830
42
    if (len > sizeof(kobj.label) - 1)
831
1
      len = sizeof(kobj.label) - 1;
832
42
    strncpy(kobj.label, (char *)(info_blob + offs + 2), len);
833
42
  }
834
271
  offs += 2 + len;
835
836
  /* ID */
837
271
  if (offs + 2 > info_len) {
838
1
    free(info_blob);
839
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'ID'");
840
1
  }
841
270
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
842
270
  if (!len) {
843
1
    free(info_blob);
844
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: zero length ID");
845
269
  } else if (len + offs + 2 > info_len) {
846
14
    free(info_blob);
847
14
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'ID' length");
848
255
  } else if (len > sizeof(kinfo.id.value)) {
849
1
    free(info_blob);
850
1
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Failed to add private key: invalid ID length");
851
1
  }
852
254
  memcpy(kinfo.id.value, info_blob + offs + 2, len);
853
254
  kinfo.id.len = len;
854
254
  offs += 2 + len;
855
856
  /* Ignore Start/End dates */
857
254
  offs += 16;
858
859
  /* Subject encoded in ASN1 */
860
254
  if (offs + 2 > info_len) {
861
1
    free(info_blob);
862
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add private key: no 'subject'");
863
1
  }
864
253
  len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
865
253
  if (len + offs + 2 > info_len) {
866
4
    free(info_blob);
867
4
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid 'subject' length");
868
249
  } else if (len) {
869
241
    kinfo.subject.value = malloc(len);
870
241
    if (!kinfo.subject.value) {
871
0
      free(info_blob);
872
0
      LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Failed to add private key: memory allocation error");
873
0
    }
874
241
    kinfo.subject.len = len;
875
241
    memcpy(kinfo.subject.value, info_blob + offs + 2, len);
876
241
  }
877
878
  /* Modulus and exponent are ignored */
879
880
249
  free(info_blob);
881
882
249
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", AWP_OBJECTS_DF_PRV, file_id);
883
249
  sc_format_path(ch_tmp, &kinfo.path);
884
249
  sc_log(ctx, "Private key info path %s", ch_tmp);
885
886
249
  kinfo.modulus_length  = size;
887
249
  kinfo.native    = 1;
888
249
  kinfo.key_reference  = file_id & 0xFF;
889
890
249
  kinfo.usage = sc_oberthur_decode_usage(flags);
891
249
  kobj.flags = SC_PKCS15_CO_FLAG_PRIVATE;
892
249
  if (flags & OBERTHUR_ATTR_MODIFIABLE)
893
10
    kobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
894
895
249
  kobj.auth_id.len = sizeof(PinDomainID) > sizeof(kobj.auth_id.value)
896
249
      ? sizeof(kobj.auth_id.value) : sizeof(PinDomainID);
897
249
  memcpy(kobj.auth_id.value, PinDomainID, kobj.auth_id.len);
898
899
249
  sc_log(ctx, "Parsed private key(reference:%i,usage:%X,flags:%X)", kinfo.key_reference, kinfo.usage, kobj.flags);
900
901
249
  rv = sc_pkcs15emu_add_rsa_prkey(p15card, &kobj, &kinfo);
902
249
  LOG_FUNC_RETURN(ctx, rv);
903
249
}
904
905
906
static int
907
sc_pkcs15emu_oberthur_add_data(struct sc_pkcs15_card *p15card,
908
    unsigned int file_id, unsigned int size, int private)
909
74
{
910
74
  struct sc_context *ctx = p15card->card->ctx;
911
74
  struct sc_pkcs15_data_info dinfo;
912
74
  struct sc_pkcs15_object dobj;
913
74
  unsigned flags;
914
74
  unsigned char *info_blob = NULL, *label = NULL, *app = NULL, *oid = NULL;
915
74
  size_t info_len, label_len, app_len, oid_len, offs;
916
74
  char ch_tmp[0x100];
917
74
  int rv;
918
919
74
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
920
74
  sc_log(ctx, "Add data(file-id:%04X,size:%i,is-private:%i)", file_id, size, private);
921
74
  memset(&dinfo, 0, sizeof(dinfo));
922
74
  memset(&dobj, 0, sizeof(dobj));
923
924
74
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", private ? AWP_OBJECTS_DF_PRV : AWP_OBJECTS_DF_PUB, file_id | 0x100);
925
926
74
  rv = sc_oberthur_read_file(p15card, ch_tmp, &info_blob, &info_len, 1);
927
74
  LOG_TEST_RET(ctx, rv, "Failed to add data: read oberthur file error");
928
929
64
  if (info_len < 2) {
930
1
    free(info_blob);
931
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add certificate: no 'tag'");
932
1
  }
933
63
  flags = *(info_blob + 0) * 0x100 + *(info_blob + 1);
934
63
  offs = 2;
935
936
  /* Label */
937
63
  if (offs + 2 > info_len) {
938
1
    free(info_blob);
939
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'label'");
940
1
  }
941
62
  label = info_blob + offs + 2;
942
62
  label_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
943
62
  if (offs + 2 + label_len > info_len) {
944
8
    free(info_blob);
945
8
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'label' received");
946
8
  }
947
54
  if (label_len > sizeof(dobj.label) - 1)
948
5
    label_len = sizeof(dobj.label) - 1;
949
54
  offs += 2 + *(info_blob + offs + 1);
950
951
  /* Application */
952
54
  if (offs + 2 > info_len) {
953
1
    free(info_blob);
954
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'application'");
955
1
  }
956
53
  app = info_blob + offs + 2;
957
53
  app_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
958
53
  if (offs + 2 + app_len > info_len) {
959
9
    free(info_blob);
960
9
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'application' received");
961
9
  }
962
44
  if (app_len > sizeof(dinfo.app_label) - 1)
963
2
    app_len = sizeof(dinfo.app_label) - 1;
964
44
  offs += 2 + app_len;
965
966
  /* OID encode like DER(ASN.1(oid)) */
967
44
  if (offs + 2 > info_len) {
968
1
    free(info_blob);
969
1
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: no 'OID'");
970
1
  }
971
43
  oid_len = *(info_blob + offs + 1) + *(info_blob + offs) * 0x100;
972
43
  if (offs + 2 + oid_len > info_len) {
973
17
    free(info_blob);
974
17
    LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Invalid length of 'oid' received");
975
17
  }
976
26
  if (oid_len > 2) {
977
4
    oid = info_blob + offs + 2;
978
4
    if (*oid != 0x06 || (*(oid + 1) != oid_len - 2)) {
979
3
      free(info_blob);
980
3
      LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Failed to add data: invalid 'OID' format");
981
3
    }
982
1
    oid += 2;
983
1
    oid_len -= 2;
984
1
  }
985
986
23
  snprintf(ch_tmp, sizeof(ch_tmp), "%s%04X", private ? AWP_OBJECTS_DF_PRV : AWP_OBJECTS_DF_PUB, file_id);
987
988
23
  sc_format_path(ch_tmp, &dinfo.path);
989
990
23
  memcpy(dobj.label, label, label_len);
991
23
  memcpy(dinfo.app_label, app, app_len);
992
23
  if (oid_len)
993
4
    sc_asn1_decode_object_id(oid, oid_len, &dinfo.app_oid);
994
995
23
  if (flags & OBERTHUR_ATTR_MODIFIABLE)
996
12
    dobj.flags |= SC_PKCS15_CO_FLAG_MODIFIABLE;
997
998
23
  if (private)   {
999
5
    dobj.auth_id.len = sizeof(PinDomainID) > sizeof(dobj.auth_id.value)
1000
5
        ? sizeof(dobj.auth_id.value) : sizeof(PinDomainID);
1001
5
    memcpy(dobj.auth_id.value, PinDomainID, dobj.auth_id.len);
1002
1003
5
    dobj.flags |= SC_PKCS15_CO_FLAG_PRIVATE;
1004
5
  }
1005
1006
23
  rv = sc_pkcs15emu_add_data_object(p15card, &dobj, &dinfo);
1007
1008
23
  free(info_blob);
1009
23
  LOG_FUNC_RETURN(p15card->card->ctx, rv);
1010
23
}
1011
1012
1013
static int
1014
sc_pkcs15emu_oberthur_init(struct sc_pkcs15_card * p15card)
1015
873
{
1016
873
  struct sc_context *ctx = p15card->card->ctx;
1017
873
  struct sc_pkcs15_auth_info auth_info;
1018
873
  struct sc_pkcs15_object   obj;
1019
873
  struct sc_card *card = p15card->card;
1020
873
  struct sc_path path;
1021
873
  int rv, ii, tries_left;
1022
873
  char serial[0x10];
1023
873
  unsigned char sopin_reference = 0x04;
1024
1025
873
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1026
873
  sc_bin_to_hex(card->serialnr.value, card->serialnr.len, serial, sizeof(serial), 0);
1027
873
  set_string(&p15card->tokeninfo->serial_number, serial);
1028
1029
873
  p15card->ops.parse_df = sc_awp_parse_df;
1030
873
  p15card->ops.clear = sc_awp_clear;
1031
1032
873
  sc_log(ctx, "Oberthur init: serial %s", p15card->tokeninfo->serial_number);
1033
1034
873
  sc_format_path(AWP_PIN_DF, &path);
1035
873
  rv = sc_select_file(card, &path, NULL);
1036
873
  LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: cannot select PIN dir");
1037
1038
567
  tries_left = -1;
1039
567
  rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
1040
567
  if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT)   {
1041
37
    sopin_reference = 0x84;
1042
37
    rv = sc_verify(card, SC_AC_CHV, sopin_reference, (unsigned char *)"", 0, &tries_left);
1043
37
  }
1044
567
  if (rv && rv != SC_ERROR_PIN_CODE_INCORRECT)
1045
567
    LOG_TEST_GOTO_ERR(ctx, rv, "Invalid state of SO-PIN");
1046
1047
  /* add PIN */
1048
543
  memset(&auth_info, 0, sizeof(auth_info));
1049
543
  memset(&obj,  0, sizeof(obj));
1050
1051
543
  auth_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN;
1052
543
  auth_info.auth_method = SC_AC_CHV;
1053
543
  auth_info.auth_id.len = 1;
1054
543
  auth_info.auth_id.value[0] = 0xFF;
1055
543
  auth_info.attrs.pin.min_length    = 4;
1056
543
  auth_info.attrs.pin.max_length    = 64;
1057
543
  auth_info.attrs.pin.stored_length = 64;
1058
543
  auth_info.attrs.pin.type    = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
1059
543
  auth_info.attrs.pin.reference   = sopin_reference;
1060
543
  auth_info.attrs.pin.pad_char    = 0xFF;
1061
543
  auth_info.attrs.pin.flags   = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
1062
543
        | SC_PKCS15_PIN_FLAG_INITIALIZED
1063
543
        | SC_PKCS15_PIN_FLAG_NEEDS_PADDING
1064
543
        | SC_PKCS15_PIN_FLAG_SO_PIN;
1065
543
  auth_info.tries_left    = tries_left;
1066
543
  auth_info.logged_in = SC_PIN_STATE_UNKNOWN;
1067
1068
543
  strncpy(obj.label, "SO PIN", SC_PKCS15_MAX_LABEL_SIZE-1);
1069
543
  obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
1070
1071
543
  sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
1072
543
      sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
1073
543
  rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
1074
543
  LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: cannot add PIN object");
1075
1076
543
  tries_left = -1;
1077
543
  rv = sc_verify(card, SC_AC_CHV, 0x81, (unsigned char *)"", 0, &tries_left);
1078
543
  if (rv == SC_ERROR_PIN_CODE_INCORRECT)   {
1079
    /* add PIN */
1080
22
    memset(&auth_info, 0, sizeof(auth_info));
1081
22
    memset(&obj,  0, sizeof(obj));
1082
1083
22
    auth_info.auth_id.len = sizeof(PinDomainID) > sizeof(auth_info.auth_id.value)
1084
22
        ? sizeof(auth_info.auth_id.value) : sizeof(PinDomainID);
1085
22
    memcpy(auth_info.auth_id.value, PinDomainID, auth_info.auth_id.len);
1086
22
    auth_info.auth_method = SC_AC_CHV;
1087
1088
22
    auth_info.attrs.pin.min_length    = 4;
1089
22
    auth_info.attrs.pin.max_length    = 64;
1090
22
    auth_info.attrs.pin.stored_length = 64;
1091
22
    auth_info.attrs.pin.type    = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC;
1092
22
    auth_info.attrs.pin.reference   = 0x81;
1093
22
    auth_info.attrs.pin.pad_char    = 0xFF;
1094
22
    auth_info.attrs.pin.flags   = SC_PKCS15_PIN_FLAG_CASE_SENSITIVE
1095
22
          | SC_PKCS15_PIN_FLAG_INITIALIZED
1096
22
          | SC_PKCS15_PIN_FLAG_NEEDS_PADDING
1097
22
          | SC_PKCS15_PIN_FLAG_LOCAL;
1098
22
    auth_info.tries_left    = tries_left;
1099
1100
22
    strncpy(obj.label, PIN_DOMAIN_LABEL, SC_PKCS15_MAX_LABEL_SIZE-1);
1101
22
    obj.flags = SC_PKCS15_CO_FLAG_MODIFIABLE | SC_PKCS15_CO_FLAG_PRIVATE;
1102
22
    if (sopin_reference == 0x84) {
1103
      /*
1104
       * auth_pin_reset_oberthur_style() in card-oberthur.c
1105
       * always uses PUK with reference 0x84 for
1106
       * unblocking of User PIN
1107
       */
1108
3
      obj.auth_id.len = 1;
1109
3
      obj.auth_id.value[0] = 0xFF;
1110
3
    }
1111
1112
22
    sc_format_path(AWP_PIN_DF, &auth_info.path);
1113
22
    auth_info.path.type = SC_PATH_TYPE_PATH;
1114
1115
22
    sc_log(ctx, "Add PIN(%s,auth_id:%s,reference:%i)", obj.label,
1116
22
        sc_pkcs15_print_id(&auth_info.auth_id), auth_info.attrs.pin.reference);
1117
22
    rv = sc_pkcs15emu_add_pin_obj(p15card, &obj, &auth_info);
1118
22
    LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: cannot add PIN object");
1119
22
  }
1120
521
  else if (rv != SC_ERROR_DATA_OBJECT_NOT_FOUND)    {
1121
520
    LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: cannot verify PIN");
1122
520
  }
1123
1124
1.88k
  for (ii=0; oberthur_infos[ii].name; ii++)   {
1125
1.72k
    sc_log(ctx, "Oberthur init: read %s file", oberthur_infos[ii].name);
1126
1.72k
    free(oberthur_infos[ii].content);
1127
1.72k
    rv = sc_oberthur_read_file(p15card, oberthur_infos[ii].path,
1128
1.72k
        &oberthur_infos[ii].content, &oberthur_infos[ii].len, 1);
1129
1.72k
    LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: read oberthur file error");
1130
1131
1.61k
    sc_log(ctx, "Oberthur init: parse %s file, content length %zu",
1132
1.61k
        oberthur_infos[ii].name, oberthur_infos[ii].len);
1133
1.61k
    rv = oberthur_infos[ii].parser(p15card, oberthur_infos[ii].content, oberthur_infos[ii].len,
1134
1.61k
        oberthur_infos[ii].postpone_allowed);
1135
1.61k
    LOG_TEST_GOTO_ERR(ctx, rv, "Oberthur init failed: parse error");
1136
1.61k
  }
1137
1138
156
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1139
1140
717
err:
1141
717
  sc_pkcs15_card_clear(p15card);
1142
717
  LOG_FUNC_RETURN(ctx, rv);
1143
717
}
1144
1145
1146
static int
1147
oberthur_detect_card(struct sc_pkcs15_card * p15card)
1148
10.2k
{
1149
10.2k
  struct sc_card *card = p15card->card;
1150
1151
10.2k
  SC_FUNC_CALLED(card->ctx, SC_LOG_DEBUG_VERBOSE);
1152
10.2k
  if (p15card->card->type != SC_CARD_TYPE_OBERTHUR_64K)
1153
10.2k
    LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_WRONG_CARD);
1154
873
  LOG_FUNC_RETURN(p15card->card->ctx, SC_SUCCESS);
1155
873
}
1156
1157
1158
int
1159
sc_pkcs15emu_oberthur_init_ex(struct sc_pkcs15_card * p15card, struct sc_aid *aid)
1160
10.2k
{
1161
10.2k
  int rv;
1162
1163
10.2k
  LOG_FUNC_CALLED(p15card->card->ctx);
1164
10.2k
  rv = oberthur_detect_card(p15card);
1165
10.2k
  if (!rv)
1166
873
    rv = sc_pkcs15emu_oberthur_init(p15card);
1167
1168
10.2k
  LOG_FUNC_RETURN(p15card->card->ctx, rv);
1169
10.2k
}
1170
1171
1172
static int
1173
sc_awp_parse_df(struct sc_pkcs15_card *p15card, struct sc_pkcs15_df *df)
1174
0
{
1175
0
  struct sc_context *ctx = p15card->card->ctx;
1176
0
  unsigned char *buf = NULL;
1177
0
  size_t buf_len;
1178
0
  int rv;
1179
1180
0
  LOG_FUNC_CALLED(ctx);
1181
0
  if (df->type != SC_PKCS15_PRKDF && df->type != SC_PKCS15_DODF)
1182
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
1183
1184
0
  if (df->enumerated)
1185
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1186
1187
0
  rv = sc_oberthur_read_file(p15card, AWP_OBJECTS_LIST_PRV, &buf, &buf_len, 1);
1188
0
  LOG_TEST_RET(ctx, rv, "Parse DF: read private objects info failed");
1189
1190
0
  rv = sc_oberthur_parse_privateinfo(p15card, buf, buf_len, 0);
1191
1192
0
  if (buf)
1193
0
    free(buf);
1194
1195
0
  if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)
1196
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1197
1198
0
  LOG_TEST_RET(ctx, rv, "Parse DF: private info parse error");
1199
0
  df->enumerated = 1;
1200
1201
0
  LOG_FUNC_RETURN(ctx, rv);
1202
0
}
1203
1204
1205
static void
1206
sc_awp_clear(struct sc_pkcs15_card *p15card)
1207
1.59k
{
1208
1.59k
  LOG_FUNC_CALLED(p15card->card->ctx);
1209
1.59k
}