Coverage Report

Created: 2026-06-06 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs15init/pkcs15-oberthur-awp.c
Line
Count
Source
1
/*
2
 * Oberthur AWP extension for PKCS #15 initialization
3
 *
4
 * Copyright (C) 2010  Viktor Tarasov <viktor.tarasov@opentrust.com>
5
 * Copyright (C) 2002  Juha Yrjola <juha.yrjola@iki.fi>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 *
21
 *  best view with tabstop=4
22
 *
23
 */
24
25
#include <stdlib.h>
26
#include <string.h>
27
#include <sys/types.h>
28
29
#include "config.h"
30
#include "pkcs15-oberthur.h"
31
32
#include "libopensc/opensc.h"
33
#include "libopensc/cardctl.h"
34
#include "libopensc/log.h"
35
#include "profile.h"
36
#include "pkcs15-init.h"
37
#include "libopensc/asn1.h"
38
39
#ifdef ENABLE_OPENSSL
40
#include "libopensc/sc-ossl-compat.h"
41
42
struct awp_lv zero_lv = { 0, NULL };
43
struct awp_lv x30_lv = { 0x10, (unsigned char *)"0000000000000000" };
44
45
static unsigned char *
46
awp_get_commonName(X509 *x)
47
0
{
48
0
  unsigned char *ret = NULL;
49
0
  int r;
50
51
0
    r = X509_NAME_get_index_by_NID(X509_get_subject_name(x),
52
0
       NID_commonName, -1);
53
0
  if (r >= 0)   {
54
0
    const X509_NAME_ENTRY *ne;
55
0
    const ASN1_STRING *a_str;
56
57
0
    if (!(ne = X509_NAME_get_entry(X509_get_subject_name(x), r)))
58
0
      ;
59
0
    else if (!(a_str = X509_NAME_ENTRY_get_data(ne)))
60
0
      ;
61
0
    else if (ASN1_STRING_type(a_str) == V_ASN1_UTF8STRING) {
62
0
      ret = malloc(ASN1_STRING_length(a_str) + 1);
63
0
      if (ret)   {
64
0
        memcpy(ret, ASN1_STRING_get0_data(a_str), ASN1_STRING_length(a_str));
65
66
0
        *(ret + ASN1_STRING_length(a_str)) = '\0';
67
0
      }
68
0
    } else {
69
0
      unsigned char *tmp = NULL;
70
71
0
      r = ASN1_STRING_to_UTF8(&tmp, a_str);
72
0
      if (r > 0)   {
73
0
        ret = malloc(r + 1);
74
0
        if (ret)   {
75
0
          memcpy(ret, tmp, r);
76
0
          *(ret + r) = '\0';
77
0
        }
78
79
0
        OPENSSL_free(tmp);
80
0
      }
81
0
    }
82
0
  }
83
84
0
  return ret;
85
0
}
86
87
88
static int
89
awp_new_file(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
90
    unsigned int type, unsigned int num,
91
    struct sc_file **info_out, struct sc_file **obj_out)
92
0
{
93
0
  struct sc_context *ctx = p15card->card->ctx;
94
0
  struct sc_file  *ifile=NULL, *ofile=NULL;
95
0
  char  name[NAME_MAX_LEN];
96
0
  const char *itag=NULL, *otag=NULL;
97
98
0
  LOG_FUNC_CALLED(ctx);
99
0
  sc_log(ctx,  "type 0x%X; num %i; info %p; obj %p", type, num, info_out, obj_out);
100
0
  switch (type) {
101
0
  case SC_PKCS15_TYPE_CERT_X509:
102
0
    itag = "certificate-info";
103
0
    otag = "template-certificate";
104
0
    break;
105
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
106
0
  case COSM_TYPE_PRKEY_RSA:
107
0
    itag = "private-key-info";
108
0
    otag = "template-private-key";
109
0
    break;
110
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
111
0
  case COSM_TYPE_PUBKEY_RSA:
112
0
    itag = "public-key-info";
113
0
    otag = "template-public-key";
114
0
    break;
115
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
116
0
    itag = "data-info";
117
0
    otag = "template-data";
118
0
    break;
119
0
  case COSM_TYPE_PRIVDATA_OBJECT:
120
0
    itag = "privdata-info";
121
0
    otag = "template-privdata";
122
0
    break;
123
0
  case SC_PKCS15_TYPE_AUTH_PIN:
124
0
  case COSM_TOKENINFO :
125
0
    itag = "token-info";
126
0
    num = 0;
127
0
    break;
128
0
  case COSM_PUBLIC_LIST:
129
0
    itag = "public-list";
130
0
    num = 0;
131
0
    break;
132
0
  case COSM_PRIVATE_LIST:
133
0
    itag = "private-list";
134
0
    num = 0;
135
0
    break;
136
0
  case COSM_CONTAINER_LIST:
137
0
        itag = "container-list";
138
0
        num = 0;
139
0
        break;
140
0
  default:
141
0
    return SC_ERROR_INVALID_ARGUMENTS;
142
0
  }
143
144
0
  if (itag)  {
145
0
    snprintf(name, sizeof(name),"%s-%s", COSM_TITLE, itag);
146
0
    sc_log(ctx,  "info template %s",name);
147
0
    if (sc_profile_get_file(profile, name, &ifile) < 0) {
148
0
      sc_log(ctx,  "profile does not defines template '%s'", name);
149
0
      return SC_ERROR_INCONSISTENT_PROFILE;
150
0
    }
151
0
  }
152
153
0
  if (otag)   {
154
0
    sc_log(ctx,  "obj template %s",otag);
155
0
    if (sc_profile_get_file(profile, otag, &ofile) < 0) {
156
0
      sc_file_free(ifile);
157
0
      sc_log(ctx,  "profile does not defines template '%s'", name);
158
0
      return SC_ERROR_INCONSISTENT_PROFILE;
159
0
    }
160
161
0
    ofile->id |= (num & 0xFF);
162
0
    ofile->path.value[ofile->path.len-1] |= (num & 0xFF);
163
0
  }
164
165
0
  if (ifile)    {
166
0
    if(info_out)    {
167
0
      if (ofile)   {
168
0
        ifile->id = ofile->id | 0x100;
169
170
0
        ifile->path = ofile->path;
171
0
        ifile->path.value[ifile->path.len-2] |= 0x01;
172
0
      }
173
174
0
      sc_log(ctx,
175
0
         "info_file(id:%04X,size:%"SC_FORMAT_LEN_SIZE_T"u,rlen:%"SC_FORMAT_LEN_SIZE_T"u)",
176
0
         ifile->id, ifile->size, ifile->record_length);
177
0
      *info_out = ifile;
178
0
    }
179
0
    else   {
180
0
      sc_file_free(ifile);
181
0
    }
182
0
  }
183
184
0
  if (ofile)   {
185
0
    sc_log(ctx,
186
0
       "obj file %04X; size %"SC_FORMAT_LEN_SIZE_T"u; ",
187
0
       ofile->id, ofile->size);
188
0
    if (obj_out)
189
0
      *obj_out = ofile;
190
0
    else
191
0
      sc_file_free(ofile);
192
0
  }
193
194
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
195
0
}
196
197
198
static int
199
awp_update_blob(struct sc_context *ctx,
200
    unsigned char **blob, int *blob_size,
201
    struct awp_lv *lv, int type)
202
0
{
203
0
  unsigned char *pp;
204
205
0
  LOG_FUNC_CALLED(ctx);
206
0
  switch (type)  {
207
0
  case TLV_TYPE_LLV :
208
0
    if (!(pp = realloc(*blob, *blob_size + 2 + lv->len)))
209
0
      return SC_ERROR_OUT_OF_MEMORY;
210
0
    *(pp + *blob_size) = (lv->len >> 8) & 0xFF;
211
0
    *(pp + *blob_size + 1) = lv->len & 0xFF;
212
0
    memcpy(pp + *blob_size + 2, lv->value, (lv->len & 0xFF));
213
0
    *blob_size += 2 + lv->len;
214
0
    break;
215
0
  case TLV_TYPE_LV :
216
0
    if (!(pp = realloc(*blob, *blob_size + 1 + lv->len)))
217
0
      return SC_ERROR_OUT_OF_MEMORY;
218
0
    *(pp + *blob_size) = lv->len & 0xFF;
219
0
    memcpy(pp + *blob_size + 1, lv->value, (lv->len & 0xFF));
220
0
    *blob_size += 1 + lv->len;
221
0
    break;
222
0
  case TLV_TYPE_V :
223
0
    if (0 == *blob_size + lv->len)
224
0
      return SC_ERROR_INVALID_DATA;
225
0
    if (!(pp = realloc(*blob, *blob_size + lv->len)))
226
0
      return SC_ERROR_OUT_OF_MEMORY;
227
0
    memcpy(pp + *blob_size, lv->value, lv->len);
228
0
    *blob_size += lv->len;
229
0
    break;
230
0
  default:
231
0
    sc_log(ctx,  "Invalid tlv type %i",type);
232
0
    return SC_ERROR_INCORRECT_PARAMETERS;
233
0
  }
234
235
0
  *blob = pp;
236
237
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
238
0
}
239
240
241
static int
242
awp_new_container_entry(struct sc_pkcs15_card *p15card, unsigned char *buff, size_t len)
243
0
{
244
0
  struct sc_context *ctx = p15card->card->ctx;
245
0
  int mm, rv = 0;
246
0
  unsigned ii, marks[5] = {4,6,8,10,0};
247
0
  unsigned char rand_buf[0x10];
248
249
0
  LOG_FUNC_CALLED(ctx);
250
0
  if (len<0x34)
251
0
    LOG_TEST_RET(ctx, SC_ERROR_INCORRECT_PARAMETERS, "Invalid container update size");
252
253
0
  rv = sc_get_challenge(p15card->card, rand_buf, sizeof(rand_buf));
254
0
  LOG_TEST_RET(ctx, rv, "Cannot get challenge");
255
256
0
  *(buff + 12) = 0x26;
257
0
  *(buff + 13) = '{';
258
0
  for (ii=0, mm = 0; ii<sizeof(rand_buf); ii++)   {
259
0
    if (ii==marks[mm])   {
260
0
      *(buff + 14 + ii*2 + mm) = '-';
261
0
      mm++;
262
0
    }
263
0
    sprintf((char *)(buff + 14 + ii*2 + mm),"%02X", rand_buf[ii]);
264
0
  }
265
0
  *(buff + 14 + ii*2 + mm) = (unsigned char)'}';
266
267
0
  LOG_FUNC_RETURN(ctx, rv);
268
0
}
269
270
271
static int
272
awp_create_container_record (struct sc_pkcs15_card *p15card, struct sc_profile *profile,
273
    struct sc_file *list_file,  struct awp_crypto_container *acc)
