Coverage Report

Created: 2025-07-18 06:10

/src/opensc/src/pkcs15init/pkcs15-oberthur-awp.c
Line
Count
Source (jump to first uncovered line)
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
    X509_NAME_ENTRY *ne;
55
0
    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 (a_str->type == 0x0C)   {
62
0
      ret = malloc(a_str->length + 1);
63
0
      if (ret)   {
64
0
        memcpy(ret, a_str->data, a_str->length);
65
0
        *(ret + a_str->length) = '\0';
66
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
  flags = lst_file->ef_structure;
728
0
  rv = sc_read_binary(p15card->card, 0, buff, lst_file->size, &flags);
729
0
  if (rv < 0)
730
0
    goto done;
731
732
0
  for (ii=0; ii < lst_file->size; ii+=5)
733
0
    if (*(buff + ii) != COSM_LIST_TAG)
734
0
      break;
735
0
  if (ii>=lst_file->size)   {
736
0
    rv = SC_ERROR_UNKNOWN_DATA_RECEIVED;
737
0
    goto done;
738
0
  }
739
740
0
  sc_log(ctx,
741
0
     "ii %i, rv %i; %X; %"SC_FORMAT_LEN_SIZE_T"u",
742
0
     ii, rv, file->id, file->size);
743
0
  *(buff + ii) = COSM_LIST_TAG;
744
0
  *(buff + ii + 1) = (file->id >> 8) & 0xFF;
745
0
  *(buff + ii + 2) = file->id & 0xFF;
746
0
  *(buff + ii + 3) = (file->size >> 8) & 0xFF;
747
0
  *(buff + ii + 4) = file->size & 0xFF;
748
749
0
  rv = sc_update_binary(p15card->card, ii, buff + ii, 5, 0);
750
0
  sc_log(ctx,  "rv %i",rv);
751
0
  if (rv < 0)
752
0
    goto done;
753
754
0
  rv = 0;
755
0
done:
756
0
  if (buff)
757
0
    free(buff);
758
0
  sc_file_free(lst_file);
759
0
  sc_file_free(obj_file);
760
0
  sc_file_free(file);
761
762
0
  LOG_FUNC_RETURN(ctx, rv);
763
0
}
764
765
766
static int
767
awp_encode_key_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
768
    struct sc_pkcs15_pubkey_rsa *pubkey, struct awp_key_info *ki)
769
0
{
770
0
  struct sc_context *ctx = p15card->card->ctx;
771
0
  struct sc_pkcs15_prkey_info *key_info;
772
0
  int r = 0;
773
774
0
  LOG_FUNC_CALLED(ctx);
775
776
0
  key_info = (struct sc_pkcs15_prkey_info *)obj->data;
777
778
0
  sc_log(ctx,  "object(%s,type:%X)", obj->label, obj->type);
779
0
  if (obj->type == SC_PKCS15_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PUBKEY_RSA )
780
0
    ki->flags = COSM_TAG_PUBKEY_RSA;
781
0
  else if (obj->type == SC_PKCS15_TYPE_PRKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA)
782
0
    ki->flags = COSM_TAG_PRVKEY_RSA;
783
0
  else
784
0
    return SC_ERROR_INCORRECT_PARAMETERS;
785
786
0
  if (obj->type == COSM_TYPE_PUBKEY_RSA || obj->type == COSM_TYPE_PRKEY_RSA)
787
0
    ki->flags |= COSM_GENERATED;
788
789
0
  ki->label.value = (unsigned char *)strdup(obj->label);
790
0
  ki->label.len = strlen(obj->label);
791
0
  sc_log(ctx,
792
0
     "cosm_encode_key_info() label(%zu):%s",
793
0
     ki->label.len, ki->label.value);
794
795
  /*
796
   * Oberthur saves modulus value without tag and length.
797
   */
798
0
  sc_log(ctx,
799
0
     "pubkey->modulus.len %"SC_FORMAT_LEN_SIZE_T"u",
800
0
     pubkey->modulus.len);
801
0
  ki->modulus.value = malloc(pubkey->modulus.len);
802
0
  if (!ki->modulus.value)   {
803
0
    r = SC_ERROR_OUT_OF_MEMORY;
804
0
    goto done;
805
0
  }
806
0
  memcpy(ki->modulus.value, pubkey->modulus.data, pubkey->modulus.len);
807
0
  ki->modulus.len = pubkey->modulus.len;
808
809
  /*
810
   * Oberthur saves exponents as length and value, without tag.
811
   */
812
0
  ki->exponent.value = malloc(pubkey->exponent.len);
813
0
  if (!ki->exponent.value)   {
814
0
    r = SC_ERROR_OUT_OF_MEMORY;
815
0
    goto done;
816
0
  }
817
0
  memcpy(ki->exponent.value, pubkey->exponent.data, pubkey->exponent.len);
818
0
  ki->exponent.len = pubkey->exponent.len;
819
820
  /*
821
   * ID
822
   */
823
0
  ki->id.value = calloc(1, key_info->id.len);
824
0
  if (!ki->id.value)
825
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: ID allocation error");
826
0
  memcpy(ki->id.value, key_info->id.value, key_info->id.len);
827
0
  ki->id.len = key_info->id.len;
828
829
0
  sc_log(ctx,  "cosm_encode_key_info() label:%s",ki->label.value);
830
0
done:
831
0
  LOG_FUNC_RETURN(ctx, r);
832
0
}
833
834
835
static void
836
awp_free_key_info(struct awp_key_info *ki)
837
0
{
838
0
  free(ki->modulus.value);
839
0
  free(ki->exponent.value);
840
0
  free(ki->id.value);
841
0
}
842
843
844
static int
845
awp_set_key_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_file *file,
846
    struct awp_key_info *ki, struct awp_cert_info *ci)
847
0
{
848
0
  struct sc_context *ctx = p15card->card->ctx;
849
0
  int r = 0, blob_size;
850
0
  unsigned char *blob;
851
852
0
  LOG_FUNC_CALLED(ctx);
853
0
  sc_log(ctx,  "file:%p, kinfo:%p, cinfo:%p", file, ki, ci);
854
0
  blob_size = 2;
855
0
  blob = malloc(blob_size);
856
0
  if (!blob)
857
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP set key info failed: blob allocation error");
858
859
0
  sc_log(ctx,  "label:%s",ki->label.value);
860
861
0
  *blob = (ki->flags >> 8) & 0xFF;
862
0
  *(blob + 1) = ki->flags & 0xFF;
863
0
  if (ci && ci->label.len)
864
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->label, TLV_TYPE_LLV);
865
0
  else if (ci && !ci->label.len)
