Coverage Report

Created: 2026-10-17 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/pkcs15init/pkcs15-authentic.c
Line
Count
Source
1
/*
2
 * Specific operations for PKCS #15 initialization of the Oberthur's card
3
 *  COSMO v7 with applet AuthentIC v3 .
4
 *
5
 * Copyright (C) 2002  Juha Yrjölä <juha.yrjola@iki.fi>
6
 * Copyright (C) 2010  Viktor Tarasov <vtarasov@opentrust.com>
7
 *                      OpenTrust <www.opentrust.com>
8
 *
9
 * This library is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU Lesser General Public
11
 * License as published by the Free Software Foundation; either
12
 * version 2.1 of the License, or (at your option) any later version.
13
 *
14
 * This library is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
 * Lesser General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Lesser General Public
20
 * License along with this library; if not, write to the Free Software
21
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22
 */
23
24
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
27
#endif
28
29
#ifdef ENABLE_OPENSSL   /* empty file without openssl */
30
#include <stdlib.h>
31
#include <string.h>
32
#include <sys/types.h>
33
#include <ctype.h>
34
#include <errno.h>
35
#include <stdio.h>
36
37
#include "libopensc/opensc.h"
38
#include "libopensc/cardctl.h"
39
#include "libopensc/log.h"
40
#include "libopensc/pkcs15.h"
41
#include "libopensc/cards.h"
42
#include "libopensc/authentic.h"
43
44
#include "pkcs15-init.h"
45
#include "profile.h"
46
47
0
#define AUTHENTIC_CACHE_TIMESTAMP_PATH "3F0050159999"
48
49
unsigned char authentic_v3_rsa_mechs[5] = {
50
  AUTHENTIC_MECH_CRYPTO_RSA1024,
51
  AUTHENTIC_MECH_CRYPTO_RSA1280,
52
  AUTHENTIC_MECH_CRYPTO_RSA1536,
53
  AUTHENTIC_MECH_CRYPTO_RSA1792,
54
  AUTHENTIC_MECH_CRYPTO_RSA2048
55
};
56
57
unsigned char authentic_v3_rsa_ac_ops[6] = {
58
  SC_AC_OP_UPDATE,
59
  SC_AC_OP_DELETE,
60
  SC_AC_OP_PSO_DECRYPT,
61
  SC_AC_OP_PSO_COMPUTE_SIGNATURE,
62
  SC_AC_OP_INTERNAL_AUTHENTICATE,
63
  SC_AC_OP_GENERATE
64
};
65
66
struct authentic_ac_access_usage {
67
  unsigned ac_op;
68
  unsigned access_rule;
69
  unsigned usage;
70
};
71
struct authentic_ac_access_usage authentic_v3_rsa_map_attributes[7]  = {
72
  {SC_AC_OP_UPDATE, SC_PKCS15_ACCESS_RULE_MODE_UPDATE, 0},
73
  {SC_AC_OP_DELETE, SC_PKCS15_ACCESS_RULE_MODE_DELETE, 0},
74
  {SC_AC_OP_PSO_DECRYPT, SC_PKCS15_ACCESS_RULE_MODE_PSO_DECRYPT,
75
      SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP},
76
  {SC_AC_OP_PSO_COMPUTE_SIGNATURE, SC_PKCS15_ACCESS_RULE_MODE_PSO_CDS,
77
      SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION},
78
  {SC_AC_OP_INTERNAL_AUTHENTICATE, SC_PKCS15_ACCESS_RULE_MODE_INT_AUTH,
79
      SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER},
80
  {SC_AC_OP_GENERATE, SC_PKCS15_ACCESS_RULE_MODE_EXECUTE, 0},
81
  {0, 0, 0}
82
};
83
84
int authentic_pkcs15_delete_file(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_file *df);
85
86
static void
87
authentic_reference_to_pkcs15_id (unsigned int ref, struct sc_pkcs15_id *id)
88
0
{
89
0
  unsigned ii, sz;
90
91
0
  for (ii=0, sz = 0; ii<sizeof(unsigned int); ii++)
92
0
    if (ref >> 8*ii)
93
0
      sz++;
94
95
0
  for (ii=0; ii < sz; ii++)
96
0
    id->value[sz - ii - 1] = (ref >> 8*ii) & 0xFF;
97
98
0
  id->len = sz;
99
0
}
100
101
102
int
103
authentic_pkcs15_delete_file(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
104
    struct sc_file *df)
105
0
{
106
0
  struct sc_context *ctx = p15card->card->ctx;
107
0
  struct sc_card *card = p15card->card;
108
0
  struct sc_path  path;
109
0
  unsigned long caps = card->caps;
110
0
  int rv = 0;
111
112
0
  LOG_FUNC_CALLED(ctx);
113
0
  sc_log(ctx, "delete file(id:%04X)", df->id);
114
115
0
  card->caps |= SC_CARD_CAP_USE_FCI_AC;
116
0
  rv = sc_pkcs15init_authenticate(profile, p15card, df, SC_AC_OP_DELETE);
117
0
  card->caps = caps;
118
119
0
  LOG_TEST_RET(ctx, rv, "'DELETE' authentication failed");
120
121
0
  memset(&path, 0, sizeof(path));
122
0
  path.type = SC_PATH_TYPE_FILE_ID;
123
0
  path.value[0] = df->id >> 8;
124
0
  path.value[1] = df->id & 0xFF;
125
0
  path.len = 2;
126
127
0
  rv = sc_delete_file(card, &path);
128
0
  LOG_FUNC_RETURN(ctx, rv);
129
0
}
130
131
132
/*
133
 * Erase the card
134
 *
135
 */