274
0
{
275
0
  struct sc_context *ctx = p15card->card->ctx;
276
0
  int rv;
277
0
  unsigned char *buff = NULL;
278
279
0
  LOG_FUNC_CALLED(ctx);
280
0
  sc_log(ctx,  "container file(file-id:%X,rlen:%"SC_FORMAT_LEN_SIZE_T"u,rcount:%"SC_FORMAT_LEN_SIZE_T"u)",
281
0
      list_file->id, list_file->record_length, list_file->record_count);
282
283
0
  buff = malloc(list_file->record_length);
284
0
  if (!buff)
285
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
286
287
0
  memset(buff, 0, list_file->record_length);
288
289
0
  rv = awp_new_container_entry(p15card, buff, list_file->record_length);
290
0
  if (rv < 0) {
291
0
    free(buff);
292
0
    sc_log(ctx, "Cannot create container");
293
0
    LOG_FUNC_RETURN(ctx, rv);
294
0
  }
295
296
0
  *(buff + 0) = (acc->pubkey_id >> 8) & 0xFF;
297
0
  *(buff + 1) = acc->pubkey_id & 0xFF;
298
0
  *(buff + 2) = (acc->prkey_id >> 8) & 0xFF;
299
0
  *(buff + 3) = acc->prkey_id & 0xFF;
300
0
  *(buff + 4) = (acc->cert_id >> 8) & 0xFF;
301
0
  *(buff + 5) = acc->cert_id & 0xFF;
302
303
0
  rv = sc_select_file(p15card->card, &list_file->path, NULL);
304
0
  if (rv == SC_ERROR_FILE_NOT_FOUND)
305
0
    rv = sc_pkcs15init_create_file(profile, p15card, list_file);
306
307
0
  if (!rv)
308
0
    rv = sc_append_record(p15card->card, buff, list_file->record_length, SC_RECORD_BY_REC_NR);
309
310
0
  free(buff);
311
0
  LOG_FUNC_RETURN(ctx, rv);
312
0
}
313
314
315
static int
316
awp_create_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, int type,
317
    struct awp_lv *key_id, struct awp_crypto_container *acc)
318
0
{
319
0
  struct sc_context *ctx = p15card->card->ctx;
320
0
  struct sc_file *clist = NULL, *file = NULL;
321
0
  int rv = 0;
322
323
0
  LOG_FUNC_CALLED(ctx);
324
0
  sc_log(ctx,  "create container(%X:%X:%X)", acc->prkey_id, acc->cert_id, acc->pubkey_id);
325
326
0
  rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL);
327
0
  LOG_TEST_RET(ctx, rv, "Create container failed");
328
0
  sc_log(ctx,  "container cfile(rcount:%"SC_FORMAT_LEN_SIZE_T"u,rlength:%"SC_FORMAT_LEN_SIZE_T"u)", clist->record_count, clist->record_length);
329
330
0
  rv = sc_select_file(p15card->card, &clist->path, &file);
331
0
  LOG_TEST_RET(ctx, rv, "Create container failed: cannot select container's list");
332
0
  file->record_length = clist->record_length;
333
334
0
  sc_log(ctx,  "container file(rcount:%"SC_FORMAT_LEN_SIZE_T"u,rlength:%"SC_FORMAT_LEN_SIZE_T"u)", file->record_count, file->record_length);
335
0
  sc_log(ctx,  "Append new record %"SC_FORMAT_LEN_SIZE_T"u for private key", file->record_count + 1);
336
337
0
  rv = awp_create_container_record(p15card, profile, file, acc);
338
339
0
  sc_file_free(file);
340
0
  sc_file_free(clist);
341
342
0
  LOG_FUNC_RETURN(ctx, rv);
343
0
}
344
345
346
static int
347
awp_update_container_entry (struct sc_pkcs15_card *p15card, struct sc_profile *profile,
348
    struct sc_file *list_file,  int type, int file_id,
349
    size_t rec, int offs)
350
0
{
351
0
  struct sc_context *ctx = p15card->card->ctx;
352
0
  int rv;
353
0
  unsigned char *buff = NULL;
354
355
0
  LOG_FUNC_CALLED(ctx);
356
0
  sc_log(ctx,
357
0
     "update container entry(type:%X,id %i,rec %"SC_FORMAT_LEN_SIZE_T"u,offs %i",
358
0
     type, file_id, rec, offs);
359
0
  sc_log(ctx,  "container file(file-id:%X,rlen:%"SC_FORMAT_LEN_SIZE_T"u,rcount:%"SC_FORMAT_LEN_SIZE_T"u)",
360
0
      list_file->id, list_file->record_length, list_file->record_count);
361
362
0
  buff = malloc(list_file->record_length);
363
0
  if (!buff)
364
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
365
366
0
  memset(buff, 0, list_file->record_length);
367
368
0
  if (rec > list_file->record_count)   {
369
0
    rv = awp_new_container_entry(p15card, buff, list_file->record_length);
370
0
  }
371
0
  else   {
372
0
    rv = sc_select_file(p15card->card, &list_file->path, NULL);
373
0
    if (!rv)
374
0
      rv = sc_read_record(p15card->card, (unsigned int)rec, 0, buff, list_file->record_length, SC_RECORD_BY_REC_NR);
375
0
  }
376
0
  if (rv < 0)   {
377
0
    free(buff);
378
0
    LOG_FUNC_RETURN(ctx, rv);
379
0
  }
380
381
0
  switch (type)  {
382
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
383
0
  case COSM_TYPE_PUBKEY_RSA:
384
0
    if (*(buff + offs + 4))
385
0
      sc_log(ctx,  "Insert public key to container that contains certificate %02X%02X",
386
0
          *(buff + offs + 4), *(buff + offs + 5));
387
0
    *(buff + offs + 0) = (file_id >> 8) & 0xFF;
388
0
    *(buff + offs + 1) = file_id & 0xFF;
389
0
    break;
390
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
391
0
  case COSM_TYPE_PRKEY_RSA:
392
0
    if (*(buff + offs + 2)) {
393
0
      free(buff);
394
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_CARD, "private key exists already");
395
0
    }
396
397
0
    *(buff + offs + 2) = (file_id >> 8) & 0xFF;
398
0
    *(buff + offs + 3) = file_id & 0xFF;
399
0
    break;
400
0
  case SC_PKCS15_TYPE_CERT_X509 :
401
0
    *(buff + offs + 4) = (file_id >> 8) & 0xFF;
402
0
    *(buff + offs + 5) = file_id & 0xFF;
403
0
    break;
404
0
  default:
405
0
    free(buff);
406
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INCORRECT_PARAMETERS);
407
0
  }
408
409
0
  if (rec > list_file->record_count)   {
410
0
    rv = sc_select_file(p15card->card, &list_file->path, NULL);
411
0
    if (rv == SC_ERROR_FILE_NOT_FOUND)
412
0
      rv = sc_pkcs15init_create_file(profile, p15card, list_file);
413
414
0
    if (!rv)
415
0
      rv = sc_append_record(p15card->card, buff, list_file->record_length, SC_RECORD_BY_REC_NR);
416
0
  }
417
0
  else   {
418
0
    rv = sc_update_record(p15card->card, (unsigned int)rec, 0, buff, list_file->record_length, SC_RECORD_BY_REC_NR);
419
0
  }
420
421
0
  free(buff);
422
0
  LOG_FUNC_RETURN(ctx, rv);
423
0
}
424
425
426
static int
427
awp_update_container(struct sc_pkcs15_card *p15card, struct sc_profile *profile, int type,
428
    struct awp_lv *key_id, unsigned obj_id, unsigned int *prkey_id)
429
0
{
430
0
  struct sc_context *ctx = p15card->card->ctx;
431
0
  struct sc_file *clist = NULL, *file = NULL;
432
0
  struct sc_path  private_path;
433
0
  int rv = 0;
434
0
  size_t rec;
435
0
  int rec_offs;
436
0
  unsigned char *list = NULL;
437
438
0
  LOG_FUNC_CALLED(ctx);
439
0
  sc_log(ctx,  "update container(type:%X,obj_id:%X)", type, obj_id);
440
441
0
  if (prkey_id)
442
0
    *prkey_id = 0;
443
444
  /*
445
   * Get path of the DF that contains private objects.
446
   */
447
0
  rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_PRKEY_RSA, 1, NULL, &file);
448
0
  if (rv)
449
0
    goto done;
450
0
  private_path = file->path;
451
0
  sc_file_free(file), file=NULL;
