Coverage Report

Created: 2026-03-01 06:54

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:%"SC_FORMAT_LEN_SIZE_T"u,type:%i/%i,id:%04X), path(type:%X,'%s')",
253
0
         file->size, file->type, file->ef_structure, file->id,
254
0
         file->path.type, sc_print_path(&file->path));
255
0
  if (out)
256
0
    *out = file;
257
0
  else
258
0
    sc_file_free(file);
259
260
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
261
0
}
262
263
264
/*
265
 * Select a key reference
266
 */
267
static int
268
authentic_pkcs15_select_key_reference(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
269
    struct sc_pkcs15_prkey_info *key_info)
270
0
{
271
0
  struct sc_context *ctx = p15card->card->ctx;
272
273
0
  LOG_FUNC_CALLED(ctx);
274
275
  /* In authentic PKCS#15 all crypto objects are locals */
276
0
  key_info->key_reference |= AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
277
278
0
  if (key_info->key_reference > AUTHENTIC_V3_CRYPTO_OBJECT_REF_MAX)
279
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
280
281
0
  if (key_info->key_reference < AUTHENTIC_V3_CRYPTO_OBJECT_REF_MIN)
282
0
    key_info->key_reference = AUTHENTIC_V3_CRYPTO_OBJECT_REF_MIN;
283
284
0
  sc_log(ctx, "returns key reference %i", key_info->key_reference);
285
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
286
0
}
287
288
289
static int
290
authentic_docp_set_acls(struct sc_card *card, struct sc_file *file,
291
    unsigned char *ops, size_t ops_len,
292
    struct sc_authentic_sdo_docp *docp)
293
0
{
294
0
  struct sc_context *ctx = card->ctx;
295
0
  unsigned ii, offs;
296
297
0
  LOG_FUNC_CALLED(ctx);
298
0
  if (ops_len > sizeof(docp->acl_data) / 2)
299
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
300
301
0
  for (ii=0, offs=0; ii<ops_len; ii++)   {
302
0
    const struct sc_acl_entry *entry;
303
304
0
    entry = sc_file_get_acl_entry(file, *(ops + ii));
305
0
    if (entry->method == SC_AC_NEVER)   {
306
0
      docp->acl_data[offs++] = 0x00;
307
0
      docp->acl_data[offs++] = 0x00;
308
0
    }
309
0
    else if (entry->method == SC_AC_NONE)   {
310
0
      docp->acl_data[offs++] = 0x00;
311
0
      docp->acl_data[offs++] = 0x00;
312
0
    }
313
0
    else if (entry->method == SC_AC_CHV)   {
314
0
      if (!(entry->key_ref & AUTHENTIC_V3_CREDENTIAL_ID_MASK)
315
0
          || (entry->key_ref & ~AUTHENTIC_V3_CREDENTIAL_ID_MASK))
316
0
        LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "Non supported Credential Reference");
317
318
0
      docp->acl_data[offs++] = 0x00;
319
0
      docp->acl_data[offs++] = 0x01 << (entry->key_ref - 1);
320
0
    }
321
0
  }
322
323
0
  docp->acl_data_len = offs;
324
0
  LOG_FUNC_RETURN(ctx, offs);
325
0
}
326
327
328
static int
329
authentic_sdo_allocate_prvkey(struct sc_profile *profile, struct sc_card *card,
330
    struct sc_pkcs15_prkey_info *key_info, struct sc_authentic_sdo **out)
331
0
{
332
0
  struct sc_context *ctx = card->ctx;
333
0
  struct sc_authentic_sdo *sdo = NULL;
334
0
  struct sc_file *file = NULL;
335
0
  int rv;
336
337
0
  LOG_FUNC_CALLED(ctx);
338
339
0
  if (!out)
340
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
341
342
0
  if ((key_info->modulus_length % 256) || key_info->modulus_length < 1024 || key_info->modulus_length > 2048)
343
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ARGUMENTS);
344
345
0
  rv = authentic_pkcs15_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
346
0
  LOG_TEST_RET(ctx, rv, "Cannot instantiate new PRKEY-RSA file");