136
static int
137
authentic_pkcs15_erase_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
138
0
{
139
0
  struct sc_context *ctx = p15card->card->ctx;
140
0
  struct sc_file  *file = NULL;
141
0
  struct sc_pkcs15_df *df;
142
0
  int rv;
143
144
0
  LOG_FUNC_CALLED(ctx);
145
146
0
  if (p15card->file_odf)   {
147
0
    sc_log(ctx, "Select ODF path: %s", sc_print_path(&p15card->file_odf->path));
148
0
    rv = sc_select_file(p15card->card, &p15card->file_odf->path, NULL);
149
0
    LOG_TEST_RET(ctx, rv, "Erase application error: cannot select ODF path");
150
0
  }
151
152
0
  for (df = p15card->df_list; df; df = df->next)   {
153
0
    struct sc_pkcs15_object *objs[32];
154
0
    unsigned obj_type = 0;
155
0
    int ii;
156
157
0
    if (df->type == SC_PKCS15_PRKDF)
158
0
      obj_type = SC_PKCS15_TYPE_PRKEY;
159
0
    else if (df->type == SC_PKCS15_PUKDF)
160
0
      obj_type = SC_PKCS15_TYPE_PUBKEY;
161
0
    else if (df->type == SC_PKCS15_CDF)
162
0
      obj_type = SC_PKCS15_TYPE_CERT;
163
0
    else if (df->type == SC_PKCS15_DODF)
164
0
      obj_type = SC_PKCS15_TYPE_DATA_OBJECT;
165
0
    else
166
0
      continue;
167
168
0
    if (df->enumerated)   {
169
0
      rv = sc_pkcs15_get_objects(p15card, obj_type, objs, 32);
170
0
      LOG_TEST_RET(ctx, rv, "Failed to get PKCS#15 objects to remove");
171
172
0
      for (ii=0; ii<rv; ii++) {
173
0
        sc_pkcs15_remove_object(p15card, objs[ii]);
174
0
        sc_pkcs15_free_object(objs[ii]);
175
0
      }
176
0
    }
177
178
0
    rv = sc_select_file(p15card->card, &df->path, &file);
179
0
    if (rv == SC_ERROR_FILE_NOT_FOUND)
180
0
      continue;
181
0
    LOG_TEST_RET(ctx, rv, "Cannot select object data file");
182
183
0
    rv = sc_erase_binary(p15card->card, 0, file->size, 0);
184
0
    if (rv == SC_ERROR_SECURITY_STATUS_NOT_SATISFIED)   {
185
0
      rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_UPDATE);
186
0
      if (rv < 0)
187
0
        sc_file_free(file);
188
189
0
      LOG_TEST_RET(ctx, rv, "'UPDATE' authentication failed");
190
191
0
      rv = sc_erase_binary(p15card->card, 0, file->size, 0);
192
0
    }
193
194
0
    sc_file_free(file);
195
0
    LOG_TEST_RET(ctx, rv, "Binary erase error");
196
197
0
    profile->dirty = 1;
198
0
  }
199
200
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
201
0
}
202
203
204
/*
205
 * Allocate a file
206
 */
207
static int
208
authentic_pkcs15_new_file(struct sc_profile *profile, struct sc_card *card,
209
    unsigned int type, unsigned int num, struct sc_file **out)
210
0
{
211
0
  struct sc_context *ctx = card->ctx;
212
0
  struct sc_file  *file = NULL;
213
0
  const char *t_name = NULL;
214
0
  int rv;
215
216
0
  LOG_FUNC_CALLED(ctx);
217
0
  sc_log(ctx, "type %X; num %i", type, num);
218
0
  switch (type) {
219
0
    case SC_PKCS15_TYPE_PRKEY_RSA:
220
0
      t_name = "template-private-key";
221
0
      break;
222
0
    case SC_PKCS15_TYPE_PUBKEY_RSA:
223
0
      t_name = "template-public-key";
224
0
      break;
225
0
    case SC_PKCS15_TYPE_CERT:
226
0
      t_name = "template-certificate";
227
0
      break;
228
0
    case SC_PKCS15_TYPE_DATA_OBJECT:
229
0
      t_name = "template-public-data";
230
0
      break;
231
0
    default:
232
0
      LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Profile template not supported");
233
0
  }
234
235
0
  sc_log(ctx, "df_info path '%s'", sc_print_path(&profile->df_info->file->path));
236
0
  rv = sc_profile_get_file(profile, t_name, &file);
237
0
  LOG_TEST_RET(ctx, rv, "Error when getting file from template");
238
239
0
  sc_log(ctx, "file(type:%X), path(type:%X,path:%s)", file->type, file->path.type, sc_print_path(&file->path));
240
241
0
  file->id = (file->id & 0xFF00) | (num & 0xFF);
242
0
  if (file->type != SC_FILE_TYPE_BSO)   {
243
0
    if (file->path.len == 0)   {
244
0
      file->path.type = SC_PATH_TYPE_FILE_ID;
245
0
      file->path.len = 2;
246
0
    }
247
0
    file->path.value[file->path.len - 2] = (file->id >> 8) & 0xFF;
248
0
    file->path.value[file->path.len - 1] = file->id & 0xFF;
249
0
    file->path.count = -1;
250
0
  }
251
252
0
  sc_log(ctx, "file(size:%zu,type:%i/%i,id:%04X), path(type:%X,'%s')", file->size, file->type,
253
0
      file->ef_structure, file->id, file->path.type, sc_print_path(&file->path));
254
0
  if (out)
255
0
    *out = file;
256
0
  else
257
0
    sc_file_free(file);
258
259
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
260
0
}
261
262
263
/*
264
 * Select a key reference
265
 */