866
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ci->cn, TLV_TYPE_LLV);
867
0
  else
868
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->label, TLV_TYPE_LLV);
869
0
  if (r)
870
0
    goto done;
871
872
0
  r = awp_update_blob(ctx, &blob, &blob_size, &ki->id, TLV_TYPE_LLV);
873
0
  if (r)
874
0
    goto done;
875
876
0
  r = awp_update_blob(ctx, &blob, &blob_size, &x30_lv, TLV_TYPE_V);
877
0
  if (r)
878
0
    goto done;
879
880
0
  if (ci)
881
0
    r = awp_update_blob(ctx, &blob, &blob_size, &(ci->subject), TLV_TYPE_LLV);
882
0
  else
883
0
    r = awp_update_blob(ctx, &blob, &blob_size, &zero_lv, TLV_TYPE_LLV);
884
0
  if (r)
885
0
    goto done;
886
887
0
  if ((ki->flags & ~COSM_GENERATED) != COSM_TAG_PUBKEY_RSA)   {
888
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->modulus, TLV_TYPE_V);
889
0
    if (r)
890
0
      goto done;
891
892
0
    r = awp_update_blob(ctx, &blob, &blob_size, &ki->exponent, TLV_TYPE_LV);
893
0
    if (r)
894
0
      goto done;
895
0
  }
896
897
0
  file->size = blob_size;
898
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
899
0
  if (r == SC_ERROR_FILE_ALREADY_EXISTS)   {
900
0
    r =  cosm_delete_file(p15card, profile, file);
901
0
    if (!r)
902
0
      r = sc_pkcs15init_create_file(profile, p15card, file);
903
0
  }
904
905
0
  if (r<0)
906
0
    goto done;
907
908
0
  r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size);
909
0
  if (r < 0)
910
0
    goto done;
911
912
0
  r = 0;
913
0
done:
914
0
  if (blob)
915
0
    free(blob);
916
917
0
  LOG_FUNC_RETURN(ctx, r);
918
0
}
919
920
921
static int
922
awp_encode_cert_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
923
    struct awp_cert_info *ci)
924
0
{
925
0
  struct sc_context *ctx = p15card->card->ctx;
926
0
  struct sc_pkcs15_cert_info *cert_info;
927
0
  struct sc_pkcs15_pubkey_rsa pubkey;
928
0
  int r = 0;
929
0
  unsigned char *buff = NULL, *ptr;
930
0
  BIO *mem = NULL;
931
0
  X509 *x = NULL;
932
933
0
  LOG_FUNC_CALLED(ctx);
934
935
0
  if (!obj || !ci)
936
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode cert failed: invalid parameters");
937
938
0
  cert_info = (struct sc_pkcs15_cert_info *)obj->data;
939
940
0
  sc_log(ctx,
941
0
     "Encode cert(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))",
942
0
     obj->label, sc_pkcs15_print_id(&cert_info->id),
943
0
     obj->content.value, obj->content.len);
944
0
  memset(&pubkey, 0, sizeof(pubkey));
945
946
0
  ci->label.value = (unsigned char *)strdup(obj->label);
947
0
  ci->label.len = strlen(obj->label);
948
949
0
  mem = BIO_new_mem_buf(obj->content.value, (int)obj->content.len);
950
0
  if (!mem) {
951
0
    sc_log_openssl(ctx);
952
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: invalid data");
953
0
  }
954
955
0
  x = d2i_X509_bio(mem, NULL);
956
0
  if (!x) {
957
0
    sc_log_openssl(ctx);
958
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "AWP encode cert failed: x509 parse error");
959
0
  }
960
961
0
  buff = OPENSSL_malloc(i2d_X509(x,NULL) + EVP_MAX_MD_SIZE);
962
0
  if (!buff)
963
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode cert failed: memory allocation error");
964
965
  /*
966
   * subject commonName.
967
   */
968
0
  ptr = awp_get_commonName(x);
969
0
  if (!ptr) {
970
0
    r = SC_ERROR_INTERNAL;
971
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get CommonName");
972
0
  }
973
0
  ci->cn.value = ptr;
974
0
  ci->cn.len = strlen((char *)ptr);
975
976
  /*
977
   * subject DN
978
   */
979
0
  ptr = buff;
980
0
  r = i2d_X509_NAME(X509_get_subject_name(x),&ptr);
981
0
  if (r<=0) {
982
0
    sc_log_openssl(ctx);
983
0
    r = SC_ERROR_INTERNAL;
984
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get SubjectName");
985
0
  }
986
987
0
  ci->subject.value = malloc(r);
988
0
  if (!ci->subject.value) {
989
0
    r = SC_ERROR_OUT_OF_MEMORY;
990
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: subject allocation error");
991
0
  }
992
0
  memcpy(ci->subject.value, buff, r);
993
0
  ci->subject.len = r;
994
995
  /*
996
   * issuer DN
997
   */
998
0
  ptr = buff;
999
0
  r = i2d_X509_NAME(X509_get_issuer_name(x),&ptr);
1000
0
  if (r <= 0) {
1001
0
    sc_log_openssl(ctx);
1002
0
    r = SC_ERROR_INTERNAL;
1003
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: cannot get IssuerName");
1004
0
  }
1005
1006
0
  ci->issuer.value = malloc(r);
1007
0
  if (!ci->issuer.value) {
1008
0
    r = SC_ERROR_OUT_OF_MEMORY;
1009
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: issuer allocation error");
1010
0
  }
1011
0
  memcpy(ci->issuer.value, buff, r);
1012
0
  ci->issuer.len = r;
1013
1014
  /*
1015
   * ID
1016
   */
1017
0
  ci->id.value = calloc(1, cert_info->id.len);
1018
0
  if (!ci->id.value) {
1019
0
    r = SC_ERROR_OUT_OF_MEMORY;
1020
0
    LOG_TEST_GOTO_ERR(ctx, r, "AWP encode cert failed: ID allocation error");
1021
0
  }
1022
0
  memcpy(ci->id.value, cert_info->id.value, cert_info->id.len);
1023
0
  ci->id.len = cert_info->id.len;
1024
1025
  /*
1026
   * serial number
1027
   */