347
348
0
  sdo = calloc(1, sizeof(struct sc_authentic_sdo));
349
0
  if (!sdo) {
350
0
    sc_file_free(file);
351
0
    LOG_TEST_RET(ctx, SC_ERROR_OUT_OF_MEMORY, "Cannot allocate 'sc_authentic_sdo'");
352
0
  }
353
354
0
  sdo->magic = AUTHENTIC_SDO_MAGIC;
355
0
  sdo->docp.id = key_info->key_reference &  ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
356
0
  sdo->docp.mech = authentic_v3_rsa_mechs[(key_info->modulus_length - 1024) / 256];
357
358
0
  rv = authentic_docp_set_acls(card, file, authentic_v3_rsa_ac_ops,
359
0
      sizeof(authentic_v3_rsa_ac_ops)/sizeof(authentic_v3_rsa_ac_ops[0]), &sdo->docp);
360
0
  sc_file_free(file);
361
0
  if (rv != SC_SUCCESS) {
362
0
    free(sdo);
363
0
    sc_log(ctx, "Cannot set key ACLs from file");
364
0
    LOG_FUNC_RETURN(ctx, rv);
365
0
  }
366
367
0
  sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id,
368
0
      sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len));
369
370
0
  *out = sdo;
371
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
372
0
}
373
374
375
static int
376
authentic_pkcs15_add_access_rule(struct sc_pkcs15_object *object, unsigned access_mode, struct sc_pkcs15_id *auth_id)
377
0
{
378
0
  int ii;
379
380
0
  for (ii=0;ii<SC_PKCS15_MAX_ACCESS_RULES;ii++)   {
381
0
    if (!object->access_rules[ii].access_mode)   {
382
0
      object->access_rules[ii].access_mode = access_mode;
383
0
      if (auth_id)
384
0
        object->access_rules[ii].auth_id = *auth_id;
385
0
      else
386
0
        object->access_rules[ii].auth_id.len = 0;
387
0
      break;
388
0
    }
389
0
    else if (!auth_id && !object->access_rules[ii].auth_id.len)   {
390
0
      object->access_rules[ii].access_mode |= access_mode;
391
0
      break;
392
0
    }
393
0
    else if (auth_id && sc_pkcs15_compare_id(&object->access_rules[ii].auth_id, auth_id))   {
394
0
      object->access_rules[ii].access_mode |= access_mode;
395
0
      break;
396
0
    }
397
0
  }
398
399
0
  if (ii==SC_PKCS15_MAX_ACCESS_RULES)
400
0
    return SC_ERROR_TOO_MANY_OBJECTS;
401
402
0
  return SC_SUCCESS;
403
0
}
404
405
406
static int
407
authentic_pkcs15_fix_file_access_rule(struct sc_pkcs15_card *p15card, struct sc_file *file,
408
    unsigned ac_op, unsigned rule_mode, struct sc_pkcs15_object *object)
409
0
{
410
0
  struct sc_context *ctx = p15card->card->ctx;
411
0
  const struct sc_acl_entry *acl = NULL;
412
0
  struct sc_pkcs15_id id;
413
0
  unsigned ref;
414
0
  int rv;
415
416
0
  LOG_FUNC_CALLED(ctx);
417
0
  acl = sc_file_get_acl_entry(file, ac_op);
418
0
  sc_log(ctx, "Fix access rule(op:%i;mode:%i) with ACL(method:%X,ref:%X)",
419
0
      ac_op, rule_mode, acl->method, acl->key_ref);
420
0
  if (acl->method == SC_AC_NEVER)   {
421
0
    sc_log(ctx, "ignore access rule(op:%i,mode:%i)", ac_op, rule_mode);
422
0
  }
423
0
  else if (acl->method == SC_AC_NONE)   {
424
0
    rv = authentic_pkcs15_add_access_rule(object, rule_mode, NULL);
425
0
    LOG_TEST_RET(ctx, rv, "Fix file access rule error");
426
0
  }
427
0
  else   {
428
0
    sc_log(ctx, "ACL(method:%X,ref:%X)", acl->method, acl->key_ref);
429
0
    if (acl->method == SC_AC_CHV)   {
430
0
      ref = acl->key_ref;
431
0
      authentic_reference_to_pkcs15_id (ref, &id);
432
0
    }
433
0
    else   {
434
0
      LOG_TEST_RET(ctx, SC_ERROR_UNKNOWN_DATA_RECEIVED, "Fix file access error");
435
0
    }
436
437
0
    sc_log(ctx, "ACL(method:%X,ref:%X)", acl->method, acl->key_ref);
438
0
    rv = authentic_pkcs15_add_access_rule(object, rule_mode, &id);
439
0
    sc_log(ctx, "rv %i", rv);
440
0
    LOG_TEST_RET(ctx, rv, "Fix file access rule error");
441
0
  }
442
443
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
444
0
}
445
446
447
static int
448
authentic_pkcs15_fix_access(struct sc_pkcs15_card *p15card, struct sc_file *file,
449
    struct sc_pkcs15_object *object)