266
static int
267
authentic_pkcs15_select_key_reference(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
268
    struct sc_pkcs15_prkey_info *key_info)
269
0
{
270
0
  struct sc_context *ctx = p15card->card->ctx;
271
272
0
  LOG_FUNC_CALLED(ctx);
273
274
  /* In authentic PKCS#15 all crypto objects are locals */
275
0
  key_info->key_reference |= AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
276
277
0
  if (key_info->key_reference > AUTHENTIC_V3_CRYPTO_OBJECT_REF_MAX)
278
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
279
280
0
  if (key_info->key_reference < AUTHENTIC_V3_CRYPTO_OBJECT_REF_MIN)
281
0
    key_info->key_reference = AUTHENTIC_V3_CRYPTO_OBJECT_REF_MIN;
282
283
0
  sc_log(ctx, "returns key reference %i", key_info->key_reference);
284
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
285
0
}
286
287
288
static int
289
authentic_docp_set_acls(struct sc_card *card, struct sc_file *file,
290
    unsigned char *ops, size_t ops_len,
291
    struct sc_authentic_sdo_docp *docp)
292
0
{
293
0
  struct sc_context *ctx = card->ctx;
294
0
  unsigned ii, offs;
295
296
0
  LOG_FUNC_CALLED(ctx);
297
0
  if (ops_len > sizeof(docp->acl_data) / 2)
298
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
299
300
0
  for (ii=0, offs=0; ii<ops_len; ii++)   {
301
0
    const struct sc_acl_entry *entry;
302
303
0
    entry = sc_file_get_acl_entry(file, *(ops + ii));
304
0
    if (entry->method == SC_AC_NEVER)   {
305
0
      docp->acl_data[offs++] = 0x00;
306
0
      docp->acl_data[offs++] = 0x00;
307
0
    }
308
0
    else if (entry->method == SC_AC_NONE)   {
309
0
      docp->acl_data[offs++] = 0x00;
310
0
      docp->acl_data[offs++] = 0x00;
311
0
    }
312
0
    else if (entry->method == SC_AC_CHV)   {
313
0
      if (!(entry->key_ref & AUTHENTIC_V3_CREDENTIAL_ID_MASK)
314
0
          || (entry->key_ref & ~AUTHENTIC_V3_CREDENTIAL_ID_MASK))
315
0
        LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non supported Credential Reference");
316
317
0
      docp->acl_data[offs++] = 0x00;
318
0
      docp->acl_data[offs++] = 0x01 << (entry->key_ref - 1);
319
0
    }
320
0
  }
321
322
0
  docp->acl_data_len = offs;
323
0
  LOG_FUNC_RETURN(ctx, offs);
324
0
}
325
326
327
static int
328
authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card,
329
    struct sc_pkcs15_prkey_info *key_info, struct sc_authentic_sdo **out)
330
0
{
331
0
  struct sc_context *ctx = card->ctx;
332
0
  struct sc_authentic_sdo *sdo = NULL;
333
0
  struct sc_file *file = NULL;
334
0
  int rv;
335
336
0
  LOG_FUNC_CALLED(ctx);
337
338
0
  if (!out)
339
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
340
341
0
  if ((key_info->modulus_length % 256) || key_info->modulus_length < 1024 || key_info->modulus_length > 2048)
342
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
343
344
0
  rv = authentic_pkcs15_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
345
0
  LOG_TEST_RET(ctx, rv, "Cannot instantiate new PRKEY-RSA file");
346
347
0
  sdo = calloc(1, sizeof(struct sc_authentic_sdo));
348
0
  if (!sdo) {
349
0
    sc_file_free(file);
350
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate 'sc_authentic_sdo'");
351
0
  }
352
353
0
  sdo->magic = AUTHENTIC_SDO_MAGIC;
354
0
  sdo->docp.id = key_info->key_reference &  ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
355
0
  sdo->docp.mech = authentic_v3_rsa_mechs[(key_info->modulus_length - 1024) / 256];
356
357
0
  rv = authentic_docp_set_acls(card, file, authentic_v3_rsa_ac_ops,
358
0
      sizeof(authentic_v3_rsa_ac_ops)/sizeof(authentic_v3_rsa_ac_ops[0]), &sdo->docp);
359
0
  sc_file_free(file);
360
0
  if (rv != SC_SUCCESS) {
361
0
    free(sdo);
362
0
    sc_log(ctx, "Cannot set key ACLs from file");
363
0
    LOG_FUNC_RETURN(ctx, rv);
364
0
  }
365
366
0
  sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id,
367
0
      sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len));