452
453
0
  rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL);
454
0
  if (rv)
455
0
    goto done;
456
457
0
  rv = sc_select_file(p15card->card, &clist->path, &file);
458
0
  if (rv)
459
0
    goto done;
460
0
  file->record_length = clist->record_length;
461
462
0
  if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA)   {
463
0
    rec_offs = 0;
464
0
    rv = awp_update_container_entry(p15card, profile, file, type, obj_id, file->record_count + 1, rec_offs);
465
0
    goto done;
466
0
  }
467
468
0
  list = malloc(AWP_CONTAINER_RECORD_LEN * file->record_count);
469
0
  if (!list)  {
470
0
    rv = SC_ERROR_OUT_OF_MEMORY;
471
0
    goto done;
472
0
  }
473
474
0
  rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_READ);
475
0
  if (rv)
476
0
    goto done;
477
478
0
  for (rec=0; rec < file->record_count; rec++)   {
479
0
    unsigned char tmp[256];
480
481
0
    rv = sc_read_record(p15card->card, (unsigned int)rec + 1, 0, tmp, sizeof(tmp), SC_RECORD_BY_REC_NR);
482
0
    if (rv >= AWP_CONTAINER_RECORD_LEN)
483
0
      memcpy(list + rec*AWP_CONTAINER_RECORD_LEN, tmp, AWP_CONTAINER_RECORD_LEN);
484
0
    else
485
0
      goto done;
486
0
  }
487
488
0
  for (rec=0, rv=0; !rv && rec < file->record_count; rec++)   {
489
0
    for (rec_offs=0; !rv && rec_offs<12; rec_offs+=6)   {
490
0
      int offs;
491
492
0
      sc_log(ctx,  "rec %zu; rec_offs %d", rec, rec_offs);
493
0
      offs = (int)rec*AWP_CONTAINER_RECORD_LEN + rec_offs;
494
0
      if (*(list + offs + 2))   {
495
0
        unsigned char *buff = NULL;
496
0
        int id_offs;
497
0
        struct sc_path path = private_path;
498
0
        struct sc_file *ff = NULL;
499
500
0
        path.value[path.len - 2] = *(list + offs + 2) | 0x01;
501
0
        path.value[path.len - 1] = *(list + offs + 3);
502
0
        rv = sc_select_file(p15card->card, &path, &ff);
503
0
        if (rv)
504
0
          continue;
505
506
0
        rv = sc_pkcs15init_authenticate(profile, p15card, ff, SC_AC_OP_READ);
507
0
        if (rv)   {
508
0
          sc_file_free(ff);
509
0
          break;
510
0
        }
511
512
0
        buff = malloc(ff->size);
513
0
        if (!buff)
514
0
          rv = SC_ERROR_OUT_OF_MEMORY;
515
516
0
        if (!rv)   {
517
0
          rv = sc_read_binary(p15card->card, 0, buff, ff->size, 0);
518
0
          if ((unsigned)rv == ff->size)  {
519
0
            rv = 0;
520
0
            id_offs = 5 + *(buff+3);
521
522
0
            if (key_id->len == *(buff + id_offs) &&
523
0
                !memcmp(key_id->value, buff + id_offs + 1, key_id->len))  {
524
0
              sc_log(ctx,  "found key file friend");
525
0
              if (!rv)
526
0
                rv = awp_update_container_entry(p15card, profile, file, type, obj_id, rec + 1, rec_offs);
527
528
0
              if (rv >= 0 && prkey_id)
529
0
                *prkey_id = *(list + offs + 2) * 0x100 + *(list + offs + 3);
530
0
            }
531
0
          }
532
0
        }
533
534
0
        free(buff);
535
0
        sc_file_free(ff);
536
537
0
        if (rv)
538
0
          break;
539
0
      }
540
0
    }
541
0
  }
542
543
0
done:
544
0
  sc_file_free(clist);
545
0
  sc_file_free(file);
546
0
  if (list)  free(list);
547
548
0
  LOG_FUNC_RETURN(ctx, rv);
549
0
}
550
551
552
static int
553
awp_update_df_create_pin(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
554
    struct sc_pkcs15_object *pinobj)
555
0
{
556
0
  SC_FUNC_CALLED(p15card->card->ctx, 1);
557
  /* No update DF when creating PIN objects */
558
0
  SC_FUNC_RETURN(p15card->card->ctx, 1, SC_SUCCESS);
559
0
}
560
561
562
static int
563
awp_set_certificate_info (struct sc_pkcs15_card *p15card,
564
    struct sc_profile *profile,
565
    struct sc_file *file,
566
    struct awp_cert_info *ci)
567
0
{
568
0
  struct sc_context *ctx = p15card->card->ctx;
569
0
  int r = 0, blob_size;
570
0
  unsigned char *blob;
571
0
  const char *default_cert_label = "Certificate";
572
573
0
  LOG_FUNC_CALLED(ctx);
574
0
  blob_size = 2;
575
0
  if (!(blob = malloc(blob_size)))   {
576
0
    r = SC_ERROR_OUT_OF_MEMORY;
577
0
    goto done;
578
0
  }
579
580
  /* TODO: cert flags */
581
0
  *blob       = (COSM_TAG_CERT >> 8) & 0xFF;
582
0
  *(blob + 1) = COSM_TAG_CERT & 0xFF;
583
584
0
  if (ci->label.len && ci->label.len != strlen(default_cert_label)
585
0
      && memcmp(ci->label.value, default_cert_label, strlen(default_cert_label)))
586
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV);
587
0
  else
588
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV);
589
0
  if (r)
590
0
    goto done;
591
592
0
  r = awp_update_blob(ctx, &blob, &blob_size, &ci->id, TLV_TYPE_LLV);
593
0
  if (r)
594
0
    goto done;
595
596
0
  r = awp_update_blob(ctx, &blob, &blob_size, &ci->subject, TLV_TYPE_LLV);
597
0
  if (r)
598
0
    goto done;
599
600
0
  if (ci->issuer.len != ci->subject.len ||
601
0
      memcmp(ci->issuer.value, ci->subject.value, ci->subject.len))   {
602
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->issuer, TLV_TYPE_LLV);
603
0
    if (r)
604
0
      goto done;
605
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->serial, TLV_TYPE_LLV);
606
0
    if (r)
607
0
      goto done;
608
0
  }
609
0
  else   {
610
0
    r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV);
611
0
    if (r)
612
0
      goto done;
613
0
    r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV);
614
0
    if (r)
615
0
      goto done;
616
0
  }
617
618
0
  file->size = blob_size;
619
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
620
0
  if (r)
621
0
    goto done;
622
623
0
  r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size);
624
0
  if (r < 0)
625
0
    goto done;
626
627
0
  r = 0;
628
0
done:
629
0
  if (blob)
630
0
    free(blob);
631
632
0
  LOG_FUNC_RETURN(ctx, r);
633
0
}
634
635
636
static int
637
awp_update_object_list(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
638
    unsigned int type, int num)
639
0
{
640
0
  struct sc_context *ctx = p15card->card->ctx;
641
0
  struct sc_file *obj_file = NULL, *lst_file = NULL;
642
0
  struct sc_file *file = NULL;
643
0
  char obj_name[NAME_MAX_LEN], lst_name[NAME_MAX_LEN];
644
0
  unsigned char *buff = NULL;
645
0
  int rv;
646
0
  unsigned ii;
647
0
  unsigned long flags;
648
649
0
  LOG_FUNC_CALLED(ctx);
650
0
  sc_log(ctx,  "type %i, num %i", type, num);
651
0
  switch (type)   {
652
0
  case SC_PKCS15_TYPE_CERT_X509:
653
0
    snprintf(obj_name, NAME_MAX_LEN, "template-certificate");
654
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE);
655
0
    break;
656
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
657
0
  case COSM_TYPE_PUBKEY_RSA:
658
0
    snprintf(obj_name, NAME_MAX_LEN, "template-public-key");
659
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE);
660
0
    break;
661
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
662
0
    snprintf(obj_name, NAME_MAX_LEN, "template-data");
663
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE);
664
0
    break;
665
0
  case COSM_TYPE_PRIVDATA_OBJECT:
666
0
    snprintf(obj_name, NAME_MAX_LEN, "template-privdata");
667
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE);
668
0
    break;
669
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
670
0
  case COSM_TYPE_PRKEY_RSA:
671
0
    snprintf(obj_name, NAME_MAX_LEN,"template-private-key");
672
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE);
673
0
    break;
674
0
  default:
675
0
        sc_log(ctx,  "Not supported file type %X", type);
676
0
        return SC_ERROR_INVALID_ARGUMENTS;
677
0
  }
678
679
0
  sc_log(ctx,  "obj_name %s; num 0x%X",obj_name, num);
680
0
  sc_log(ctx,  "lst_name %s",lst_name);
681
0
  if (sc_profile_get_file(profile, obj_name, &obj_file) < 0) {
682
0
    sc_log(ctx,  "No profile template '%s'", obj_name);
683
0
    rv = SC_ERROR_NOT_SUPPORTED;
684
0
    goto done;
685
0
  }
686
0
  else if (sc_profile_get_file(profile, lst_name, &lst_file) < 0)  {
687
0
    sc_log(ctx,  "No profile template '%s'", lst_name);
688
0
    rv = SC_ERROR_NOT_SUPPORTED;
689
0
    goto done;
690
0
  }
691
692
0
  obj_file->id |= (num & 0xFF);
693
0
  obj_file->path.value[obj_file->path.len-1] |= (num & 0xFF);
694
695
0
  rv = sc_select_file(p15card->card, &obj_file->path, &file);
696
0
  if (rv)
697
0
    goto done;