450
0
{
451
0
  struct sc_context *ctx = p15card->card->ctx;
452
0
  int rv, ii;
453
454
0
  LOG_FUNC_CALLED(ctx);
455
0
  sc_log(ctx, "authID %s", sc_pkcs15_print_id(&object->auth_id));
456
457
0
  memset(object->access_rules, 0, sizeof(object->access_rules));
458
459
0
  for (ii=0; authentic_v3_rsa_map_attributes[ii].access_rule; ii++)   {
460
0
    rv = authentic_pkcs15_fix_file_access_rule(p15card, file,
461
0
        authentic_v3_rsa_map_attributes[ii].ac_op,
462
0
        authentic_v3_rsa_map_attributes[ii].access_rule,
463
0
        object);
464
0
    LOG_TEST_RET(ctx, rv, "Fix file READ access error");
465
0
  }
466
467
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
468
0
}
469
470
471
static int
472
authentic_pkcs15_fix_usage(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *object)
473
0
{
474
0
  struct sc_context *ctx = p15card->card->ctx;
475
0
  int ii, jj;
476
477
0
  LOG_FUNC_CALLED(ctx);
478
0
  if (object->type == SC_PKCS15_TYPE_PRKEY_RSA)   {
479
0
    struct sc_pkcs15_prkey_info *prkey_info = (struct sc_pkcs15_prkey_info *) object->data;
480
481
0
    sc_log(ctx, "fix private key usage 0x%X", prkey_info->usage);
482
0
          for (ii=0;ii<SC_PKCS15_MAX_ACCESS_RULES;ii++)   {
483
0
      if (!object->access_rules[ii].access_mode)
484
0
        break;
485
486
0
      for (jj=0; authentic_v3_rsa_map_attributes[jj].access_rule; jj++)
487
0
        if (authentic_v3_rsa_map_attributes[jj].access_rule & object->access_rules[ii].access_mode)
488
0
          prkey_info->usage |= authentic_v3_rsa_map_attributes[jj].usage;
489
0
    }
490
0
    sc_log(ctx, "fixed private key usage 0x%X", prkey_info->usage);
491
0
  }
492
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
493
0
}
494
495
496
static void
497
authentic_free_sdo_data(struct sc_authentic_sdo *sdo)
498
0
{
499
0
  int rsa_mechs_num = sizeof(authentic_v3_rsa_mechs)/sizeof(authentic_v3_rsa_mechs[0]);
500
0
  int ii;
501
502
0
  if (!sdo)
503
0
    return;
504
505
0
  sc_file_free(sdo->file);
506
507
0
  for (ii=0; ii<rsa_mechs_num; ii++)
508
0
    if (sdo->docp.mech == authentic_v3_rsa_mechs[ii])
509
0
      break;
510
0
  if (ii<rsa_mechs_num)
511
0
    sc_pkcs15_free_prkey(sdo->data.prvkey);
512
0
}
513
514
515
static int
516
authentic_pkcs15_create_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
517
          struct sc_pkcs15_object *object)