368
369
0
  *out = sdo;
370
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
371
0
}
372
373
374
static int
375
authentic_pkcs15_add_access_rule(struct sc_pkcs15_object *object, unsigned access_mode, struct sc_pkcs15_id *auth_id)
376
0
{
377
0
  int ii;
378
379
0
  for (ii=0;ii<SC_PKCS15_MAX_ACCESS_RULES;ii++)   {
380
0
    if (!object->access_rules[ii].access_mode)   {
381
0
      object->access_rules[ii].access_mode = access_mode;
382
0
      if (auth_id)
383
0
        object->access_rules[ii].auth_id = *auth_id;
384
0
      else
385
0
        object->access_rules[ii].auth_id.len = 0;
386
0
      break;
387
0
    }
388
0
    else if (!auth_id && !object->access_rules[ii].auth_id.len)   {
389
0
      object->access_rules[ii].access_mode |= access_mode;
390
0
      break;
391
0
    }
392
0
    else if (auth_id && sc_pkcs15_compare_id(&object->access_rules[ii].auth_id, auth_id))   {
393
0
      object->access_rules[ii].access_mode |= access_mode;
394
0
      break;
395
0
    }
396
0
  }
397
398
0
  if (ii==SC_PKCS15_MAX_ACCESS_RULES)
399
0
    return SC_ERROR_TOO_MANY_OBJECTS;
400
401
0
  return SC_SUCCESS;
402
0
}
403
404
405
static int
406
authentic_pkcs15_fix_file_access_rule(struct sc_pkcs15_card *p15card, struct sc_file *file,
407
    unsigned ac_op, unsigned rule_mode, struct sc_pkcs15_object *object)
408
0
{
409
0
  struct sc_context *ctx = p15card->card->ctx;
410
0
  const struct sc_acl_entry *acl = NULL;
411
0
  struct sc_pkcs15_id id;
412
0
  unsigned ref;
413
0
  int rv;
414
415
0
  LOG_FUNC_CALLED(ctx);
416
0
  acl = sc_file_get_acl_entry(file, ac_op);
417
0
  sc_log(ctx, "Fix access rule(op:%i;mode:%i) with ACL(method:%X,ref:%X)",
418
0
      ac_op, rule_mode, acl->method, acl->key_ref);
419
0
  if (acl->method == SC_AC_NEVER)   {
420
0
    sc_log(ctx, "ignore access rule(op:%i,mode:%i)", ac_op, rule_mode);
421
0
  }
422
0
  else if (acl->method == SC_AC_NONE)   {
423
0
    rv = authentic_pkcs15_add_access_rule(object, rule_mode, NULL);
424
0
    LOG_TEST_RET(ctx, rv, "Fix file access rule error");
425
0
  }
426
0
  else   {
427
0
    sc_log(ctx, "ACL(method:%X,ref:%X)", acl->method, acl->key_ref);
428
0
    if (acl->method == SC_AC_CHV)   {
429
0
      ref = acl->key_ref;
430
0
      authentic_reference_to_pkcs15_id (ref, &id);
431
0
    }
432
0
    else   {
433
0
      LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Fix file access error");
434
0
    }
435
436
0
    sc_log(ctx, "ACL(method:%X,ref:%X)", acl->method, acl->key_ref);
437
0
    rv = authentic_pkcs15_add_access_rule(object, rule_mode, &id);
438
0
    sc_log(ctx, "rv %i", rv);
439
0
    LOG_TEST_RET(ctx, rv, "Fix file access rule error");
440
0
  }
441
442
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
443
0
}
444
445
446
static int
447
authentic_pkcs15_fix_access(struct sc_pkcs15_card *p15card, struct sc_file *file,
448
    struct sc_pkcs15_object *object)