1028
0
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
1029
1030
  /* TODO the der encoding of a ANS1_INTEGER is a TLV, the original code only as using the
1031
   * i2c_ASN1_INTEGER which is not in OpenSSL 1.1
1032
   * It was adding the tag V_ASN1_INTEGER and the one byte length back in in effect creating
1033
   * a DER encoded ASN1_INTEGER
1034
   * So we can simplify the code and make compatible with OpenSSL 1.1. This needs to be tested
1035
   */
1036
0
  ci->serial.len = 0;
1037
0
  ci->serial.value = NULL;
1038
  /* get length */
1039
0
  ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), NULL);
1040
0
  if (ci->serial.len > 0) {
1041
0
    if (!(ci->serial.value = malloc(ci->serial.len)))   {
1042
0
      ci->serial.len = 0;
1043
0
      r = SC_ERROR_OUT_OF_MEMORY;
1044
0
      goto err;
1045
0
    }
1046
0
    ci->serial.len = i2d_ASN1_INTEGER(X509_get_serialNumber(x), &ci->serial.value);
1047
0
  }
1048
  /* if len == 0, and value == NULL, then the cert did not have a serial number.*/
1049
0
  sc_log(ctx,  "cert. serial encoded length %zu", ci->serial.len);
1050
1051
#else
1052
  do   {
1053
    int encoded_len;
1054
    unsigned char encoded[0x40], *encoded_ptr;
1055
1056
    encoded_ptr = encoded;
1057
    encoded_len = i2c_ASN1_INTEGER(X509_get_serialNumber(x), &encoded_ptr);
1058
1059
    if (!(ci->serial.value = malloc(encoded_len + 3)))   {
1060
      r = SC_ERROR_OUT_OF_MEMORY;
1061
      goto err;
1062
    }
1063
1064
    memcpy(ci->serial.value + 2, encoded, encoded_len);
1065
    *(ci->serial.value + 0) = V_ASN1_INTEGER;
1066
    *(ci->serial.value + 1) = encoded_len;
1067
    ci->serial.len = encoded_len + 2;
1068
1069
    sc_log(ctx,  "cert. serial encoded length %i", encoded_len);
1070
  } while (0);
1071
#endif
1072
1073
0
  ci->x509 = X509_dup(x);
1074
0
err:
1075
0
  ERR_print_errors_fp(stderr);
1076
0
  ERR_clear_error();
1077
0
  if (pubkey.exponent.data) free(pubkey.exponent.data);
1078
0
  if (pubkey.modulus.data) free(pubkey.modulus.data);
1079
0
  if (x) X509_free(x);
1080
0
  if (mem) BIO_free(mem);
1081
0
  if (buff) OPENSSL_free(buff);
1082
1083
0
  LOG_FUNC_RETURN(ctx, r);
1084
0
}
1085
1086
1087
static void
1088
awp_free_cert_info(struct awp_cert_info *ci)
1089
0
{
1090
0
  if (ci) {
1091
0
    if (ci->cn.len && ci->cn.value)
1092
0
      free(ci->cn.value);
1093
1094
0
    if (ci->id.len && ci->id.value)
1095
0
      free(ci->id.value);
1096
1097
0
    if (ci->subject.len && ci->subject.value)
1098
0
      free(ci->subject.value);
1099
1100
0
    if (ci->issuer.len && ci->issuer.value)
1101
0
      free(ci->issuer.value);
1102
1103
0
    if (ci->x509)
1104
0
      X509_free(ci->x509);
1105
1106
0
    memset(ci,0,sizeof(struct awp_cert_info));
1107
0
  }
1108
0
}
1109
1110
1111
static int
1112
awp_encode_data_info(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
1113
    struct awp_data_info *di)
1114
0
{
1115
0
  struct sc_context *ctx = p15card->card->ctx;
1116
0
  struct sc_pkcs15_data_info *data_info;
1117
0
  int r = 0;
1118
0
  unsigned char *buf = NULL;
1119
0
  size_t buflen;
1120
1121
0
  LOG_FUNC_CALLED(ctx);
1122
1123
0
  if (!obj || !di)
1124
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "AWP encode data failed: invalid parameters");
1125
1126
0
  data_info = (struct sc_pkcs15_data_info *)obj->data;
1127
1128
0
  sc_log(ctx,
1129
0
     "Encode data(%s,id:%s,der(%p,%"SC_FORMAT_LEN_SIZE_T"u))",
1130
0
     obj->label, sc_pkcs15_print_id(&data_info->id),
1131
0
     obj->content.value, obj->content.len);
1132
1133
0
  di->flags = 0x0000;
1134
1135
0
  di->label.value = (unsigned char *)strdup(obj->label);
1136
0
  di->label.len = strlen(obj->label);
1137
1138
0
  di->app.len = strlen(data_info->app_label);
1139
0
  if (di->app.len)   {
1140
0
    di->app.value = (unsigned char *)strdup(data_info->app_label);
1141
0
    if (!di->app.value)
1142
0
      LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
1143
0
  }
1144
1145
0
  r = sc_asn1_encode_object_id(&buf, &buflen, &data_info->app_oid);
1146
0
  LOG_TEST_RET(ctx, r, "AWP encode data failed: cannot encode OID");
1147
1148
0
  di->oid.len = buflen + 2;
1149
0
  di->oid.value = malloc(di->oid.len);
1150
0
  if (!di->oid.value) {
1151
0
    free(buf);
1152
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP encode data failed: cannot allocate OID");
1153
0
  }
1154
1155
0
  *(di->oid.value + 0) = 0x06;
1156
0
  *(di->oid.value + 1) = buflen;
1157
0
  memcpy(di->oid.value + 2, buf, buflen);
1158
1159
0
  free(buf);
1160
0
  LOG_FUNC_RETURN(ctx, r);
1161
0
}
1162
1163
1164
static void
1165
awp_free_data_info(struct awp_data_info *di)
1166
0
{
1167
0
  if (di->label.len && di->label.value)
1168
0
    free(di->label.value);
1169
1170
0
  if (di->app.len && di->app.value)
1171
0
    free(di->app.value);
1172
1173
0
  if (di->oid.len && di->oid.value)
1174
0
    free(di->oid.value);
1175
1176
0
  memset(di, 0, sizeof(struct awp_data_info));
1177
0
}
1178
1179
1180
static int
1181
awp_set_data_info (struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1182
    struct sc_file *file, struct awp_data_info *di)