518
0
{
519
0
  struct sc_card *card = p15card->card;
520
0
  struct sc_context *ctx = card->ctx;
521
0
  struct sc_authentic_sdo *sdo = NULL;
522
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
523
0
  struct sc_file  *file_p_prvkey = NULL, *parent = NULL;
524
0
  size_t keybits = key_info->modulus_length;
525
0
  int  rv;
526
527
0
  LOG_FUNC_CALLED(ctx);
528
0
  sc_log(ctx,
529
0
         "create private key(keybits:%"SC_FORMAT_LEN_SIZE_T"u,usage:%X,access:%X,ref:%X)",
530
0
         keybits, key_info->usage, key_info->access_flags,
531
0
         key_info->key_reference);
532
0
  if (keybits < 1024 || keybits > 2048 || (keybits % 256))
533
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
534
535
0
  rv = authentic_pkcs15_new_file(profile, card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file_p_prvkey);
536
0
  LOG_TEST_RET(ctx, rv, "IasEcc pkcs15 new PRKEY_RSA file error");
537
538
0
  key_info->key_reference |= AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
539
540
0
  rv = sc_select_file(card, &file_p_prvkey->path, &parent);
541
0
  if (rv != SC_SUCCESS)
542
0
    sc_file_free(file_p_prvkey);
543
0
  LOG_TEST_RET(ctx, rv, "DF for the private objects not defined");
544
545
0
  rv = sc_pkcs15init_authenticate(profile, p15card, parent, SC_AC_OP_CRYPTO);
546
0
  sc_file_free(parent);
547
0
  if (rv != SC_SUCCESS)
548
0
    sc_file_free(file_p_prvkey);
549
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_CRYPTO authentication failed for parent DF");
550
551
0
  key_info->access_flags = SC_PKCS15_PRKEY_ACCESS_NEVEREXTRACTABLE
552
0
    | SC_PKCS15_PRKEY_ACCESS_ALWAYSSENSITIVE
553
0
    | SC_PKCS15_PRKEY_ACCESS_SENSITIVE;
554
555
0
  rv = authentic_sdo_allocate_prvkey(profile, card, key_info, &sdo);
556
0
  if (rv != SC_SUCCESS || sdo == NULL) {
557
0
    sc_log(ctx, "IasEcc: init SDO private key failed");
558
0
    sc_file_free(file_p_prvkey);
559
0
    LOG_FUNC_RETURN(ctx, rv);
560
0
  }
561
562
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_CREATE, sdo);
563
0
  if (rv == SC_ERROR_FILE_ALREADY_EXISTS)   {
564
0
    unsigned long caps = p15card->card->caps;
565
566
0
    p15card->card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
567
0
    rv = sc_pkcs15init_authenticate(profile, p15card, file_p_prvkey, SC_AC_OP_DELETE);
568
0
    p15card->card->caps = caps;
569
0
    LOG_TEST_GOTO_ERR(ctx, rv, "SC_AC_OP_CRYPTO authentication failed for parent DF");
570
571
0
    rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_DELETE, sdo);
572
0
    LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key");
573
574
0
    rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_CREATE, sdo);
575
0
  }
576
0
  LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_CREATE failed");
577
578
0
  rv = authentic_pkcs15_fix_access(p15card, file_p_prvkey, object);
579
0
  LOG_TEST_GOTO_ERR(ctx, rv, "cannot fix access rules for private key");
580
581
0
  rv = authentic_pkcs15_fix_usage(p15card, object);
582
0
  LOG_TEST_GOTO_ERR(ctx, rv, "cannot fix access rules for private key");
583
584
  /* Here fix the key's supported algorithms, if these ones will be implemented
585
   * (see src/libopensc/pkcs15-prkey.c).
586
   */
587
588
0
  sdo->file = file_p_prvkey;
589
0
  sc_log(ctx, "sdo->file:%p", sdo->file);
590
591
0
  rv = sc_pkcs15_allocate_object_content(ctx, object, (unsigned char *)sdo, sizeof(struct sc_authentic_sdo));
592
0
  LOG_TEST_GOTO_ERR(ctx, rv, "Failed to allocate PrvKey SDO as object content");
593
594
0
err:
595
0
  if (sdo == NULL || sdo->file != file_p_prvkey)