698
699
0
  if (type == SC_PKCS15_TYPE_PUBKEY_RSA || type == COSM_TYPE_PUBKEY_RSA)   {
700
0
    if (file->size==PUBKEY_512_ASN1_SIZE)
701
0
      file->size = 512;
702
0
    else if (file->size==PUBKEY_1024_ASN1_SIZE)
703
0
      file->size = 1024;
704
0
    else if (file->size==PUBKEY_2048_ASN1_SIZE)
705
0
      file->size = 2048;
706
0
  }
707
708
0
  buff = malloc(lst_file->size);
709
0
  if (!buff)   {
710
0
    rv = SC_ERROR_OUT_OF_MEMORY;
711
0
    goto done;
712
0
  }
713
714
0
  rv = sc_pkcs15init_authenticate(profile, p15card, lst_file, SC_AC_OP_READ);
715
0
  if (rv)
716
0
    goto done;
717
0
  rv = sc_pkcs15init_authenticate(profile, p15card, lst_file, SC_AC_OP_UPDATE);
718
0
  if (rv)
719
0
    goto done;
720
721
0
  rv = sc_select_file(p15card->card, &lst_file->path, NULL);
722
0
  if (rv == SC_ERROR_FILE_NOT_FOUND)
723
0
    rv = sc_pkcs15init_create_file(profile, p15card, lst_file);
724
0
  if (rv < 0)
725
0
    goto done;
726
727
0
  if (lst_file->size < 5) {
728
0
    rv = SC_ERROR_UNKNOWN_DATA_RECEIVED;
729
0
    goto done;
730
0
  }
731
732
0
  flags = lst_file->ef_structure;
733
0
  rv = sc_read_binary(p15card->card, 0, buff, lst_file->size, &flags);
734
0
  if (rv < 0)
735
0
    goto done;
736
737
0
  for (ii=0; ii <= lst_file->size-5; ii+=5)
738
0
    if (*(buff + ii) != COSM_LIST_TAG)
739
0
      break;
740
0
  if (ii>=lst_file->size)   {
741
0
    rv = SC_ERROR_UNKNOWN_DATA_RECEIVED;
742
0
    goto done;
743
0
  }
744
745
0
  sc_log(ctx,
746
0
     "ii %i, rv %i; %X; %"SC_FORMAT_LEN_SIZE_T"u",
747
0
     ii, rv, file->id, file->size);
748
0
  *(buff + ii) = COSM_LIST_TAG;
749
0
  *(buff + ii + 1) = (file->id >> 8) & 0xFF;
750
0
  *(buff + ii + 2) = file->id & 0xFF;
751
0
  *(buff + ii + 3) = (file->size >> 8) & 0xFF;
752
0
  *(buff + ii + 4) = file->size & 0xFF;
753
754
0
  rv = sc_update_binary(p15card->card, ii, buff + ii, 5, 0);
755
0
  sc_log(ctx,  "rv %i",rv);
756
0
  if (rv < 0)
757
0
    goto done;
758
759
0
  rv = 0;
760
0
done:
761
0
  if (buff)
762
0
    free(buff);
763
0
  sc_file_free(lst_file);
764
0
  sc_file_free(obj_file);
765
0
  sc_file_free(file);
766
767
0
  LOG_FUNC_RETURN(ctx, rv);
768
0
}
769
770
771
static int
772
awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
773
    struct sc_pkcs15_pubkey_rsa *pubkey, struct awp_key_info *ki)
774
0
{
775
0
  struct sc_context *ctx = p15card->card->ctx;
776
0
  struct sc_pkcs15_prkey_info *key_info;
777
0
  int r = 0;
778
779
0
  LOG_FUNC_CALLED(ctx);
780
781
0
  key_info = (struct sc_pkcs15_prkey_info *)obj->data;
782
783
0
  sc_log(ctx,  "object(%s,type:%X)", obj->label, obj->type);
784
0
  if (obj->type == SC_PKCS15_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PUBKEY_RSA )
785
0
    ki->flags = COSM_TAG_PUBKEY_RSA;
786
0
  else if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA)
787
0
    ki->flags = COSM_TAG_PRVKEY_RSA;
788
0
  else
789
0
    return SC_ERROR_INCORRECT_PARAMETERS;
790
791
0
  if (obj->type == COSM_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA)
792
0
    ki->flags |= COSM_GENERATED;
793
794
0
  ki->label.value = (unsigned char *)strdup(obj->label);
795
0
  ki->label.len = strlen(obj->label);
796
0
  sc_log(ctx,
797
0
     "cosm_encode_key_info() label(%zu):%s",
798
0
     ki->label.len, ki->label.value);
799
800
  /*
801
   * Oberthur saves modulus value without tag and length.
802
   */
803
0
  sc_log(ctx,
804
0
     "pubkey->modulus.len %"SC_FORMAT_LEN_SIZE_T"u",
805
0
     pubkey->modulus.len);
806
0
  ki->modulus.value = malloc(pubkey->modulus.len);
807
0
  if (!ki->modulus.value)   {
808
0
    r = SC_ERROR_OUT_OF_MEMORY;
809
0
    goto done;
810
0
  }
811
0
  memcpy(ki->modulus.value, pubkey->modulus.data, pubkey->modulus.len);
812
0
  ki->modulus.len = pubkey->modulus.len;
813
814
  /*
815
   * Oberthur saves exponents as length and value, without tag.
816
   */
817
0
  ki->exponent.value = malloc(pubkey->exponent.len);
818
0
  if (!ki->exponent.value)   {
819
0
    r = SC_ERROR_OUT_OF_MEMORY;
820
0
    goto done;
821
0
  }
822
0
  memcpy(ki->exponent.value, pubkey->exponent.data, pubkey->exponent.len);
823
0
  ki->exponent.len = pubkey->exponent.len;
824
825
  /*
826
   * ID
827
   */
828
0
  ki->id.value = calloc(1, key_info->id.len);
829
0
  if (!ki->id.value)
830
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: ID allocation error");
831
0
  memcpy(ki->id.value, key_info->id.value, key_info->id.len);
832
0
  ki->id.len = key_info->id.len;
833
834
0
  sc_log(ctx,  "cosm_encode_key_info() label:%s",ki->label.value);
835
0
done:
836
0
  LOG_FUNC_RETURN(ctx, r);
837
0
}
838
839
840
static void
841
awp_free_key_info(struct awp_key_info *ki)
842
0
{
843
0
  free(ki->modulus.value);
844
0
  free(ki->exponent.value);
845
0
  free(ki->id.value);
846
0
}
847
848
849
static int
850
awp_set_key_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_file *file,
851
    struct awp_key_info *ki, struct awp_cert_info *ci)
852
0
{
853
0
  struct sc_context *ctx = p15card->card->ctx;
854
0
  int r = 0, blob_size;
855
0
  unsigned char *blob;
856
857
0
  LOG_FUNC_CALLED(ctx);
858
0
  sc_log(ctx,  "file:%p, kinfo:%p, cinfo:%p", file, ki, ci);
859
0
  blob_size = 2;
860
0
  blob = malloc(blob_size);
861
0
  if (!blob)
862
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP set key info failed: blob allocation error");
863
864
0
  sc_log(ctx,  "label:%s",ki->label.value);
865
866
0
  *blob = (ki->flags >> 8) & 0xFF;
867
0
  *(blob + 1) = ki->flags & 0xFF;
868
0
  if (ci && ci->label.len)
869
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV);
870
0
  else if (ci && !ci->label.len)
871
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV);
872
0
  else
873
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->label, TLV_TYPE_LLV);
874
0
  if (r)
875
0
    goto done;
876
877
0
  r = awp_update_blob(ctx, &blob, &blob_size, &ki->id, TLV_TYPE_LLV);
878
0
  if (r)
879
0
    goto done;
880
881
0
  r = awp_update_blob(ctx, &blob, &blob_size, &x30_lv, TLV_TYPE_V);
882
0
  if (r)
883
0
    goto done;
884
885
0
  if (ci)
886
0
    r = awp_update_blob(ctx, &blob, &blob_size, &(ci->subject), TLV_TYPE_LLV);
887
0
  else
888
0
    r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV);
889
0
  if (r)
890
0
    goto done;
891
892
0
  if ((ki->flags & ~COSM_GENERATED) != COSM_TAG_PUBKEY_RSA)   {
893
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->modulus, TLV_TYPE_V);
894
0
    if (r)
895
0
      goto done;
896
897
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->exponent, TLV_TYPE_LV);
898
0
    if (r)
899
0
      goto done;
900
0
  }
901
902
0
  file->size = blob_size;
903
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
904
0
  if (r == SC_ERROR_FILE_ALREADY_EXISTS)   {
905
0
    r =  cosm_delete_file(p15card, profile, file);
906
0
    if (!r)
907
0
      r = sc_pkcs15init_create_file(profile, p15card, file);
908
0
  }
909
910
0
  if (r<0)
911
0
    goto done;
912
913
0
  r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size);
914
0
  if (r < 0)
915
0
    goto done;
916
917
0
  r = 0;
918
0
done:
919
0
  if (blob)
920
0
    free(blob);
921
922
0
  LOG_FUNC_RETURN(ctx, r);
923
0
}
924
925
926
static int
927
awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
928
    struct awp_cert_info *ci)