449
0
{
450
0
  struct sc_context *ctx = p15card->card->ctx;
451
0
  int rv, ii;
452
453
0
  LOG_FUNC_CALLED(ctx);
454
0
  sc_log(ctx, "authID %s", sc_pkcs15_print_id(&object->auth_id));
455
456
0
  memset(object->access_rules, 0, sizeof(object->access_rules));
457
458
0
  for (ii=0; authentic_v3_rsa_map_attributes[ii].access_rule; ii++)   {
459
0
    rv = authentic_pkcs15_fix_file_access_rule(p15card, file,
460
0
        authentic_v3_rsa_map_attributes[ii].ac_op,
461
0
        authentic_v3_rsa_map_attributes[ii].access_rule,
462
0
        object);
463
0
    LOG_TEST_RET(ctx, rv, "Fix file READ access error");
464
0
  }
465
466
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
467
0
}
468
469
470
static int
471
authentic_pkcs15_fix_usage(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object)
472
0
{
473
0
  struct sc_context *ctx = p15card->card->ctx;
474
0
  int ii, jj;
475
476
0
  LOG_FUNC_CALLED(ctx);
477
0
  if (object->type == SC_PKCS15_TYPE_PRKEY_RSA)   {
478
0
    struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *) object->data;
479
480
0
    sc_log(ctx, "fix private key usage 0x%X", prkey_info->usage);
481
0
          for (ii=0;ii<SC_PKCS15_MAX_ACCESS_RULES;ii++)   {
482
0
      if (!object->access_rules[ii].access_mode)
483
0
        break;
484
485
0
      for (jj=0; authentic_v3_rsa_map_attributes[jj].access_rule; jj++)
486
0
        if (authentic_v3_rsa_map_attributes[jj].access_rule & object->access_rules[ii].access_mode)
487
0
          prkey_info->usage |= authentic_v3_rsa_map_attributes[jj].usage;
488
0
    }
489
0
    sc_log(ctx, "fixed private key usage 0x%X", prkey_info->usage);
490
0
  }
491
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
492
0
}
493
494
495
static void
496
authentic_free_sdo_data(struct sc_authentic_sdo *sdo)
497
0
{
498
0
  int rsa_mechs_num = sizeof(authentic_v3_rsa_mechs)/sizeof(authentic_v3_rsa_mechs[0]);
499
0
  int ii;
500
501
0
  if (!sdo)
502
0
    return;
503
504
0
  sc_file_free(sdo->file);
505
506
0
  for (ii=0; ii<rsa_mechs_num; ii++)
507
0
    if (sdo->docp.mech == authentic_v3_rsa_mechs[ii])
508
0
      break;
509
0
  if (ii<rsa_mechs_num)
510
0
    sc_pkcs15_free_prkey(sdo->data.prvkey);
511
0
}
512
513
514
static int
515
authentic_pkcs15_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
516
          struct sc_pkcs15_object *object)
517
0
{
518
0
  struct sc_card *card = p15card->card;
519
0
  struct sc_context *ctx = card->ctx;
520
0
  struct sc_authentic_sdo *sdo = NULL;
521
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
522
0
  struct sc_file  *file_p_prvkey = NULL, *parent = NULL;
523
0
  size_t keybits = key_info->modulus_length;
524
0
  int  rv;
525
526
0
  LOG_FUNC_CALLED(ctx);
527
0
  sc_log(ctx, "create private key(keybits:%zu,usage:%X,access:%X,ref:%X)",
528
0
      keybits, key_info->usage, key_info->access_flags, key_info->key_reference);
529
0
  if (keybits < 1024 || keybits > 2048 || (keybits % 256))
530
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
531
532
0
  rv = authentic_pkcs15_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file_p_prvkey);
533
0
  LOG_TEST_RET(ctx, rv, "IasEcc pkcs15 new PRKEY_RSA file error");
534
535
0
  key_info->key_reference |= AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
536
537
0
  rv = sc_select_file(card, &file_p_prvkey->path, &parent);
538
0
  if (rv != SC_SUCCESS)
539
0
    sc_file_free(file_p_prvkey);
540
0
  LOG_TEST_RET(ctx, rv, "DF for the private objects not defined");
541
542
0
  rv = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_CRYPTO);
543
0
  sc_file_free(parent);
544
0
  if (rv != SC_SUCCESS)
545
0
    sc_file_free(file_p_prvkey);
546
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_CRYPTO authentication failed for parent DF");
547
548
0
  key_info->access_flags = SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
549
0
    | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
550
0
    | SC_PKCS15_PRKEY_ACCESS_SENSITIVE;
551
552
0
  rv = authentic_sdo_allocate_prvkey(profile, card, key_info, &sdo);
553
0
  if (rv != SC_SUCCESS || sdo == NULL) {
554
0
    sc_log(ctx, "IasEcc: init SDO private key failed");
555
0
    sc_file_free(file_p_prvkey);
556
0
    LOG_FUNC_RETURN(ctx, rv);
557
0
  }
558
559
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_CREATE, sdo);
560
0
  if (rv == SC_ERROR_FILE_ALREADY_EXISTS)   {
561
0
    unsigned long caps = p15card->card->caps;
562
563
0
    p15card->card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
564
0
    rv = sc_pkcs15init_authenticate(profile, p15card, file_p_prvkey, SC_AC_OP_DELETE);
565
0
    p15card->card->caps = caps;
566
0
    LOG_TEST_GOTO_ERR(ctx, rv, "SC_AC_OP_CRYPTO authentication failed for parent DF");
567
568
0
    rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_DELETE, sdo);
569
0
    LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key");
570
571
0
    rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_CREATE, sdo);
572
0
  }
573
0
  LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_CREATE failed");
574
575
0
  rv = authentic_pkcs15_fix_access(p15card, file_p_prvkey, object);