596
0
    sc_file_free(file_p_prvkey);
597
0
  authentic_free_sdo_data(sdo);
598
0
  free(sdo);
599
0
  LOG_FUNC_RETURN(ctx, rv);
600
0
}
601
602
603
/*
604
 * RSA key generation
605
 */
606
static int
607
authentic_pkcs15_generate_key(struct sc_profile *profile, sc_pkcs15_card_t *p15card,
608
    struct sc_pkcs15_object *object, struct sc_pkcs15_pubkey *pubkey)
609
0
{
610
0
  struct sc_card *card = p15card->card;
611
0
  struct sc_context *ctx = card->ctx;
612
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
613
0
  size_t keybits = key_info->modulus_length;
614
0
  struct sc_authentic_sdo *sdo = NULL;
615
0
  unsigned char *tmp = NULL;
616
0
  size_t tmp_len;
617
0
  unsigned long caps;
618
0
  int rv;
619
620
0
  LOG_FUNC_CALLED(ctx);
621
0
  sc_log(ctx,
622
0
         "generate key(bits:%"SC_FORMAT_LEN_SIZE_T"u,path:%s,AuthID:%s\n",
623
0
         keybits, sc_print_path(&key_info->path),
624
0
         sc_pkcs15_print_id(&object->auth_id));
625
626
0
  if (!object->content.value || object->content.len != sizeof(struct sc_authentic_sdo))
627
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid PrKey SDO data");
628
0
  else if (keybits < 1024 || keybits > 2048 || (keybits % 256))
629
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
630
631
0
  sdo = (struct sc_authentic_sdo *)object->content.value;
632
0
  if (sdo->magic != AUTHENTIC_SDO_MAGIC)
633
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "'Magic' control failed for SDO PrvKey");
634
635
0
  rv = sc_select_file(card, &key_info->path, NULL);
636
0
  LOG_TEST_RET(ctx, rv, "failed to select parent DF");
637
638
0
  caps = card->caps;
639
0
  card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
640
0
  rv = sc_pkcs15init_authenticate(profile, p15card, sdo->file, SC_AC_OP_GENERATE);
641
0
  card->caps = caps;
642
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_GENERATE authentication failed");
643
644
0
  key_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_LOCAL;
645
646
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_GENERATE, sdo);
647
0
  LOG_TEST_RET(ctx, rv, "generate key failed");
648
649
0
  pubkey->algorithm = SC_ALGORITHM_RSA;
650
  //FIXME: allocate/copy/free to reduce memory leakage
651
0
  pubkey->u.rsa.modulus = sdo->data.prvkey->u.rsa.modulus;
652
0
  pubkey->u.rsa.exponent = sdo->data.prvkey->u.rsa.exponent;
653
0
  sdo->data.prvkey = NULL;
654
655
0
  rv = sc_pkcs15_encode_pubkey(ctx, pubkey, &tmp, &tmp_len);
656
0
  LOG_TEST_RET(ctx, rv, "encode public key failed");
657
658
  /*
659
   * Here algorithms supported by key have to be fixed, if it will be implemented
660
   * (see src/libopensc/pkcs15-prkey.c).
661
   */
662
663
0
  authentic_free_sdo_data(sdo);
664
665
0
  rv = sc_pkcs15_allocate_object_content(ctx, object, tmp, tmp_len);
666
0
  LOG_TEST_RET(ctx, rv, "Failed to allocate public key as object content");
667
668
0
  free(tmp);
669
0
  LOG_FUNC_RETURN(ctx, rv);
670
0
}
671
672
673
/*
674
 * Store a private key
675
 */
676
static int
677
authentic_pkcs15_store_key(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
678
    struct sc_pkcs15_object *object, struct sc_pkcs15_prkey *prvkey)