929
0
{
930
0
  struct sc_context *ctx = p15card->card->ctx;
931
0
  struct sc_pkcs15_cert_info *cert_info;
932
0
  struct sc_pkcs15_pubkey_rsa pubkey;
933
0
  int r = 0;
934
0
  unsigned char *buff = NULL, *ptr;
935
0
  BIO *mem = NULL;
936
0
  X509 *x = NULL;
937
938
0
  LOG_FUNC_CALLED(ctx);
939
940
0
  if (!obj || !ci)
941
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode cert failed: invalid parameters");
942
943
0
  cert_info = (struct sc_pkcs15_cert_info *)obj->data;
944
945
0
  sc_log(ctx,
946
0
     "Encode cert(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))",
947
0
     obj->label, sc_pkcs15_print_id(&cert_info->id),
948
0
     obj->content.value, obj->content.len);
949
0
  memset(&pubkey, 0, sizeof(pubkey));
950
951
0
  ci->label.value = (unsigned char *)strdup(obj->label);
952
0
  ci->label.len = strlen(obj->label);
953
954
0
  mem = BIO_new_mem_buf(obj->content.value, (int)obj->content.len);
955
0
  if (!mem) {
956
0
    sc_log_openssl(ctx);
957
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: invalid data");
958
0
  }
959
960
0
  x = d2i_X509_bio(mem, NULL);
961
0
  if (!x) {
962
0
    sc_log_openssl(ctx);
963
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: x509 parse error");
964
0
  }
965
966
0
  buff = OPENSSL_malloc(i2d_X509(x,NULL) + EVP_MAX_MD_SIZE);
967
0
  if (!buff)
968
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: memory allocation error");
969
970
  /*
971
   * subject commonName.
972
   */
973
0
  ptr = awp_get_commonName(x);
974
0
  if (!ptr) {
975
0
    r = SC_ERROR_INTERNAL;
976
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get CommonName");
977
0
  }
978
0
  ci->cn.value = ptr;
979
0
  ci->cn.len = strlen((char *)ptr);
980
981
  /*
982
   * subject DN
983
   */
984
0
  ptr = buff;
985
0
  r = i2d_X509_NAME(X509_get_subject_name(x),&ptr);
986
0
  if (r<=0) {
987
0
    sc_log_openssl(ctx);
988
0
    r = SC_ERROR_INTERNAL;
989
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get SubjectName");
990
0
  }
991
992
0
  ci->subject.value = malloc(r);
993
0
  if (!ci->subject.value) {
994
0
    r = SC_ERROR_OUT_OF_MEMORY;
995
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: subject allocation error");
996
0
  }
997
0
  memcpy(ci->subject.value, buff, r);
998
0
  ci->subject.len = r;
999
1000
  /*
1001
   * issuer DN
1002
   */
1003
0
  ptr = buff;
1004
0
  r = i2d_X509_NAME(X509_get_issuer_name(x),&ptr);
1005
0
  if (r <= 0) {
1006
0
    sc_log_openssl(ctx);
1007
0
    r = SC_ERROR_INTERNAL;
1008
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get IssuerName");
1009
0
  }
1010
1011
0
  ci->issuer.value = malloc(r);
1012
0
  if (!ci->issuer.value) {
1013
0
    r = SC_ERROR_OUT_OF_MEMORY;
1014
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: issuer allocation error");
1015
0
  }
1016
0
  memcpy(ci->issuer.value, buff, r);
1017
0
  ci->issuer.len = r;
1018
1019
  /*
1020
   * ID
1021
   */
1022
0
  ci->id.value = calloc(1, cert_info->id.len);
1023
0
  if (!ci->id.value) {
1024
0
    r = SC_ERROR_OUT_OF_MEMORY;
1025
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: ID allocation error");
1026
0
  }
1027
0
  memcpy(ci->id.value, cert_info->id.value, cert_info->id.len);
1028
0
  ci->id.len = cert_info->id.len;
1029
1030
  /*
1031
   * serial number
1032
   */
1033
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
1034
1035
  /* TODO the der encoding of a ANS1_INTEGER is a TLV, the original code only as using the
1036
   * i2c_ASN1_INTEGER which is not in OpenSSL 1.1
1037
   * It was adding the tag V_ASN1_INTEGER and the one byte length back in in effect creating
1038
   * a DER encoded ASN1_INTEGER
1039
   * So we can simplify the code and make compatible with OpenSSL 1.1. This needs to be tested
1040
   */
1041
0
  ci->serial.len = 0;
1042
0
  ci->serial.value = NULL;
1043
  /* get length */
1044
0
  ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), NULL);
1045
0
  if (ci->serial.len > 0) {
1046
0
    if (!(ci->serial.value = malloc(ci->serial.len)))   {
1047
0
      ci->serial.len = 0;
1048
0
      r = SC_ERROR_OUT_OF_MEMORY;
1049
0
      goto err;
1050
0
    }
1051
0
    ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), &ci->serial.value);
1052
0
  }
1053
  /* if len == 0, and value == NULL, then the cert did not have a serial number.*/
1054
0
  sc_log(ctx,  "cert. serial encoded length %zu", ci->serial.len);
1055
1056
#else
1057
  do   {
1058
    int encoded_len;
1059
    unsigned char encoded[0x40], *encoded_ptr;
1060
1061
    encoded_ptr = encoded;
1062
    encoded_len = i2c_ASN1_INTEGER(X509_get_serialNumber(x), &encoded_ptr);
1063
1064
    if (!(ci->serial.value = malloc(encoded_len + 3)))   {
1065
      r = SC_ERROR_OUT_OF_MEMORY;
1066
      goto err;
1067
    }
1068
1069
    memcpy(ci->serial.value + 2, encoded, encoded_len);
1070
    *(ci->serial.value + 0) = V_ASN1_INTEGER;
1071
    *(ci->serial.value + 1) = encoded_len;
1072
    ci->serial.len = encoded_len + 2;
1073
1074
    sc_log(ctx,  "cert. serial encoded length %i", encoded_len);
1075
  } while (0);
1076
#endif
1077
1078
0
  ci->x509 = X509_dup(x);
1079
0
err:
1080
0
  ERR_print_errors_fp(stderr);
1081
0
  ERR_clear_error();
1082
0
  if (pubkey.exponent.data) free(pubkey.exponent.data);
1083
0
  if (pubkey.modulus.data) free(pubkey.modulus.data);
1084
0
  if (x) X509_free(x);
1085
0
  if (mem) BIO_free(mem);
1086
0
  if (buff) OPENSSL_free(buff);
1087
1088
0
  LOG_FUNC_RETURN(ctx, r);
1089
0
}
1090
1091
1092
static void
1093
awp_free_cert_info(struct awp_cert_info *ci)
1094
0
{
1095
0
  if (ci) {
1096
0
    if (ci->cn.len && ci->cn.value)
1097
0
      free(ci->cn.value);
1098
1099
0
    if (ci->id.len && ci->id.value)
1100
0
      free(ci->id.value);
1101
1102
0
    if (ci->subject.len && ci->subject.value)
1103
0
      free(ci->subject.value);
1104
1105
0
    if (ci->issuer.len && ci->issuer.value)
1106
0
      free(ci->issuer.value);
1107
1108
0
    if (ci->x509)
1109
0
      X509_free(ci->x509);
1110
1111
0
    memset(ci,0,sizeof(struct awp_cert_info));
1112
0
  }
1113
0
}
1114
1115
1116
static int
1117
awp_encode_data_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
1118
    struct awp_data_info *di)
1119
0
{
1120
0
  struct sc_context *ctx = p15card->card->ctx;
1121
0
  struct sc_pkcs15_data_info *data_info;
1122
0
  int r = 0;
1123
0
  unsigned char *buf = NULL;
1124
0
  size_t buflen;
1125
1126
0
  LOG_FUNC_CALLED(ctx);
1127
1128
0
  if (!obj || !di)
1129
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode data failed: invalid parameters");
1130
1131
0
  data_info = (struct sc_pkcs15_data_info *)obj->data;
1132
1133
0
  sc_log(ctx,
1134
0
     "Encode data(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))",
1135
0
     obj->label, sc_pkcs15_print_id(&data_info->id),
1136
0
     obj->content.value, obj->content.len);
1137
1138
0
  di->flags = 0x0000;
1139
1140
0
  di->label.value = (unsigned char *)strdup(obj->label);
1141
0
  di->label.len = strlen(obj->label);
1142
1143
0
  di->app.len = strlen(data_info->app_label);
1144
0
  if (di->app.len)   {
1145
0
    di->app.value = (unsigned char *)strdup(data_info->app_label);
1146
0
    if (!di->app.value)
1147
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
1148
0
  }
1149
1150
0
  r = sc_asn1_encode_object_id(&buf, &buflen, &data_info->app_oid);
1151
0
  LOG_TEST_RET(ctx, r, "AWP encode data failed: cannot encode OID");
1152
1153
0
  di->oid.len = buflen + 2;
1154
0
  di->oid.value = malloc(di->oid.len);
1155
0
  if (!di->oid.value) {
1156
0
    free(buf);
1157
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode data failed: cannot allocate OID");
1158
0
  }
1159
1160
0
  *(di->oid.value + 0) = 0x06;
1161
0
  *(di->oid.value + 1) = buflen;
1162
0
  memcpy(di->oid.value + 2, buf, buflen);
1163
1164
0
  free(buf);
1165
0
  LOG_FUNC_RETURN(ctx, r);
1166
0
}
1167
1168
1169
static void
1170
awp_free_data_info(struct awp_data_info *di)
1171
0
{
1172
0
  if (di->label.len && di->label.value)
1173
0
    free(di->label.value);
1174
1175
0
  if (di->app.len && di->app.value)
1176
0
    free(di->app.value);
1177
1178
0
  if (di->oid.len && di->oid.value)
1179
0
    free(di->oid.value);
1180
1181
0
  memset(di, 0, sizeof(struct awp_data_info));
1182
0
}
1183
1184
1185
static int
1186
awp_set_data_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1187
    struct sc_file *file, struct awp_data_info *di)
