Coverage Report

Created: 2026-06-10 06:48

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