1183
0
{
1184
0
  struct sc_context *ctx = p15card->card->ctx;
1185
0
  int r = 0, blob_size;
1186
0
  unsigned char *blob;
1187
1188
0
  LOG_FUNC_CALLED(ctx);
1189
0
  sc_log(ctx, "Set 'DATA' info %p", di);
1190
0
  blob_size = 2;
1191
0
  if (!(blob = malloc(blob_size)))   {
1192
0
    r = SC_ERROR_OUT_OF_MEMORY;
1193
0
          goto done;
1194
0
  }
1195
0
  *blob       = (di->flags >> 8) & 0xFF;
1196
0
  *(blob + 1) = di->flags & 0xFF;
1197
1198
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->label, TLV_TYPE_LLV);
1199
0
  if (r)
1200
0
    goto done;
1201
1202
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->app, TLV_TYPE_LLV);
1203
0
  if (r)
1204
0
    goto done;
1205
1206
0
  r = awp_update_blob(ctx, &blob, &blob_size, &di->oid, TLV_TYPE_LLV);
1207
0
  if (r)
1208
0
    goto done;
1209
1210
0
  file->size = blob_size;
1211
0
  r = sc_pkcs15init_create_file(profile, p15card, file);
1212
0
  if (r)
1213
0
    goto done;
1214
1215
0
  r = sc_pkcs15init_update_file(profile, p15card, file, blob, blob_size);
1216
0
  if (r < 0)
1217
0
    goto done;
1218
1219
0
  r = 0;
1220
0
done:
1221
0
  if (blob)
1222
0
    free(blob);
1223
1224
0
  LOG_FUNC_RETURN(ctx, r);
1225
0
}
1226
1227
1228
static int
1229
awp_get_lv(struct sc_context *ctx, unsigned char *buf, size_t buf_len,
1230
    size_t offs, int len_len,
1231
    struct awp_lv *out)
1232
0
{
1233
0
  int len = 0, ii;
1234
1235
0
  if (buf_len - offs < 2)
1236
0
    return 0;
1237
1238
0
  if (len_len > 2)   {
1239
0
    len = len_len;
1240
0
    len_len = 0;
1241
0
  }
1242
0
  else   {
1243
0
    for (len=0, ii=0; ii<len_len; ii++)
1244
0
      len = len * 0x100 + *(buf + offs + ii);
1245
0
  }
1246
1247
0
  if (len && out)   {
1248
0
    if (out->value)
1249
0
      free(out->value);
1250
1251
0
    out->value = malloc(len);
1252
0
    if (!out->value)
1253
0
      return SC_ERROR_OUT_OF_MEMORY;
1254
0
    memcpy(out->value, buf + offs + len_len, len);
1255
0
    out->len = len;
1256
0
  }
1257
1258
0
  return len_len + len;
1259
0
}
1260
1261
1262
static int
1263
awp_parse_key_info(struct sc_context *ctx, unsigned char *buf, size_t buf_len,
1264
    struct awp_key_info *ikey)
1265
0
{
1266
0
  size_t offs;
1267
0
  int len;
1268
1269
0
  LOG_FUNC_CALLED(ctx);
1270
0
  offs = 0;
1271
1272
  /* Flags */
1273
0
  if (buf_len - offs < 2)
1274
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1275
0
  ikey->flags = *(buf + offs) * 0x100 + *(buf + offs + 1);
1276
0
  offs += 2;
1277
1278
  /* Label */
1279
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->label);
1280
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: label");
1281
0
  if (!len)
1282
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1283
0
  offs += len;
1284
1285
  /* Ignore Key ID */
1286
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->id);
1287
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: ID");
1288
0
  if (!len)
1289
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1290
0
  offs += len;
1291
1292
0
  while (*(buf + offs) == '0')
1293
0
    offs++;
1294
1295
  /* Subject */
1296
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 2, &ikey->subject);
1297
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: subject");
1298
0
  if (!len)
1299
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1300
0
  offs += len;
1301
1302
  /* Modulus */
1303
0
  if (buf_len - offs > 64 && buf_len - offs < 128)
1304
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 64, &ikey->modulus);
1305
0
  else if (buf_len - offs > 128 && buf_len - offs < 256)
1306
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 128, &ikey->modulus);
1307
0
  else
1308
0
    len = awp_get_lv(ctx, buf, buf_len, offs, 256, &ikey->modulus);
1309
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: modulus");
1310
0
  if (!len)
1311
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1312
0
  offs += len;
1313
1314
  /* Exponent */
1315
0
  len = awp_get_lv(ctx, buf, buf_len, offs, 1, &ikey->exponent);
1316
0
  LOG_TEST_RET(ctx, len, "AWP parse key info failed: exponent");
1317
0
  if (!len)
1318
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1319
1320
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1321
0
}
1322
1323
1324
static int
1325
awp_update_key_info(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1326
    unsigned prvkey_id,  struct awp_cert_info *ci)
1327
0
{
1328
0
  struct sc_context *ctx = p15card->card->ctx;
1329
0
  struct sc_file *key_file=NULL, *info_file=NULL, *file=NULL;
1330
0
  struct awp_key_info ikey;
1331
0
  int rv = 0;
1332
0
  unsigned char *buf;
1333
0
  size_t buf_len;
1334
1335
0
  LOG_FUNC_CALLED(ctx);
1336
1337
0
      rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_PRKEY_RSA, prvkey_id & 0xFF, &info_file, &key_file);
1338
0
  LOG_TEST_RET(ctx, rv, "AWP update key info failed: instantiation error");
1339
0
  sc_log(ctx,  "key id %X; info id%X", key_file->id, info_file->id);
1340
1341
0
  rv = sc_pkcs15init_authenticate(profile, p15card, info_file, SC_AC_OP_READ);
1342
0
  if (rv)   {
1343
0
    sc_log(ctx,  "AWP update key info failed: 'READ' authentication error");
1344
0
    goto done;
1345
0
  }
1346
1347
0
  rv = sc_select_file(p15card->card, &info_file->path, &file);
1348
0
  if (rv)   {
1349
0
    sc_log(ctx,  "AWP update key info failed: cannot select info file");
1350
0
    goto done;
1351
0
  }
1352
1353
0
  buf = calloc(1,file->size);
1354
0
  if (!buf)
1355
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update key info failed: allocation error");
1356
1357
0
  rv = sc_read_binary(p15card->card, 0, buf, file->size, 0);