1188
0
{
1189
0
  struct sc_context *ctx = p15card->card->ctx;
1190
0
  int r = 0, blob_size;
1191
0
  unsigned char *blob;
1192
1193
0
  LOG_FUNC_CALLED(ctx);
1194
0
  sc_log(ctx, "Set 'DATA' info %p", di);
1195
0
  blob_size = 2;
1196
0
  if (!(blob = malloc(blob_size)))   {
1197
0
    r = SC_ERROR_OUT_OF_MEMORY;
1198
0
          goto done;
1199
0
  }
1200
0
  *blob       = (di->flags >> 8) & 0xFF;
1201
0
  *(blob + 1) = di->flags & 0xFF;
1202
1203
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->label, TLV_TYPE_LLV);
1204
0
  if (r)
1205
0
    goto done;
1206
1207
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->app, TLV_TYPE_LLV);
1208
0
  if (r)
1209
0
    goto done;
1210
1211
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->oid, TLV_TYPE_LLV);
1212
0
  if (r)
1213
0
    goto done;
1214
1215
0
  file->size = blob_size;
1216
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
1217
0
  if (r)
1218
0
    goto done;
1219
1220
0
  r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size);
1221
0
  if (r < 0)
1222
0
    goto done;
1223
1224
0
  r = 0;
1225
0
done:
1226
0
  if (blob)
1227
0
    free(blob);
1228
1229
0
  LOG_FUNC_RETURN(ctx, r);
1230
0
}
1231
1232
1233
static int
1234
awp_get_lv(struct sc_context *ctx, unsigned char *buf, size_t buf_len,
1235
    size_t offs, int len_len,
1236
    struct awp_lv *out)
1237
0
{
1238
0
  int len = 0, ii;
1239
1240
0
  if (buf_len - offs < 2)
1241
0
    return 0;
1242
1243
0
  if (len_len > 2)   {
1244
0
    len = len_len;
1245
0
    len_len = 0;
1246
0
  }
1247
0
  else   {
1248
0
    for (len=0, ii=0; ii<len_len; ii++)
1249
0
      len = len * 0x100 + *(buf + offs + ii);
1250
0
  }
1251
1252
0
  if (len && out)   {
1253
0
    if (out->value)
1254
0
      free(out->value);
1255
1256
0
    out->value = malloc(len);
1257
0
    if (!out->value)
1258
0
      return SC_ERROR_OUT_OF_MEMORY;
1259
0
    memcpy(out->value, buf + offs + len_len, len);
1260
0
    out->len = len;
1261
0
  }
1262
1263
0
  return len_len + len;
1264
0
}
1265
1266
1267
static int
1268
awp_parse_key_info(struct sc_context *ctx, unsigned char *buf, size_t buf_len,
1269
    struct awp_key_info *ikey)
1270
0
{
1271
0
  size_t offs;
1272
0
  int len;
1273
1274
0
  LOG_FUNC_CALLED(ctx);
1275
0
  offs = 0;
1276
1277
  /* Flags */
1278
0
  if (buf_len - offs < 2)
1279
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1280
0
  ikey->flags = *(buf + offs) * 0x100 + *(buf + offs + 1);
1281
0
  offs += 2;
1282
1283
  /* Label */
1284
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->label);
1285
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: label");
1286
0
  if (!len)
1287
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1288
0
  offs += len;
1289
1290
  /* Ignore Key ID */
1291
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->id);
1292
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: ID");
1293
0
  if (!len)
1294
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1295
0
  offs += len;
1296
1297
0
  while (*(buf + offs) == '0')
1298
0
    offs++;
1299
1300
  /* Subject */
1301
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->subject);
1302
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: subject");
1303
0
  if (!len)
1304
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1305
0
  offs += len;
1306
1307
  /* Modulus */
1308
0
  if (buf_len - offs > 64 && buf_len - offs < 128)
1309
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 64, &ikey->modulus);
1310
0
  else if (buf_len - offs > 128 && buf_len - offs < 256)
1311
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 128, &ikey->modulus);
1312
0
  else
1313
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 256, &ikey->modulus);
1314
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: modulus");
1315
0
  if (!len)
1316
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1317
0
  offs += len;
1318
1319
  /* Exponent */
1320
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 1, &ikey->exponent);
1321
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: exponent");
1322
0
  if (!len)
1323
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1324
1325
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1326
0
}
1327
1328
1329
static int
1330
awp_update_key_info(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1331
    unsigned prvkey_id,  struct awp_cert_info *ci)
1332
0
{
1333
0
  struct sc_context *ctx = p15card->card->ctx;
1334
0
  struct sc_file *key_file=NULL, *info_file=NULL, *file=NULL;
1335
0
  struct awp_key_info ikey;
1336
0
  int rv = 0;
1337
0
  unsigned char *buf;
1338
0
  size_t buf_len;
1339
1340
0
  LOG_FUNC_CALLED(ctx);
1341
1342
0
      rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_PRKEY_RSA, prvkey_id & 0xFF, &info_file, &key_file);
1343
0
  LOG_TEST_RET(ctx, rv, "AWP update key info failed: instantiation error");
1344
0
  sc_log(ctx,  "key id %X; info id%X", key_file->id, info_file->id);
1345
1346
0
  rv = sc_pkcs15init_authenticate(profile, p15card, info_file, SC_AC_OP_READ);
1347
0
  if (rv)   {
1348
0
    sc_log(ctx,  "AWP update key info failed: 'READ' authentication error");
1349
0
    goto done;
1350
0
  }
1351
1352
0
  rv = sc_select_file(p15card->card, &info_file->path, &file);
1353
0
  if (rv)   {
1354
0
    sc_log(ctx,  "AWP update key info failed: cannot select info file");
1355
0
    goto done;
1356
0
  }
1357
1358
0
  buf = calloc(1,file->size);
1359
0
  if (!buf)
1360
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update key info failed: allocation error");
1361
1362
0
  rv = sc_read_binary(p15card->card, 0, buf, file->size, 0);
1363
0
  if (rv < 0)    {
1364
0
    sc_log(ctx,  "AWP update key info failed: read info file error");
1365
0
    goto done;
1366
0
  }
1367
0
  buf_len = rv;
1368
1369
0
  memset(&ikey, 0, sizeof(ikey));
1370
0
  rv = awp_parse_key_info(ctx, buf, buf_len, &ikey);
1371
0
  if (rv < 0)   {
1372
0
    sc_log(ctx,  "AWP update key info failed: parse key info error");
1373
0
    goto done;
1374
0
  }
1375
0
  free(buf);
1376
1377
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, ci);
1378
0
  LOG_TEST_RET(ctx, rv, "AWP update key info failed: set key info error");
1379
0
done:
1380
0
  sc_file_free(file);
1381
0
  sc_file_free(key_file);
1382
0
  sc_file_free(info_file);
1383
1384
0
  LOG_FUNC_RETURN(ctx, rv);
1385
0
}
1386
1387
1388
static int
1389
awp_update_df_create_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1390
    struct sc_pkcs15_object *obj)
1391
0
{
1392
0
  struct sc_context *ctx = p15card->card->ctx;
1393
0
  struct sc_file *info_file=NULL, *obj_file=NULL;
1394
0
  struct awp_cert_info icert;
1395
0
  struct sc_pkcs15_der der;
1396
0
  struct sc_path path;
1397
0
  unsigned prvkey_id, obj_id;
1398
0
  int rv;
1399
1400
0
  LOG_FUNC_CALLED(ctx);
1401
1402
0
  der = obj->content;
1403
0
  path = ((struct sc_pkcs15_cert_info *)obj->data)->path;
1404
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1405
1406
0
  rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF, &info_file, &obj_file);
1407
0
  LOG_TEST_RET(ctx, rv, "COSM new file error");
1408
1409
0
  memset(&icert, 0, sizeof(icert));
1410
0
  sc_log(ctx,
1411
0
     "Cert Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1412
0
  rv = awp_encode_cert_info(p15card, obj, &icert);
1413
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot encode info");
1414
1415
0
  rv = awp_set_certificate_info(p15card, profile, info_file, &icert);
1416
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot set info");
1417
1418
0
  rv = awp_update_object_list(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF);
1419
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update list");
1420
1421
0
  rv = awp_update_container(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &icert.id, obj_id, &prvkey_id);
1422
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update container");
1423
1424
0
  sc_log(ctx,  "PrvKeyID:%04X", prvkey_id);
1425
1426
0
  if (prvkey_id)
1427
0
    rv = awp_update_key_info(p15card, profile, prvkey_id, &icert);
1428
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update key info");
1429
1430
0
  awp_free_cert_info(&icert);
1431
1432
0
err:
1433
0
  sc_file_free(info_file);
1434
0
  sc_file_free(obj_file);
1435
1436
0
  LOG_FUNC_RETURN(ctx, rv);
1437
0
}
1438
1439
1440
static int
1441
awp_update_df_create_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1442
    struct sc_pkcs15_object *key_obj)