576
0
  LOG_TEST_GOTO_ERR(ctx, rv, "cannot fix access rules for private key");
577
578
0
  rv = authentic_pkcs15_fix_usage(p15card, object);
579
0
  LOG_TEST_GOTO_ERR(ctx, rv, "cannot fix access rules for private key");
580
581
  /* Here fix the key's supported algorithms, if these ones will be implemented
582
   * (see src/libopensc/pkcs15-prkey.c).
583
   */
584
585
0
  sdo->file = file_p_prvkey;
586
0
  sc_log(ctx, "sdo->file:%p", sdo->file);
587
588
0
  rv = sc_pkcs15_allocate_object_content(ctx, object, (unsigned char *)sdo, sizeof(struct sc_authentic_sdo));
589
0
  LOG_TEST_GOTO_ERR(ctx, rv, "Failed to allocate PrvKey SDO as object content");
590
591
0
err:
592
0
  if (sdo == NULL || sdo->file != file_p_prvkey)
593
0
    sc_file_free(file_p_prvkey);
594
0
  authentic_free_sdo_data(sdo);
595
0
  free(sdo);
596
0
  LOG_FUNC_RETURN(ctx, rv);
597
0
}
598
599
600
/*
601
 * RSA key generation
602
 */
603
static int
604
authentic_pkcs15_generate_key(struct sc_profile *profile, sc_pkcs15_card_t *p15card,
605
    struct sc_pkcs15_object *object, struct sc_pkcs15_pubkey *pubkey)
606
0
{
607
0
  struct sc_card *card = p15card->card;
608
0
  struct sc_context *ctx = card->ctx;
609
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
610
0
  size_t keybits = key_info->modulus_length;
611
0
  struct sc_authentic_sdo *sdo = NULL;
612
0
  unsigned char *tmp = NULL;
613
0
  size_t tmp_len;
614
0
  unsigned long caps;
615
0
  int rv;
616
617
0
  LOG_FUNC_CALLED(ctx);
618
0
  sc_log(ctx, "generate key(bits:%zu,path:%s,AuthID:%s",
619
0
      keybits, sc_print_path(&key_info->path), sc_pkcs15_print_id(&object->auth_id));
620
621
0
  if (!object->content.value || object->content.len != sizeof(struct sc_authentic_sdo))
622
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid PrKey SDO data");
623
0
  else if (keybits < 1024 || keybits > 2048 || (keybits % 256))
624
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
625
626
0
  sdo = (struct sc_authentic_sdo *)object->content.value;
627
0
  if (sdo->magic != AUTHENTIC_SDO_MAGIC)
628
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "'Magic' control failed for SDO PrvKey");
629
630
0
  rv = sc_select_file(card, &key_info->path, NULL);
631
0
  LOG_TEST_RET(ctx, rv, "failed to select parent DF");
632
633
0
  caps = card->caps;
634
0
  card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
635
0
  rv = sc_pkcs15init_authenticate(profile, p15card, sdo->file, SC_AC_OP_GENERATE);
636
0
  card->caps = caps;
637
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_GENERATE authentication failed");
638
639
0
  key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_LOCAL;
640
641
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_GENERATE, sdo);
642
0
  LOG_TEST_RET(ctx, rv, "generate key failed");
643
644
0
  pubkey->algorithm = SC_ALGORITHM_RSA;
645
  //FIXME: allocate/copy/free to reduce memory leakage
646
0
  pubkey->u.rsa.modulus = sdo->data.prvkey->u.rsa.modulus;
647
0
  pubkey->u.rsa.exponent = sdo->data.prvkey->u.rsa.exponent;
648
0
  sdo->data.prvkey = NULL;
649
650
0
  rv = sc_pkcs15_encode_pubkey(ctx, pubkey, &tmp, &tmp_len);
651
0
  LOG_TEST_RET(ctx, rv, "encode public key failed");
652
653
  /*
654
   * Here algorithms supported by key have to be fixed, if it will be implemented
655
   * (see src/libopensc/pkcs15-prkey.c).
656
   */
657
658
0
  authentic_free_sdo_data(sdo);
659
660
0
  rv = sc_pkcs15_allocate_object_content(ctx, object, tmp, tmp_len);
661
0
  LOG_TEST_RET(ctx, rv, "Failed to allocate public key as object content");
662
663
0
  free(tmp);
664
0
  LOG_FUNC_RETURN(ctx, rv);
665
0
}
666
667
668
/*
669
 * Store a private key
670
 */
671
static int
672
authentic_pkcs15_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
673
    struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prvkey)