1358
0
  if (rv < 0)    {
1359
0
    sc_log(ctx,  "AWP update key info failed: read info file error");
1360
0
    goto done;
1361
0
  }
1362
0
  buf_len = rv;
1363
1364
0
  memset(&ikey, 0, sizeof(ikey));
1365
0
  rv = awp_parse_key_info(ctx, buf, buf_len, &ikey);
1366
0
  if (rv < 0)   {
1367
0
    sc_log(ctx,  "AWP update key info failed: parse key info error");
1368
0
    goto done;
1369
0
  }
1370
0
  free(buf);
1371
1372
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, ci);
1373
0
  LOG_TEST_RET(ctx, rv, "AWP update key info failed: set key info error");
1374
0
done:
1375
0
  sc_file_free(file);
1376
0
  sc_file_free(key_file);
1377
0
  sc_file_free(info_file);
1378
1379
0
  LOG_FUNC_RETURN(ctx, rv);
1380
0
}
1381
1382
1383
static int
1384
awp_update_df_create_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1385
    struct sc_pkcs15_object *obj)
1386
0
{
1387
0
  struct sc_context *ctx = p15card->card->ctx;
1388
0
  struct sc_file *info_file=NULL, *obj_file=NULL;
1389
0
  struct awp_cert_info icert;
1390
0
  struct sc_pkcs15_der der;
1391
0
  struct sc_path path;
1392
0
  unsigned prvkey_id, obj_id;
1393
0
  int rv;
1394
1395
0
  LOG_FUNC_CALLED(ctx);
1396
1397
0
  der = obj->content;
1398
0
  path = ((struct sc_pkcs15_cert_info *)obj->data)->path;
1399
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1400
1401
0
  rv = awp_new_file(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF, &info_file, &obj_file);
1402
0
  LOG_TEST_RET(ctx, rv, "COSM new file error");
1403
1404
0
  memset(&icert, 0, sizeof(icert));
1405
0
  sc_log(ctx,
1406
0
     "Cert Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1407
0
  rv = awp_encode_cert_info(p15card, obj, &icert);
1408
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot encode info");
1409
1410
0
  rv = awp_set_certificate_info(p15card, profile, info_file, &icert);
1411
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot set info");
1412
1413
0
  rv = awp_update_object_list(p15card, profile, SC_PKCS15_TYPE_CERT_X509, obj_id & 0xFF);
1414
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update list");
1415
1416
0
  rv = awp_update_container(p15card, profile, SC_PKCS15_TYPE_CERT_X509, &icert.id, obj_id, &prvkey_id);
1417
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update container");
1418
1419
0
  sc_log(ctx,  "PrvKeyID:%04X", prvkey_id);
1420
1421
0
  if (prvkey_id)
1422
0
    rv = awp_update_key_info(p15card, profile, prvkey_id, &icert);
1423
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "'Create Cert' update DF failed: cannot update key info");
1424
1425
0
  awp_free_cert_info(&icert);
1426
1427
0
err:
1428
0
  sc_file_free(info_file);
1429
0
  sc_file_free(obj_file);
1430
1431
0
  LOG_FUNC_RETURN(ctx, rv);
1432
0
}
1433
1434
1435
static int
1436
awp_update_df_create_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1437
    struct sc_pkcs15_object *key_obj)
1438
0
{
1439
0
  struct sc_context *ctx = p15card->card->ctx;
1440
0
  struct sc_pkcs15_pubkey pubkey;
1441
0
  struct sc_pkcs15_der der;
1442
0
  struct awp_key_info ikey;
1443
0
  struct awp_cert_info icert;
1444
0
  struct sc_file *info_file=NULL;
1445
0
  struct sc_pkcs15_prkey_info *key_info;
1446
0
  struct sc_pkcs15_object *cert_obj = NULL, *pubkey_obj = NULL;
1447
0
  struct sc_path path;
1448
0
  struct awp_crypto_container cc;
1449
0
  struct sc_pkcs15_cert *p15cert = NULL;
1450
0
  int rv;
1451
1452
0
  LOG_FUNC_CALLED(ctx);
1453
1454
0
  memset(&ikey, 0, sizeof(ikey));
1455
0
  memset(&icert, 0, sizeof(icert));
1456
1457
0
  key_info = (struct sc_pkcs15_prkey_info *)key_obj->data;
1458
0
  der = key_obj->content;
1459
1460
0
  memset(&cc, 0, sizeof(cc));
1461
0
  path = key_info->path;
1462
0
  cc.prkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1463
1464
0
  rv = sc_pkcs15_find_cert_by_id(p15card, &key_info->id, &cert_obj);
1465
0
  if (!rv)   {
1466
0
    struct sc_pkcs15_cert_info *cert_info = (struct sc_pkcs15_cert_info *) cert_obj->data;
1467
0
    int private_obj = cert_obj->flags & SC_PKCS15_CO_FLAG_PRIVATE;
1468
1469
0
    path = cert_info->path;
1470
0
    cc.cert_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1471
1472
0
    rv = sc_pkcs15_read_certificate(p15card, cert_info, private_obj, &p15cert);
1473
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot get certificate");
1474
1475
0
    rv = sc_pkcs15_allocate_object_content(ctx, cert_obj, p15cert->data.value, p15cert->data.len);
1476
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot allocate content");
1477
1478
0
    rv = awp_encode_cert_info(p15card, cert_obj, &icert);
1479
0
    SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed:  cannot encode cert info");
1480
1481
0
    sc_pkcs15_free_certificate(p15cert);
1482
0
    p15cert = NULL;
1483
0
  }
1484
1485
0
  rv = sc_pkcs15_find_pubkey_by_id(p15card, &key_info->id, &pubkey_obj);
1486
0
  if (!rv)   {
1487
0
    path = ((struct sc_pkcs15_cert_info *)pubkey_obj->data)->path;
1488
0
    cc.pubkey_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1489
0
  }
1490
1491
0
  rv = awp_new_file(p15card, profile, key_obj->type, cc.prkey_id & 0xFF, &info_file, NULL);
1492
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New private key info file error");
1493
1494
0
  pubkey.algorithm = SC_ALGORITHM_RSA;
1495
0
  sc_log(ctx,
1496
0
     "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1497
0
  rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len);
1498
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: decode public key error");
1499
1500
0
  rv = awp_encode_key_info(p15card, key_obj, &pubkey.u.rsa, &ikey);
1501
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: encode info error");
1502
1503
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, cert_obj ? &icert : NULL);
1504
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: set info error");
1505
1506
0
  rv = awp_update_object_list(p15card, profile, key_obj->type, cc.prkey_id & 0xFF);