1443
0
{
1444
0
  struct sc_context *ctx = p15card->card->ctx;
1445
0
  struct sc_pkcs15_pubkey pubkey;
1446
0
  struct sc_pkcs15_der der;
1447
0
  struct awp_key_info ikey;
1448
0
  struct awp_cert_info icert;
1449
0
  struct sc_file *info_file=NULL;
1450
0
  struct sc_pkcs15_prkey_info *key_info;
1451
0
  struct sc_pkcs15_object *cert_obj = NULL, *pubkey_obj = NULL;
1452
0
  struct sc_path path;
1453
0
  struct awp_crypto_container cc;
1454
0
  struct sc_pkcs15_cert *p15cert = NULL;
1455
0
  int rv;
1456
1457
0
  LOG_FUNC_CALLED(ctx);
1458
1459
0
  memset(&ikey, 0, sizeof(ikey));
1460
0
  memset(&icert, 0, sizeof(icert));
1461
1462
0
  key_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
1463
0
  der = key_obj->content;
1464
1465
0
  memset(&cc, 0, sizeof(cc));
1466
0
  path = key_info->path;
1467
0
  cc.prkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1468
1469
0
  rv = sc_pkcs15_find_cert_by_id(p15card, &key_info->id, &cert_obj);
1470
0
  if (!rv)   {
1471
0
    struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) cert_obj->data;
1472
0
    int private_obj = cert_obj->flags & SC_PKCS15_CO_FLAG_PRIVATE;
1473
1474
0
    path = cert_info->path;
1475
0
    cc.cert_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1476
1477
0
    rv = sc_pkcs15_read_certificate(p15card, cert_info, private_obj, &p15cert);
1478
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot get certificate");
1479
1480
0
    rv = sc_pkcs15_allocate_object_content(ctx, cert_obj, p15cert->data.value, p15cert->data.len);
1481
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot allocate content");
1482
1483
0
    rv = awp_encode_cert_info(p15card, cert_obj, &icert);
1484
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot encode cert info");
1485
1486
0
    sc_pkcs15_free_certificate(p15cert);
1487
0
    p15cert = NULL;
1488
0
  }
1489
1490
0
  rv = sc_pkcs15_find_pubkey_by_id(p15card, &key_info->id, &pubkey_obj);
1491
0
  if (!rv)   {
1492
0
    path = ((struct sc_pkcs15_cert_info *)pubkey_obj->data)->path;
1493
0
    cc.pubkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1494
0
  }
1495
1496
0
  rv = awp_new_file(p15card, profile, key_obj->type, cc.prkey_id & 0xFF, &info_file, NULL);
1497
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New private key info file error");
1498
1499
0
  pubkey.algorithm = SC_ALGORITHM_RSA;
1500
0
  sc_log(ctx,
1501
0
     "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1502
0
  rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len);
1503
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: decode public key error");
1504
1505
0
  rv = awp_encode_key_info(p15card, key_obj, &pubkey.u.rsa, &ikey);
1506
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: encode info error");
1507
1508
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, cert_obj ? &icert : NULL);
1509
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: set info error");
1510
1511
0
  rv = awp_update_object_list(p15card, profile, key_obj->type, cc.prkey_id & 0xFF);
1512
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update object list error");
1513
1514
0
  rv = awp_create_container(p15card, profile, key_obj->type, &ikey.id, &cc);
1515
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update container error");
1516
1517
0
err:
1518
0
  if (p15cert)
1519
0
    sc_pkcs15_free_certificate(p15cert);
1520
0
  sc_file_free(info_file);
1521
0
  if (cert_obj)
1522
0
    awp_free_cert_info(&icert);
1523
0
  awp_free_key_info(&ikey);
1524
1525
0
  LOG_FUNC_RETURN(ctx, rv);
1526
0
}
1527
1528
1529
static int
1530
awp_update_df_create_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1531
    struct sc_pkcs15_object *obj)
1532
0
{
1533
0
  struct sc_context *ctx = p15card->card->ctx;
1534
0
  struct sc_pkcs15_pubkey pubkey;
1535
0
  struct sc_pkcs15_der der;
1536
0
  struct awp_key_info ikey;
1537
0
  struct sc_file *info_file=NULL;
1538
0
  struct sc_path path;
1539
0
  unsigned obj_id;
1540
0
  int index, rv;
1541
1542
0
  LOG_FUNC_CALLED(ctx);
1543
1544
0
  path = ((struct sc_pkcs15_pubkey_info *)obj->data)->path;
1545
0
  der = obj->content;
1546
0
  index = path.value[path.len-1] & 0xFF;
1547
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1548
1549
0
  memset(&ikey, 0, sizeof(ikey));
1550
1551
0
  rv = awp_new_file(p15card, profile, obj->type, index, &info_file, NULL);
1552
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New public key info file error");
1553
1554
0
  pubkey.algorithm = SC_ALGORITHM_RSA;
1555
0
  sc_log(ctx,
1556
0
     "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1557
0
  rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len);
1558
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: decode public key error");
1559
1560
0
  rv = awp_encode_key_info(p15card, obj, &pubkey.u.rsa, &ikey);
1561
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: encode info error");
1562
1563
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, NULL);
1564
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: set info error");
1565
1566
0
  rv = awp_update_object_list(p15card, profile, obj->type, index);
1567
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update object list error");
1568
1569
0
  rv = awp_update_container(p15card, profile, obj->type, &ikey.id, obj_id, NULL);
1570
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update container error");
1571
1572
0
err:
1573
0
  awp_free_key_info(&ikey);
1574
0
  sc_file_free(info_file);
1575
0
  LOG_FUNC_RETURN(ctx, rv);
1576
0
}
1577
1578
1579
static int
1580
awp_update_df_create_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1581
    struct sc_pkcs15_object *obj)
1582
0
{
1583
0
  struct sc_context *ctx = p15card->card->ctx;
1584
0
  struct sc_file *info_file=NULL, *obj_file=NULL;
1585
0
  struct awp_data_info idata;
1586
0
  struct sc_path path;
1587
0
  unsigned obj_id, obj_type = obj->auth_id.len ? COSM_TYPE_PRIVDATA_OBJECT : SC_PKCS15_TYPE_DATA_OBJECT;
1588
0
  int rv;
1589
1590
0
  LOG_FUNC_CALLED(ctx);
1591
0
  memset(&idata, 0, sizeof(idata));
1592
1593
0
  path = ((struct sc_pkcs15_data_info *)obj->data)->path;
1594
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1595
1596
0
  rv = awp_new_file(p15card, profile, obj_type, obj_id & 0xFF, &info_file, &obj_file);
1597
0
  LOG_TEST_GOTO_ERR(ctx, rv, "COSM new file error");
1598
1599
0
  rv = awp_encode_data_info(p15card, obj, &idata);
1600
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot encode info");
1601
1602
0
  rv = awp_set_data_info(p15card, profile, info_file, &idata);
1603
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot set info");
1604
1605
0
  rv = awp_update_object_list(p15card, profile, obj_type, obj_id & 0xFF);
1606
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot update list");
1607
1608
0
err:
1609
0
  awp_free_data_info(&idata);
1610
0
  sc_file_free(info_file);
1611
0
  sc_file_free(obj_file);
1612
1613
0
  LOG_FUNC_RETURN(ctx, rv);
1614
0
}
1615
1616
1617
int
1618
awp_update_df_create(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1619
    struct sc_pkcs15_object *object)
1620
0
{
1621
0
  struct sc_context *ctx = p15card->card->ctx;
1622
0
  int rv = SC_ERROR_INTERNAL;
1623
1624
0
  LOG_FUNC_CALLED(ctx);
1625
0
  if (!object)
1626
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1627
1628
0
  switch (object->type)   {
1629
0
  case SC_PKCS15_TYPE_AUTH_PIN:
1630
0
    rv = awp_update_df_create_pin(p15card, profile, object);
1631
0
    break;
1632
0
  case SC_PKCS15_TYPE_CERT_X509:
1633
0
    rv = awp_update_df_create_cert(p15card, profile, object);
1634
0
    break;
1635
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1636
0
    rv = awp_update_df_create_prvkey(p15card, profile, object);
1637
0
    break;
1638
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1639
0
    rv = awp_update_df_create_pubkey(p15card, profile, object);
1640
0
    break;
1641
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1642
0
    rv = awp_update_df_create_data(p15card, profile, object);
1643
0
    break;
1644
0
  default:
1645
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type");
1646
0
  }
1647
1648
0
  LOG_FUNC_RETURN(ctx, rv);
1649
0
}
1650
1651
1652
static int
1653
awp_delete_from_container(struct sc_pkcs15_card *p15card,
1654
    struct sc_profile *profile, int type, int file_id)
1655
0
{
1656
0
  struct sc_context *ctx = p15card->card->ctx;
1657
0
  struct sc_file *clist=NULL, *file=NULL;
1658
0
  unsigned rec, rec_len;
1659
0
  int rv = 0, ii;
1660
0
  unsigned char *buff=NULL;
1661
1662
0
  LOG_FUNC_CALLED(ctx);
1663
0
  sc_log(ctx,  "update container entry (type:%X,file-id:%X)", type, file_id);
1664
1665
0
  rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL);
1666
0
  LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot get allocate AWP file");
1667
1668
0
  rv = sc_select_file(p15card->card, &clist->path, &file);
1669
0
  LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot select container list file");
1670
1671
0
  buff = malloc(file->record_length);
1672
0
  if (!buff)
1673
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update container entry: allocation error");
1674
1675
0
  for (rec = 1; rec <= (unsigned)file->record_count; rec++)   {
1676
0
    rv = sc_read_record(p15card->card, rec, 0, buff, file->record_length, SC_RECORD_BY_REC_NR);
1677
0
    if (rv < 0)   {
1678
0
      sc_log(ctx,  "AWP update container entry: read record error %i", rv);
1679
0
      break;
1680
0
    }
1681
0
    rec_len = rv;
1682
1683
0
    for (ii=0; ii<12; ii+=2)
1684
0
      if (file_id == (*(buff+ii) * 0x100 + *(buff+ii+1)))
1685
0
        break;
1686
0
    if (ii==12)
1687
0
      continue;
1688
1689
0
    if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA)