674
0
{
675
0
  struct sc_card *card = p15card->card;
676
0
  struct sc_context *ctx = card->ctx;
677
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
678
0
  size_t keybits = key_info->modulus_length;
679
0
  struct sc_authentic_sdo *sdo;
680
0
  int rv;
681
682
0
  LOG_FUNC_CALLED(ctx);
683
0
  sc_log(ctx, "Store IAS/ECC key(keybits:%zu,AuthID:%s,path:%s)",
684
0
      keybits, sc_pkcs15_print_id(&object->auth_id), sc_print_path(&key_info->path));
685
686
0
  if (!object->content.value || object->content.len != sizeof(struct sc_authentic_sdo))
687
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid PrKey SDO data");
688
0
  else if (keybits < 1024 || keybits > 2048 || (keybits % 256))
689
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
690
691
0
  key_info->access_flags &= ~SC_PKCS15_PRKEY_ACCESS_LOCAL;
692
693
0
  sdo = (struct sc_authentic_sdo *)object->content.value;
694
0
  if (sdo->magic != AUTHENTIC_SDO_MAGIC)
695
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "'Magic' control failed for SDO PrvKey");
696
697
0
  rv = sc_select_file(card, &key_info->path, NULL);
698
0
  LOG_TEST_RET(ctx, rv, "failed to select parent DF");
699
700
0
  sdo->data.prvkey = prvkey;
701
702
0
  sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id,
703
0
      sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len));
704
705
0
  card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
706
0
  rv = sc_pkcs15init_authenticate(profile, p15card, sdo->file, SC_AC_OP_UPDATE);
707
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_GENERATE authentication failed");
708
709
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_STORE, sdo);
710
0
  LOG_TEST_RET(ctx, rv, "store IAS SDO PRIVATE KEY failed");
711
712
0
  authentic_free_sdo_data(sdo);
713
0
  sc_pkcs15_free_object_content(object);
714
715
0
  LOG_FUNC_RETURN(ctx, rv);
716
0
}
717
718
719
static int
720
authentic_pkcs15_delete_rsa_sdo (struct sc_profile *profile, struct sc_pkcs15_card *p15card,
721
    struct sc_pkcs15_prkey_info *key_info)
722
0
{
723
0
  struct sc_context *ctx = p15card->card->ctx;
724
0
  unsigned long caps = p15card->card->caps;
725
0
  struct sc_authentic_sdo sdo;
726
0
  struct sc_file  *file = NULL;
727
0
  int rv;
728
729
0
  LOG_FUNC_CALLED(ctx);
730
0
  sc_log(ctx, "delete SDO RSA key (ref:%i,size:%zu)", key_info->key_reference, key_info->modulus_length);
731
732
0
  rv = authentic_pkcs15_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
733
0
  LOG_TEST_GOTO_ERR(ctx, rv, "PRKEY_RSA instantiation file error");
734
735
0
  p15card->card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
736
0
  rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE);
737
0
  p15card->card->caps = caps;
738
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'DELETE' authentication failed for parent RSA key");
739
740
0
  sdo.magic = AUTHENTIC_SDO_MAGIC;
741
0
  sdo.docp.id = key_info->key_reference & ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
742
0
  sdo.docp.mech = authentic_v3_rsa_mechs[(key_info->modulus_length - 1024) / 256];
743
744
0
  rv = sc_card_ctl(p15card->card, SC_CARDCTL_AUTHENTIC_SDO_DELETE, &sdo);
745
0
  if (rv == SC_ERROR_DATA_OBJECT_NOT_FOUND)
746
0
    rv = SC_SUCCESS;
747
0
  LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key");
748
749
0
err:
750
0
  sc_file_free(file);
751
0
  LOG_FUNC_RETURN(ctx, rv);
752
0
}
753
754
755
static int
756
authentic_pkcs15_delete_object (struct sc_profile *profile, struct sc_pkcs15_card *p15card,
757
    struct sc_pkcs15_object *object, const struct sc_path *path)
758
0
{
759
0
  struct sc_context *ctx = p15card->card->ctx;
760
0
  int rv;
761
762
0
  LOG_FUNC_CALLED(ctx);
763
0
  sc_log(ctx, "delete PKCS15 object: type %X; path %s\n", object->type, sc_print_path(path));
764
765
0
  switch(object->type & SC_PKCS15_TYPE_CLASS_MASK)   {
766
0
  case SC_PKCS15_TYPE_PRKEY:
767
0
    rv = authentic_pkcs15_delete_rsa_sdo (profile, p15card, (struct sc_pkcs15_prkey_info *)object->data);
768
0
    LOG_FUNC_RETURN(ctx, rv);
769
0
  case SC_PKCS15_TYPE_PUBKEY:
770
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
771
0
  default:
772
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
773
0
  }
774
775
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
776
0
}
777
778
779
static int
780
authentic_store_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_pkcs15_object *object,
781
    struct sc_pkcs15_der *data, struct sc_path *path)