1507
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update object list error");
1508
1509
0
  rv = awp_create_container(p15card, profile, key_obj->type, &ikey.id, &cc);
1510
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update private key' DF failed: update container error");
1511
1512
0
err:
1513
0
  if (p15cert)
1514
0
    sc_pkcs15_free_certificate(p15cert);
1515
0
  sc_file_free(info_file);
1516
0
  if (cert_obj)
1517
0
    awp_free_cert_info(&icert);
1518
0
  awp_free_key_info(&ikey);
1519
1520
0
  LOG_FUNC_RETURN(ctx, rv);
1521
0
}
1522
1523
1524
static int
1525
awp_update_df_create_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1526
    struct sc_pkcs15_object *obj)
1527
0
{
1528
0
  struct sc_context *ctx = p15card->card->ctx;
1529
0
  struct sc_pkcs15_pubkey pubkey;
1530
0
  struct sc_pkcs15_der der;
1531
0
  struct awp_key_info ikey;
1532
0
  struct sc_file *info_file=NULL;
1533
0
  struct sc_path path;
1534
0
  unsigned obj_id;
1535
0
  int index, rv;
1536
1537
0
  LOG_FUNC_CALLED(ctx);
1538
1539
0
  path = ((struct sc_pkcs15_pubkey_info *)obj->data)->path;
1540
0
  der = obj->content;
1541
0
  index = path.value[path.len-1] & 0xFF;
1542
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1543
1544
0
  memset(&ikey, 0, sizeof(ikey));
1545
1546
0
  rv = awp_new_file(p15card, profile, obj->type, index, &info_file, NULL);
1547
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "New public key info file error");
1548
1549
0
  pubkey.algorithm = SC_ALGORITHM_RSA;
1550
0
  sc_log(ctx,
1551
0
     "PrKey Der(%p,%"SC_FORMAT_LEN_SIZE_T"u)", der.value, der.len);
1552
0
  rv = sc_pkcs15_decode_pubkey(ctx, &pubkey, der.value, der.len);
1553
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: decode public key error");
1554
1555
0
  rv = awp_encode_key_info(p15card, obj, &pubkey.u.rsa, &ikey);
1556
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: encode info error");
1557
1558
0
  rv = awp_set_key_info(p15card, profile, info_file, &ikey, NULL);
1559
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: set info error");
1560
1561
0
  rv = awp_update_object_list(p15card, profile, obj->type, index);
1562
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update object list error");
1563
1564
0
  rv = awp_update_container(p15card, profile, obj->type, &ikey.id, obj_id, NULL);
1565
0
  SC_TEST_GOTO_ERR(ctx, SC_LOG_DEBUG_VERBOSE, rv, "AWP 'update public key' DF failed: update container error");
1566
1567
0
err:
1568
0
  awp_free_key_info(&ikey);
1569
0
  sc_file_free(info_file);
1570
0
  LOG_FUNC_RETURN(ctx, rv);
1571
0
}
1572
1573
1574
static int
1575
awp_update_df_create_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1576
    struct sc_pkcs15_object *obj)
1577
0
{
1578
0
  struct sc_context *ctx = p15card->card->ctx;
1579
0
  struct sc_file *info_file=NULL, *obj_file=NULL;
1580
0
  struct awp_data_info idata;
1581
0
  struct sc_path path;
1582
0
  unsigned obj_id, obj_type = obj->auth_id.len ? COSM_TYPE_PRIVDATA_OBJECT : SC_PKCS15_TYPE_DATA_OBJECT;
1583
0
  int rv;
1584
1585
0
  LOG_FUNC_CALLED(ctx);
1586
0
  memset(&idata, 0, sizeof(idata));
1587
1588
0
  path = ((struct sc_pkcs15_data_info *)obj->data)->path;
1589
0
  obj_id = (path.value[path.len-1] & 0xFF) + (path.value[path.len-2] & 0xFF) * 0x100;
1590
1591
0
  rv = awp_new_file(p15card, profile, obj_type, obj_id & 0xFF, &info_file, &obj_file);
1592
0
  LOG_TEST_GOTO_ERR(ctx, rv, "COSM new file error");
1593
1594
0
  rv = awp_encode_data_info(p15card, obj, &idata);
1595
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot encode info");
1596
1597
0
  rv = awp_set_data_info(p15card, profile, info_file, &idata);
1598
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot set info");
1599
1600
0
  rv = awp_update_object_list(p15card, profile, obj_type, obj_id & 0xFF);
1601
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'Create Data' update DF failed: cannot update list");
1602
1603
0
err:
1604
0
  awp_free_data_info(&idata);
1605
0
  sc_file_free(info_file);
1606
0
  sc_file_free(obj_file);
1607
1608
0
  LOG_FUNC_RETURN(ctx, rv);
1609
0
}
1610
1611
1612
int
1613
awp_update_df_create(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1614
    struct sc_pkcs15_object *object)
1615
0
{
1616
0
  struct sc_context *ctx = p15card->card->ctx;
1617
0
  int rv = SC_ERROR_INTERNAL;
1618
1619
0
  LOG_FUNC_CALLED(ctx);
1620
0
  if (!object)
1621
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1622
1623
0
  switch (object->type)   {
1624
0
  case SC_PKCS15_TYPE_AUTH_PIN:
1625
0
    rv = awp_update_df_create_pin(p15card, profile, object);
1626
0
    break;
1627
0
  case SC_PKCS15_TYPE_CERT_X509:
1628
0
    rv = awp_update_df_create_cert(p15card, profile, object);
1629
0
    break;
1630
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1631
0
    rv = awp_update_df_create_prvkey(p15card, profile, object);
1632
0
    break;
1633
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1634
0
    rv = awp_update_df_create_pubkey(p15card, profile, object);
1635
0
    break;
1636
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1637
0
    rv = awp_update_df_create_data(p15card, profile, object);
1638
0
    break;
1639
0
  default:
1640
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type");
1641
0
  }
1642
1643
0
  LOG_FUNC_RETURN(ctx, rv);
1644
0
}
1645
1646
1647
static int
1648
awp_delete_from_container(struct sc_pkcs15_card *p15card,
1649
    struct sc_profile *profile, int type, int file_id)