679
0
{
680
0
  struct sc_card *card = p15card->card;
681
0
  struct sc_context *ctx = card->ctx;
682
0
  struct sc_pkcs15_prkey_info *key_info = (struct sc_pkcs15_prkey_info *) object->data;
683
0
  size_t keybits = key_info->modulus_length;
684
0
  struct sc_authentic_sdo *sdo;
685
0
  int rv;
686
687
0
  LOG_FUNC_CALLED(ctx);
688
0
  sc_log(ctx,
689
0
         "Store IAS/ECC key(keybits:%"SC_FORMAT_LEN_SIZE_T"u,AuthID:%s,path:%s)",
690
0
         keybits, sc_pkcs15_print_id(&object->auth_id),
691
0
         sc_print_path(&key_info->path));
692
693
0
  if (!object->content.value || object->content.len != sizeof(struct sc_authentic_sdo))
694
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "Invalid PrKey SDO data");
695
0
  else if (keybits < 1024 || keybits > 2048 || (keybits % 256))
696
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ARGUMENTS, "Invalid RSA key size");
697
698
0
  key_info->access_flags &= ~SC_PKCS15_PRKEY_ACCESS_LOCAL;
699
700
0
  sdo = (struct sc_authentic_sdo *)object->content.value;
701
0
  if (sdo->magic != AUTHENTIC_SDO_MAGIC)
702
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_DATA, "'Magic' control failed for SDO PrvKey");
703
704
0
  rv = sc_select_file(card, &key_info->path, NULL);
705
0
  LOG_TEST_RET(ctx, rv, "failed to select parent DF");
706
707
0
  sdo->data.prvkey = prvkey;
708
709
0
  sc_log(ctx, "sdo(mech:%X,id:%X,acls:%s)", sdo->docp.mech, sdo->docp.id,
710
0
      sc_dump_hex(sdo->docp.acl_data, sdo->docp.acl_data_len));
711
712
0
  card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
713
0
  rv = sc_pkcs15init_authenticate(profile, p15card, sdo->file, SC_AC_OP_UPDATE);
714
0
  LOG_TEST_RET(ctx, rv, "SC_AC_OP_GENERATE authentication failed");
715
716
0
  rv = sc_card_ctl(card, SC_CARDCTL_AUTHENTIC_SDO_STORE, sdo);
717
0
  LOG_TEST_RET(ctx, rv, "store IAS SDO PRIVATE KEY failed");
718
719
0
  authentic_free_sdo_data(sdo);
720
0
  sc_pkcs15_free_object_content(object);
721
722
0
  LOG_FUNC_RETURN(ctx, rv);
723
0
}
724
725
726
static int
727
authentic_pkcs15_delete_rsa_sdo (struct sc_profile *profile, struct sc_pkcs15_card *p15card,
728
    struct sc_pkcs15_prkey_info *key_info)
729
0
{
730
0
  struct sc_context *ctx = p15card->card->ctx;
731
0
  unsigned long caps = p15card->card->caps;
732
0
  struct sc_authentic_sdo sdo;
733
0
  struct sc_file  *file = NULL;
734
0
  int rv;
735
736
0
  LOG_FUNC_CALLED(ctx);
737
0
  sc_log(ctx, "delete SDO RSA key (ref:%i,size:%"SC_FORMAT_LEN_SIZE_T"u)",
738
0
         key_info->key_reference, key_info->modulus_length);
739
740
0
  rv = authentic_pkcs15_new_file(profile, p15card->card, SC_PKCS15_TYPE_PRKEY_RSA, key_info->key_reference, &file);
741
0
  LOG_TEST_GOTO_ERR(ctx, rv, "PRKEY_RSA instantiation file error");
742
743
0
  p15card->card->caps &= ~SC_CARD_CAP_USE_FCI_AC;
744
0
  rv = sc_pkcs15init_authenticate(profile, p15card, file, SC_AC_OP_DELETE);
745
0
  p15card->card->caps = caps;
746
0
  LOG_TEST_GOTO_ERR(ctx, rv, "'DELETE' authentication failed for parent RSA key");
747
748
0
  sdo.magic = AUTHENTIC_SDO_MAGIC;
749
0
  sdo.docp.id = key_info->key_reference & ~AUTHENTIC_OBJECT_REF_FLAG_LOCAL;
750
0
  sdo.docp.mech = authentic_v3_rsa_mechs[(key_info->modulus_length - 1024) / 256];
751
752
0
  rv = sc_card_ctl(p15card->card, SC_CARDCTL_AUTHENTIC_SDO_DELETE, &sdo);
753
0
  if (rv == SC_ERROR_DATA_OBJECT_NOT_FOUND)
754
0
    rv = SC_SUCCESS;
755
0
  LOG_TEST_GOTO_ERR(ctx, rv, "SC_CARDCTL_AUTHENTIC_SDO_DELETE failed for private key");
756
757
0
err:
758
0
  sc_file_free(file);
759
0
  LOG_FUNC_RETURN(ctx, rv);
760
0
}
761
762
763
static int
764
authentic_pkcs15_delete_object (struct sc_profile *profile, struct sc_pkcs15_card *p15card,
765
    struct sc_pkcs15_object *object, const struct sc_path *path)