782
0
{
783
0
  struct sc_context *ctx = p15card->card->ctx;
784
0
  struct sc_pkcs15_pubkey_info *pubkey_info = (struct sc_pkcs15_pubkey_info *)object->data;
785
0
  struct sc_pkcs15_prkey_info *prkey_info = NULL;
786
0
  struct sc_pkcs15_object *prkey_object = NULL;
787
0
  int rv;
788
789
0
  LOG_FUNC_CALLED(ctx);
790
0
  sc_log(ctx, "Public Key id '%s'", sc_pkcs15_print_id(&pubkey_info->id));
791
792
0
  rv = sc_pkcs15_find_prkey_by_id(p15card, &pubkey_info->id, &prkey_object);
793
0
  LOG_TEST_RET(ctx, rv, "Find related PrKey error");
794
795
0
  prkey_info = (struct sc_pkcs15_prkey_info *)prkey_object->data;
796
797
0
  pubkey_info->key_reference = prkey_info->key_reference;
798
799
0
  pubkey_info->access_flags = prkey_info->access_flags & SC_PKCS15_PRKEY_ACCESS_LOCAL;
800
0
  pubkey_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
801
802
0
  pubkey_info->native = 0;
803
804
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_SIGN ? SC_PKCS15_PRKEY_USAGE_VERIFY : 0;
805
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_SIGNRECOVER ? SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER : 0;
806
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_NONREPUDIATION ? SC_PKCS15_PRKEY_USAGE_VERIFY : 0;
807
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_DECRYPT ? SC_PKCS15_PRKEY_USAGE_ENCRYPT : 0;
808
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_UNWRAP ? SC_PKCS15_PRKEY_USAGE_WRAP : 0;
809
810
0
  authentic_pkcs15_add_access_rule(object, SC_PKCS15_ACCESS_RULE_MODE_READ, NULL);
811
812
  /* Here, if key supported algorithms will be implemented (see src/libopensc/pkcs15-prkey.c),
813
   * copy private key supported algorithms to the public key's ones.
814
   */
815
816
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
817
0
}
818
819
820
static int
821
authentic_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
822
    struct sc_pkcs15_object *object,
823
    struct sc_pkcs15_der *data, struct sc_path *path)
824
825
0
{
826
0
  struct sc_context *ctx = p15card->card->ctx;
827
0
  int rv = SC_ERROR_NOT_IMPLEMENTED;
828
829
0
  LOG_FUNC_CALLED(ctx);
830
831
0
  switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
832
0
  case SC_PKCS15_TYPE_PUBKEY:
833
0
    rv = authentic_store_pubkey(p15card, profile, object, data, path);
834
0
    break;
835
0
  }
836
837
0
  LOG_FUNC_RETURN(ctx, rv);
838
0
}
839
840
841
static int
842
authentic_emu_update_tokeninfo(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
843
    struct sc_pkcs15_tokeninfo *tinfo)
844
0
{
845
0
  struct sc_context *ctx = p15card->card->ctx;
846
0
  struct sc_file *file = NULL;
847
0
  struct sc_path path;
848
0
  unsigned char buffer[8];
849
0
  int rv;
850
0
  size_t len;
851
852
0
  sc_format_path(AUTHENTIC_CACHE_TIMESTAMP_PATH, &path);
853
0
  rv = sc_select_file(p15card->card, &path, &file);
854
0
  if (!rv) {
855
0
    rv = sc_get_challenge(p15card->card, buffer, sizeof(buffer));
856
0
    if (rv < 0) {
857
0
      sc_file_free(file);
858
0
      LOG_TEST_RET(ctx, rv, "Get challenge error");
859
0
    }
860
861
0
    len = file->size > sizeof(buffer) ? sizeof(buffer) : file->size;
862
0
    rv = sc_update_binary(p15card->card, 0, buffer, len, 0);
863
0
    sc_file_free(file);
864
0
    LOG_TEST_RET(ctx, rv, "Update binary error");
865
0
  }
866
867
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
868
0
}
869
870
static int
871
authentic_pkcs15_init_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
872
0
{
873
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
874
0
}
875
876
877
static int
878
authentic_pkcs15_create_dir(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
879
    struct sc_file *df)
880
0
{
881
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
882
0
}
883
884
885
static int
886
authentic_pkcs15_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
887
    struct sc_file *df, struct sc_pkcs15_object *pin_obj,
888
    const unsigned char *pin, size_t pin_len,
889
    const unsigned char *puk, size_t puk_len)
890
0
{
891
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
892
0
}
893
894
895
static struct sc_pkcs15init_operations
896
sc_pkcs15init_authentic_operations = {
897
  authentic_pkcs15_erase_card,
898
  authentic_pkcs15_init_card,
899
  authentic_pkcs15_create_dir,
900
  NULL,         /* create_domain */
901
  NULL,         /* select_pin_reference */
902
  authentic_pkcs15_create_pin,
903
  authentic_pkcs15_select_key_reference,
904
  authentic_pkcs15_create_key,
905
  authentic_pkcs15_store_key,
906
  authentic_pkcs15_generate_key,
907
  NULL,         /* encode private key */
908
  NULL,         /* encode public key */
909
  NULL,         /* finalize_card */
910
  authentic_pkcs15_delete_object,
911
912
  /* pkcs15init emulation */
913
  NULL,
914
  NULL,
915
  authentic_emu_update_tokeninfo,
916
  NULL,
917
  authentic_emu_store_data,
918
919
  NULL,         /* sanity_check */
920
};
921
922
923
struct sc_pkcs15init_operations *
924
sc_pkcs15init_get_authentic_ops(void)
925
16
{
926
16
  return &sc_pkcs15init_authentic_operations;
927
16
}
928
929
#endif /* ENABLE_OPENSSL */