1650
0
{
1651
0
  struct sc_context *ctx = p15card->card->ctx;
1652
0
  struct sc_file *clist=NULL, *file=NULL;
1653
0
  unsigned rec, rec_len;
1654
0
  int rv = 0, ii;
1655
0
  unsigned char *buff=NULL;
1656
1657
0
  LOG_FUNC_CALLED(ctx);
1658
0
  sc_log(ctx,  "update container entry (type:%X,file-id:%X)", type, file_id);
1659
1660
0
  rv = awp_new_file(p15card, profile, COSM_CONTAINER_LIST, 0, &clist, NULL);
1661
0
  LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot get allocate AWP file");
1662
1663
0
  rv = sc_select_file(p15card->card, &clist->path, &file);
1664
0
  LOG_TEST_RET(ctx, rv, "AWP update container entry: cannot select container list file");
1665
1666
0
  buff = malloc(file->record_length);
1667
0
  if (!buff)
1668
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update container entry: allocation error");
1669
1670
0
  for (rec = 1; rec <= (unsigned)file->record_count; rec++)   {
1671
0
    rv = sc_read_record(p15card->card, rec, 0, buff, file->record_length, SC_RECORD_BY_REC_NR);
1672
0
    if (rv < 0)   {
1673
0
      sc_log(ctx,  "AWP update container entry: read record error %i", rv);
1674
0
      break;
1675
0
    }
1676
0
    rec_len = rv;
1677
1678
0
    for (ii=0; ii<12; ii+=2)
1679
0
      if (file_id == (*(buff+ii) * 0x100 + *(buff+ii+1)))
1680
0
        break;
1681
0
    if (ii==12)
1682
0
      continue;
1683
1684
0
    if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == COSM_TYPE_PRKEY_RSA)
1685
0
      memset(buff + ii/6*6, 0, 6);
1686
0
    else
1687
0
      memset(buff + ii, 0, 2);
1688
1689
0
    if (!memcmp(buff,"\0\0\0\0\0\0\0\0\0\0\0\0",12))   {
1690
0
      rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_ERASE);
1691
0
      if (rv < 0)   {
1692
0
        sc_log(ctx,  "AWP update container entry: 'erase' authentication error %i", rv);
1693
0
        break;
1694
0
      }
1695
1696
0
      rv = sc_delete_record(p15card->card, rec);
1697
0
      if (rv < 0)   {
1698
0
        sc_log(ctx,  "AWP update container entry: delete record error %i", rv);
1699
0
        break;
1700
0
      }
1701
0
    }
1702
0
    else   {
1703
0
      rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
1704
0
      if (rv < 0)   {
1705
0
        sc_log(ctx,  "AWP update container entry: 'update' authentication error %i", rv);
1706
0
        break;
1707
0
      }
1708
1709
0
      rv = sc_update_record(p15card->card, rec, 0, buff, rec_len, SC_RECORD_BY_REC_NR);
1710
0
      if (rv < 0)   {
1711
0
        sc_log(ctx,  "AWP update container entry: update record error %i", rv);
1712
0
        break;
1713
0
      }
1714
0
    }
1715
0
  }
1716
1717
0
  if (rv > 0)
1718
0
    rv = 0;
1719
1720
0
  free(buff);
1721
0
  sc_file_free(clist);
1722
0
  sc_file_free(file);
1723
1724
0
  LOG_FUNC_RETURN(ctx, rv);
1725
0
}
1726
1727
1728
static int
1729
awp_remove_from_object_list( struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1730
    int type, unsigned int obj_id)
1731
0
{
1732
0
  struct sc_context *ctx = p15card->card->ctx;
1733
0
  struct sc_file *lst_file=NULL, *lst=NULL;
1734
0
  int rv = 0;
1735
0
  unsigned ii;
1736
0
  char lst_name[NAME_MAX_LEN];
1737
0
  unsigned char *buff=NULL;
1738
0
  unsigned char id[2];
1739
1740
0
  LOG_FUNC_CALLED(ctx);
1741
0
  sc_log(ctx,  "type %X; obj_id %X",type, obj_id);
1742
1743
0
  switch (type)   {
1744
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1745
0
  case COSM_TYPE_PRKEY_RSA:
1746
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-private-list", COSM_TITLE);
1747
0
    break;
1748
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1749
0
  case SC_PKCS15_TYPE_CERT_X509:
1750
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1751
0
  case COSM_TYPE_PUBKEY_RSA:
1752
0
    snprintf(lst_name, NAME_MAX_LEN,"%s-public-list", COSM_TITLE);
1753
0
    break;
1754
0
  default:
1755
0
    LOG_TEST_RET(ctx, SC_ERROR_INCORRECT_PARAMETERS, "AWP update object list: invalid type");
1756
0
  }
1757
1758
0
  sc_log(ctx,  "AWP update object list: select '%s' file", lst_name);
1759
0
  rv = sc_profile_get_file(profile, lst_name, &lst_file);
1760
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: cannot instantiate list file");
1761
1762
0
  rv = sc_select_file(p15card->card, &lst_file->path, &lst);
1763
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: cannot select list file");
1764
1765
0
  rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_READ);
1766
0
  LOG_TEST_RET(ctx, rv, "AWP update object list: 'read' authentication failed");
1767
1768
0
  buff = malloc(lst->size);
1769
0
  if (!buff)
1770
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "AWP update object list: allocation error");
1771
1772
0
  rv = sc_read_binary(p15card->card, 0, buff, lst->size, 0);
1773
0
  if (rv != (int)lst->size)
1774
0
    goto done;
1775
1776
0
  id[0] = (obj_id >> 8) & 0xFF;
1777
0
  id[1] = obj_id & 0xFF;
1778
0
  for (ii=0; ii<lst->size; ii+=5)   {
1779
0
    if (*(buff+ii)==0xFF && *(buff+ii+1)==id[0] && *(buff+ii+2)==id[1])   {
1780
0
      rv = sc_pkcs15init_authenticate(profile, p15card, lst, SC_AC_OP_UPDATE);
1781
0
      if (rv)
1782
0
        goto done;
1783
1784
0
      rv = sc_update_binary(p15card->card, ii, (unsigned char *)"\0", 1, 0);
1785
0
      if (rv && rv!=1)
1786
0
        rv = SC_ERROR_INVALID_CARD;
1787
0
      break;
1788
0
    }
1789
0
  }