766
0
{
767
0
  struct sc_context *ctx = p15card->card->ctx;
768
0
  int rv;
769
770
0
  LOG_FUNC_CALLED(ctx);
771
0
  sc_log(ctx, "delete PKCS15 object: type %X; path %s\n", object->type, sc_print_path(path));
772
773
0
  switch(object->type & SC_PKCS15_TYPE_CLASS_MASK)   {
774
0
  case SC_PKCS15_TYPE_PRKEY:
775
0
    rv = authentic_pkcs15_delete_rsa_sdo (profile, p15card, (struct sc_pkcs15_prkey_info *)object->data);
776
0
    LOG_FUNC_RETURN(ctx, rv);
777
0
  case SC_PKCS15_TYPE_PUBKEY:
778
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
779
0
  default:
780
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_NOT_SUPPORTED);
781
0
  }
782
783
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
784
0
}
785
786
787
static int
788
authentic_store_pubkey(struct sc_pkcs15_card *p15card, struct sc_profile *profile, struct sc_pkcs15_object *object,
789
    struct sc_pkcs15_der *data, struct sc_path *path)
790
0
{
791
0
  struct sc_context *ctx = p15card->card->ctx;
792
0
  struct sc_pkcs15_pubkey_info *pubkey_info = (struct sc_pkcs15_pubkey_info *)object->data;
793
0
  struct sc_pkcs15_prkey_info *prkey_info = NULL;
794
0
  struct sc_pkcs15_object *prkey_object = NULL;
795
0
  int rv;
796
797
0
  LOG_FUNC_CALLED(ctx);
798
0
  sc_log(ctx, "Public Key id '%s'", sc_pkcs15_print_id(&pubkey_info->id));
799
800
0
  rv = sc_pkcs15_find_prkey_by_id(p15card, &pubkey_info->id, &prkey_object);
801
0
  LOG_TEST_RET(ctx, rv, "Find related PrKey error");
802
803
0
  prkey_info = (struct sc_pkcs15_prkey_info *)prkey_object->data;
804
805
0
  pubkey_info->key_reference = prkey_info->key_reference;
806
807
0
  pubkey_info->access_flags = prkey_info->access_flags & SC_PKCS15_PRKEY_ACCESS_LOCAL;
808
0
  pubkey_info->access_flags |= SC_PKCS15_PRKEY_ACCESS_EXTRACTABLE;
809
810
0
  pubkey_info->native = 0;
811
812
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_SIGN ? SC_PKCS15_PRKEY_USAGE_VERIFY : 0;
813
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_SIGNRECOVER ? SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER : 0;
814
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_NONREPUDIATION ? SC_PKCS15_PRKEY_USAGE_VERIFY : 0;
815
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_DECRYPT ? SC_PKCS15_PRKEY_USAGE_ENCRYPT : 0;
816
0
  pubkey_info->usage |= prkey_info->usage & SC_PKCS15_PRKEY_USAGE_UNWRAP ? SC_PKCS15_PRKEY_USAGE_WRAP : 0;
817
818
0
  authentic_pkcs15_add_access_rule(object, SC_PKCS15_ACCESS_RULE_MODE_READ, NULL);
819
820
  /* Here, if key supported algorithms will be implemented (see src/libopensc/pkcs15-prkey.c),
821
   * copy private key supported algorithms to the public key's ones.
822
   */
823
824
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
825
0
}
826
827
828
static int
829
authentic_emu_store_data(struct sc_pkcs15_card *p15card, struct sc_profile *profile,
830
    struct sc_pkcs15_object *object,
831
    struct sc_pkcs15_der *data, struct sc_path *path)