1690
0
      memset(buff + ii/6*6, 0, 6);
1691
0
    else
1692
0
      memset(buff + ii, 0, 2);
1693
1694
0
    if (!memcmp(buff,"\0\0\0\0\0\0\0\0\0\0\0\0",12))   {
1695
0
      rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_ERASE);
1696
0
      if (rv < 0)   {
1697
0
        sc_log(ctx,  "AWP update container entry: 'erase' authentication error %i", rv);
1698
0
        break;
1699
0
      }
1700
1701
0
      rv = sc_delete_record(p15card->card, rec);
1702
0
      if (rv < 0)   {
1703
0
        sc_log(ctx,  "AWP update container entry: delete record error %i", rv);
1704
0
        break;
1705
0
      }
1706
0
    }
1707
0
    else   {
1708
0
      rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
1709
0
      if (rv < 0)   {
1710
0
        sc_log(ctx,  "AWP update container entry: 'update' authentication error %i", rv);
1711
0
        break;
1712
0
      }
1713
1714
0
      rv = sc_update_record(p15card->card, rec, 0, buff, rec_len, SC_RECORD_BY_REC_NR);
1715
0
      if (rv < 0)   {
1716
0
        sc_log(ctx,  "AWP update container entry: update record error %i", rv);
1717
0
        break;
1718
0
      }
1719
0
    }
1720
0
  }
1721
1722
0
  if (rv > 0)
1723
0
    rv = 0;
1724
1725
0
  free(buff);
1726
0
  sc_file_free(clist);
1727
0
  sc_file_free(file);
1728
1729
0
  LOG_FUNC_RETURN(ctx, rv);
1730
0
}
1731
1732
1733
static int
1734
awp_remove_from_object_list( struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1735
    int type, unsigned int obj_id)
1736
0
{
1737
0
  struct sc_context *ctx = p15card->card->ctx;
1738
0
  struct sc_file *lst_file=NULL, *lst=NULL;
1739
0
  int rv = 0;
1740
0
  unsigned ii;
1741
0
  char lst_name[NAME_MAX_LEN];
1742
0
  unsigned char *buff=NULL;
1743
0
  unsigned char id[2];
1744
1745
0
  LOG_FUNC_CALLED(ctx);
1746
0
  sc_log(ctx,  "type %X; obj_id %X",type, obj_id);
1747
1748
0
  switch (type)   {
1749
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1750
0
  case COSM_TYPE_PRKEY_RSA:
1751
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE);
1752
0
    break;
1753
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1754
0
  case SC_PKCS15_TYPE_CERT_X509:
1755
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1756
0
  case COSM_TYPE_PUBKEY_RSA:
1757
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE);
1758
0
    break;
1759
0
  default:
1760
0
    LOG_TEST_RET(ctx, SC_ERROR_INCORRECT_PARAMETERS, "AWP update object list: invalid type");
1761
0
  }
1762
1763
0
  sc_log(ctx,  "AWP update object list: select '%s' file", lst_name);
1764
0
  rv = sc_profile_get_file(profile, lst_name, &lst_file);
1765
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: cannot instantiate list file");
1766
1767
0
  rv = sc_select_file(p15card->card, &lst_file->path, &lst);
1768
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: cannot select list file");
1769
1770
0
  rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_READ);
1771
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: 'read' authentication failed");
1772
1773
0
  buff = malloc(lst->size);
1774
0
  if (!buff)
1775
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update object list: allocation error");
1776
1777
0
  rv = sc_read_binary(p15card->card, 0, buff, lst->size, 0);
1778
0
  if (rv != (int)lst->size)
1779
0
    goto done;
1780
1781
0
  id[0] = (obj_id >> 8) & 0xFF;
1782
0
  id[1] = obj_id & 0xFF;
1783
0
  for (ii=0; ii<lst->size; ii+=5)   {
1784
0
    if (*(buff+ii)==0xFF && *(buff+ii+1)==id[0] && *(buff+ii+2)==id[1])   {
1785
0
      rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_UPDATE);
1786
0
      if (rv)
1787
0
        goto done;
1788
1789
0
      rv = sc_update_binary(p15card->card, ii, (unsigned char *)"\0", 1, 0);
1790
0
      if (rv && rv!=1)
1791
0
        rv = SC_ERROR_INVALID_CARD;
1792
0
      break;
1793
0
    }
1794
0
  }
1795
1796
0
  if (rv > 0)
1797
0
    rv = 0;
1798
0
done:
1799
0
  if (buff)
1800
0
    free(buff);
1801
0
  sc_file_free(lst);
1802
0
  sc_file_free(lst_file);
1803
1804
0
  LOG_FUNC_RETURN(ctx, rv);
1805
0
}
1806
1807
1808
static int
1809
awp_update_df_delete_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1810
    struct sc_pkcs15_object *obj)
1811
0
{
1812
0
  struct sc_context *ctx = p15card->card->ctx;
1813
0
  struct sc_file *info_file = NULL;
1814
0
  struct sc_path path;
1815
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1816
0
  unsigned file_id;
1817
1818
0
  LOG_FUNC_CALLED(ctx);
1819
1820
0
  path = ((struct sc_pkcs15_cert_info *) obj->data)->path;
1821
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1822
0
  sc_log(ctx,  "file-id:%X", file_id);
1823
1824
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1825
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot get allocate new AWP file");
1826
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1827
1828
0
  rv = cosm_delete_file(p15card, profile, info_file);
1829
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1830
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: delete info file error");
1831
1832
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1833
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot update container");
1834
1835
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1836
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot remove object");
1837
1838
0
  LOG_FUNC_RETURN(ctx, rv);
1839
0
}
1840
1841
1842
static int
1843
awp_update_df_delete_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1844
    struct sc_pkcs15_object *obj)
1845
0
{
1846
0
  struct sc_context *ctx = p15card->card->ctx;
1847
0
  struct sc_file *info_file = NULL;
1848
0
  struct sc_path path;
1849
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1850
0
  unsigned file_id;
1851
1852
0
  LOG_FUNC_CALLED(ctx);
1853
1854
0
  path = ((struct sc_pkcs15_prkey_info *) obj->data)->path;
1855
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1856
0
  sc_log(ctx,  "file-id:%X", file_id);
1857
1858
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1859
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot get allocate new AWP file");
1860
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1861
1862
0
  rv = cosm_delete_file(p15card, profile, info_file);
1863
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1864
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: delete info file error");
1865
1866
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1867
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot update container");
1868
1869
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1870
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot remove object");
1871
1872
0
  LOG_FUNC_RETURN(ctx, rv);
1873
0
}
1874
1875
1876
static int
1877
awp_update_df_delete_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1878
    struct sc_pkcs15_object *obj)
1879
0
{
1880
0
  struct sc_context *ctx = p15card->card->ctx;
1881
0
  struct sc_file *info_file = NULL;
1882
0
  struct sc_path path;
1883
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1884
0
  unsigned file_id;
1885
1886
0
  LOG_FUNC_CALLED(ctx);
1887
1888
0
  path = ((struct sc_pkcs15_pubkey_info *) obj->data)->path;
1889
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1890
0
  sc_log(ctx,  "file-id:%X", file_id);
1891
1892
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1893
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot get allocate new AWP file");
1894
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1895
1896
0
  rv = cosm_delete_file(p15card, profile, info_file);
1897
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1898
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: delete info file error");
1899
1900
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1901
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot update container");
1902
1903
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1904
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot remove object");
1905
1906
0
  LOG_FUNC_RETURN(ctx, rv);
1907
0
}
1908
1909
1910
static int
1911
awp_update_df_delete_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1912
    struct sc_pkcs15_object *obj)
1913
0
{
1914
0
  struct sc_context *ctx = p15card->card->ctx;
1915
0
  struct sc_file *info_file = NULL;
1916
0
  struct sc_path path;
1917
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1918
0
  unsigned file_id;
1919
1920
0
  LOG_FUNC_CALLED(ctx);
1921
1922
0
  path = ((struct sc_pkcs15_data_info *) obj->data)->path;
1923
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1924
0
  sc_log(ctx,  "file-id:%X", file_id);
1925
1926
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1927
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot get allocate new AWP file");
1928
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1929
1930
0
  rv = cosm_delete_file(p15card, profile, info_file);
1931
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1932
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: delete info file error");
1933
1934
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1935
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot remove object");
1936
1937
0
  LOG_FUNC_RETURN(ctx, rv);
1938
0
}
1939
1940
1941
int
1942
awp_update_df_delete(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1943
    struct sc_pkcs15_object *object)
1944
0
{
1945
0
  struct sc_context *ctx = p15card->card->ctx;
1946
0
  int rv = SC_ERROR_INTERNAL;
1947
1948
0
  LOG_FUNC_CALLED(ctx);
1949
0
  if (!object)
1950
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1951
1952
0
  switch (object->type)   {
1953
0
  case SC_PKCS15_TYPE_CERT_X509:
1954
0
    rv = awp_update_df_delete_cert(p15card, profile, object);
1955
0
    break;
1956
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1957
0
    rv = awp_update_df_delete_prvkey(p15card, profile, object);
1958
0
    break;
1959
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1960
0
    rv = awp_update_df_delete_pubkey(p15card, profile, object);
1961
0
    break;
1962
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1963
0
    rv = awp_update_df_delete_data(p15card, profile, object);
1964
0
    break;
1965
0
  default:
1966
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type");
1967
0
  }
1968
1969
0
  SC_FUNC_RETURN(ctx, 1, rv);
1970
0
}
1971
1972
#endif /* #ifdef ENABLE_OPENSSL */