1790
1791
0
  if (rv > 0)
1792
0
    rv = 0;
1793
0
done:
1794
0
  if (buff)
1795
0
    free(buff);
1796
0
  sc_file_free(lst);
1797
0
  sc_file_free(lst_file);
1798
1799
0
  LOG_FUNC_RETURN(ctx, rv);
1800
0
}
1801
1802
1803
static int
1804
awp_update_df_delete_cert(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1805
    struct sc_pkcs15_object *obj)
1806
0
{
1807
0
  struct sc_context *ctx = p15card->card->ctx;
1808
0
  struct sc_file *info_file = NULL;
1809
0
  struct sc_path path;
1810
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1811
0
  unsigned file_id;
1812
1813
0
  LOG_FUNC_CALLED(ctx);
1814
1815
0
  path = ((struct sc_pkcs15_cert_info *) obj->data)->path;
1816
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1817
0
  sc_log(ctx,  "file-id:%X", file_id);
1818
1819
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1820
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot get allocate new AWP file");
1821
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1822
1823
0
  rv = cosm_delete_file(p15card, profile, info_file);
1824
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1825
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: delete info file error");
1826
1827
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1828
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot update container");
1829
1830
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1831
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete cert' update DF failed: cannot remove object");
1832
1833
0
  LOG_FUNC_RETURN(ctx, rv);
1834
0
}
1835
1836
1837
static int
1838
awp_update_df_delete_prvkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1839
    struct sc_pkcs15_object *obj)
1840
0
{
1841
0
  struct sc_context *ctx = p15card->card->ctx;
1842
0
  struct sc_file *info_file = NULL;
1843
0
  struct sc_path path;
1844
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1845
0
  unsigned file_id;
1846
1847
0
  LOG_FUNC_CALLED(ctx);
1848
1849
0
  path = ((struct sc_pkcs15_prkey_info *) obj->data)->path;
1850
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1851
0
  sc_log(ctx,  "file-id:%X", file_id);
1852
1853
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1854
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot get allocate new AWP file");
1855
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1856
1857
0
  rv = cosm_delete_file(p15card, profile, info_file);
1858
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1859
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: delete info file error");
1860
1861
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1862
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot update container");
1863
1864
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1865
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete prkey' update DF failed: cannot remove object");
1866
1867
0
  LOG_FUNC_RETURN(ctx, rv);
1868
0
}
1869
1870
1871
static int
1872
awp_update_df_delete_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1873
    struct sc_pkcs15_object *obj)
1874
0
{
1875
0
  struct sc_context *ctx = p15card->card->ctx;
1876
0
  struct sc_file *info_file = NULL;
1877
0
  struct sc_path path;
1878
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1879
0
  unsigned file_id;
1880
1881
0
  LOG_FUNC_CALLED(ctx);
1882
1883
0
  path = ((struct sc_pkcs15_pubkey_info *) obj->data)->path;
1884
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1885
0
  sc_log(ctx,  "file-id:%X", file_id);
1886
1887
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1888
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot get allocate new AWP file");
1889
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1890
1891
0
  rv = cosm_delete_file(p15card, profile, info_file);
1892
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1893
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: delete info file error");
1894
1895
0
  rv = awp_delete_from_container(p15card, profile, obj->type, file_id);
1896
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot update container");
1897
1898
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1899
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete pubkey' update DF failed: cannot remove object");
1900
1901
0
  LOG_FUNC_RETURN(ctx, rv);
1902
0
}
1903
1904
1905
static int
1906
awp_update_df_delete_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1907
    struct sc_pkcs15_object *obj)
1908
0
{
1909
0
  struct sc_context *ctx = p15card->card->ctx;
1910
0
  struct sc_file *info_file = NULL;
1911
0
  struct sc_path path;
1912
0
  int rv = SC_ERROR_NOT_SUPPORTED;
1913
0
  unsigned file_id;
1914
1915
0
  LOG_FUNC_CALLED(ctx);
1916
1917
0
  path = ((struct sc_pkcs15_data_info *) obj->data)->path;
1918
0
  file_id = path.value[path.len-2] * 0x100 + path.value[path.len-1];
1919
0
  sc_log(ctx,  "file-id:%X", file_id);
1920
1921
0
  rv = awp_new_file(p15card, profile, obj->type, file_id & 0xFF, &info_file, NULL);
1922
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot get allocate new AWP file");
1923
0
  sc_log(ctx,  "info file-id:%X", info_file->id);
1924
1925
0
  rv = cosm_delete_file(p15card, profile, info_file);
1926
0
  if (rv != SC_ERROR_FILE_NOT_FOUND)
1927
0
    LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: delete info file error");
1928
1929
0
  rv = awp_remove_from_object_list(p15card, profile, obj->type, file_id);
1930
0
  LOG_TEST_RET(ctx, rv, "AWP 'delete DATA' update DF failed: cannot remove object");
1931
1932
0
  LOG_FUNC_RETURN(ctx, rv);
1933
0
}
1934
1935
1936
int
1937
awp_update_df_delete(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
1938
    struct sc_pkcs15_object *object)
1939
0
{
1940
0
  struct sc_context *ctx = p15card->card->ctx;
1941
0
  int rv = SC_ERROR_INTERNAL;
1942
1943
0
  LOG_FUNC_CALLED(ctx);
1944
0
  if (!object)
1945
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
1946
1947
0
  switch (object->type)   {
1948
0
  case SC_PKCS15_TYPE_CERT_X509:
1949
0
    rv = awp_update_df_delete_cert(p15card, profile, object);
1950
0
    break;
1951
0
  case SC_PKCS15_TYPE_PRKEY_RSA:
1952
0
    rv = awp_update_df_delete_prvkey(p15card, profile, object);
1953
0
    break;
1954
0
  case SC_PKCS15_TYPE_PUBKEY_RSA:
1955
0
    rv = awp_update_df_delete_pubkey(p15card, profile, object);
1956
0
    break;
1957
0
  case SC_PKCS15_TYPE_DATA_OBJECT:
1958
0
    rv = awp_update_df_delete_data(p15card, profile, object);
1959
0
    break;
1960
0
  default:
1961
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "'Create' update DF failed: unsupported object type");
1962
0
  }
1963
1964
0
  SC_FUNC_RETURN(ctx, 1, rv);
1965
0
}
1966
1967
#endif /* #ifdef ENABLE_OPENSSL */