832
833
0
{
834
0
  struct sc_context *ctx = p15card->card->ctx;
835
0
  int rv = SC_ERROR_NOT_IMPLEMENTED;
836
837
0
  LOG_FUNC_CALLED(ctx);
838
839
0
  switch (object->type & SC_PKCS15_TYPE_CLASS_MASK) {
840
0
  case SC_PKCS15_TYPE_PUBKEY:
841
0
    rv = authentic_store_pubkey(p15card, profile, object, data, path);
842
0
    break;
843
0
  }
844
845
0
  LOG_FUNC_RETURN(ctx, rv);
846
0
}
847
848
849
static int
850
authentic_emu_update_tokeninfo(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
851
    struct sc_pkcs15_tokeninfo *tinfo)
852
0
{
853
0
  struct sc_context *ctx = p15card->card->ctx;
854
0
  struct sc_file *file = NULL;
855
0
  struct sc_path path;
856
0
  unsigned char buffer[8];
857
0
  int rv;
858
0
  size_t len;
859
860
0
  sc_format_path(AUTHENTIC_CACHE_TIMESTAMP_PATH, &path);
861
0
  rv = sc_select_file(p15card->card, &path, &file);
862
0
  if (!rv) {
863
0
    rv = sc_get_challenge(p15card->card, buffer, sizeof(buffer));
864
0
    if (rv < 0) {
865
0
      sc_file_free(file);
866
0
      LOG_TEST_RET(ctx, rv, "Get challenge error");
867
0
    }
868
869
0
    len = file->size > sizeof(buffer) ? sizeof(buffer) : file->size;
870
0
    rv = sc_update_binary(p15card->card, 0, buffer, len, 0);
871
0
    sc_file_free(file);
872
0
    LOG_TEST_RET(ctx, rv, "Update binary error");
873
0
  }
874
875
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
876
0
}
877
878
static int
879
authentic_pkcs15_init_card(struct sc_profile *profile, struct sc_pkcs15_card *p15card)
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_dir(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
887
    struct sc_file *df)
888
0
{
889
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
890
0
}
891
892
893
static int
894
authentic_pkcs15_create_pin(struct sc_profile *profile, struct sc_pkcs15_card *p15card,
895
    struct sc_file *df, struct sc_pkcs15_object *pin_obj,
896
    const unsigned char *pin, size_t pin_len,
897
    const unsigned char *puk, size_t puk_len)
898
0
{
899
0
  LOG_FUNC_RETURN(p15card->card->ctx, SC_ERROR_NOT_SUPPORTED);
900
0
}
901
902
903
static struct sc_pkcs15init_operations
904
sc_pkcs15init_authentic_operations = {
905
  authentic_pkcs15_erase_card,
906
  authentic_pkcs15_init_card,
907
  authentic_pkcs15_create_dir,
908
  NULL,         /* create_domain */
909
  NULL,         /* select_pin_reference */
910
  authentic_pkcs15_create_pin,
911
  authentic_pkcs15_select_key_reference,
912
  authentic_pkcs15_create_key,
913
  authentic_pkcs15_store_key,
914
  authentic_pkcs15_generate_key,
915
  NULL,         /* encode private key */
916
  NULL,         /* encode public key */
917
  NULL,         /* finalize_card */
918
  authentic_pkcs15_delete_object,
919
920
  /* pkcs15init emulation */
921
  NULL,
922
  NULL,
923
  authentic_emu_update_tokeninfo,
924
  NULL,
925
  authentic_emu_store_data,
926
927
  NULL,         /* sanity_check */
928
};
929
930
931
struct sc_pkcs15init_operations *
932
sc_pkcs15init_get_authentic_ops(void)
933
0
{
934
0
  return &sc_pkcs15init_authentic_operations;
935
0
}
936
937
#endif /* ENABLE_OPENSSL */